From 4fdb36ae7ce1917025d6fb554458ebb6bc85451c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Mar 2022 14:43:50 +0200 Subject: [PATCH 0001/1892] Update index.rst Added a line of text to test search feature. --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index e1455f21a..26b7459ec 100644 --- a/index.rst +++ b/index.rst @@ -4,7 +4,7 @@ SQream DB Documentation ************************* -For SQream version 2021.2. +The **2022.3 Preview** branch is a private branch designed for internal use only. .. only:: html From 94440c79ec952f53dde1dff744367a3d4eb974d2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 20 Mar 2022 16:31:25 +0200 Subject: [PATCH 0002/1892] Started Creating Data Encryption Page --- feature_guides/data_encryption.rst | 115 +++++++++++++++++++++++++++++ feature_guides/index.rst | 1 + 2 files changed, 116 insertions(+) create mode 100644 feature_guides/data_encryption.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst new file mode 100644 index 000000000..02bdf2cea --- /dev/null +++ b/feature_guides/data_encryption.rst @@ -0,0 +1,115 @@ +.. _data_encryption: + +*********************** +Data Encryption +*********************** +The **Data Encryption** page: + +.. contents:: + :local: + :depth: 1 + +Overview +============== +Encryption functionality is an increasing growing demands from customers and new projects prospects (see Customers Specific Requirements section for more information), the functionality manifests in all sorts of ways as seen in the below section (implementation option) and the reason for it to be very important to customers is due to market strive to comply to the GDPR compliance regulations as it shows in the GDPR Compliance section. + +The encryption demand is growing around the world as it can be inserted to our sales pitch to promote vendors which security features is very important for them + +Column/Table-level encryption - More granular approach, encrypt only what you really need to + +Syntax +============== +The following is the correct syntax for encrypting a new table: + +.. code-block:: console + + CREATE TABLE client_name ( + first_name TEXT(128), + last_name TEXT(128), + salary INT(6) ENCRYPT); + +The following is the correct syntax for decrypting a new table: + +.. code-block:: console + + SELECT * FROM TABLE; + +The following is an example of encrypting a new table: + +.. code-block:: console + + EXAMPLE + +The following is an example of decryping a new table: + +.. code-block:: console + + EXAMPLE + +Encrypting Data in Transit +============== + +Encrypting Data at Rest +============== + +Data Types +============== + +How Encryption Works +============== +The **How Encryption Works** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Encryption +---------------- + + + +Decryption +---------------- + + + +Encrypted Columns +---------------- + + + +Constraints +---------------- +Describe these in one of the existing sections. + + + +Use Case Considerations +============== +Include the relevant content from this section in the correct places in this document. + + + +Permissions +============== + + + +Usage Notes +============== +Include the relevant content from this section in the correct places in this document. + + + + + + + +Security Encryption available in one column. +Is there a flag associated with this feature? +There already is a Security page. Are we overriding it? +Give the big picture in the Overview. +Show Inon the before/after example. +Minimum Viable Product MVP +Permissions section - external +Deadline: two weeks minimum \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index a0a996fc8..c5f472785 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,6 +12,7 @@ This section describes the following features: :titlesonly: delete_guide + data_encryption compression flexible_data_clustering python_functions From 93b019432b2e557c7c9200b15bcb6bbbea69ae5f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 21 Mar 2022 09:34:34 +0200 Subject: [PATCH 0003/1892] Update data_encryption.rst --- feature_guides/data_encryption.rst | 78 ++++++++++++++++-------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 02bdf2cea..e3e1af5f3 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -3,23 +3,53 @@ *********************** Data Encryption *********************** -The **Data Encryption** page: + +The **Data Encryption** page describes the following: .. contents:: :local: :depth: 1 - + + Overview ============== -Encryption functionality is an increasing growing demands from customers and new projects prospects (see Customers Specific Requirements section for more information), the functionality manifests in all sorts of ways as seen in the below section (implementation option) and the reason for it to be very important to customers is due to market strive to comply to the GDPR compliance regulations as it shows in the GDPR Compliance section. +**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. -The encryption demand is growing around the world as it can be inserted to our sales pitch to promote vendors which security features is very important for them +For more information on GDPR compliance requirements, see the `GDPR checklist `_. Column/Table-level encryption - More granular approach, encrypt only what you really need to + + +Encryption Methods +============== +The **Encryption Methods** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Encrypting Data in Transit +---------------- +**In-transit data** refers to data files inserted from customer repositories using the COPY FROM command, and is transmitted to SQream over a TLS-encrypted channel using a JDBC or ODBC connection. + +For more information, see the following: + +* :ref:`copy_from` +* :ref:`jdbc` +* :ref:`odbc` + +Encrypting Data at Rest +---------------- + +Data Types +============== + Syntax ============== -The following is the correct syntax for encrypting a new table: +The following is the correct syntax for **encrypting** a new table: .. code-block:: console @@ -27,33 +57,24 @@ The following is the correct syntax for encrypting a new table: first_name TEXT(128), last_name TEXT(128), salary INT(6) ENCRYPT); - -The following is the correct syntax for decrypting a new table: - -.. code-block:: console - - SELECT * FROM TABLE; - + The following is an example of encrypting a new table: .. code-block:: console EXAMPLE - -The following is an example of decryping a new table: + +The following is the correct syntax for **decrypting** a new table: .. code-block:: console - - EXAMPLE -Encrypting Data in Transit -============== + SELECT * FROM TABLE; -Encrypting Data at Rest -============== +The following is an example of decrypting a new table: -Data Types -============== +.. code-block:: console + + EXAMPLE How Encryption Works ============== @@ -100,16 +121,3 @@ Usage Notes Include the relevant content from this section in the correct places in this document. - - - - - -Security Encryption available in one column. -Is there a flag associated with this feature? -There already is a Security page. Are we overriding it? -Give the big picture in the Overview. -Show Inon the before/after example. -Minimum Viable Product MVP -Permissions section - external -Deadline: two weeks minimum \ No newline at end of file From a9e050e7d935f55a00cb385a732b9d655168bacd Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 21 Mar 2022 09:58:12 +0200 Subject: [PATCH 0004/1892] Created Data Encryption Folder Separate page for each section. --- feature_guides/data_encryption.rst | 123 ------------------ .../data_encryption/data_encryption.rst | 18 +++ .../data_encryption/data_encryption_flow.rst | 32 +++++ .../data_encryption_methods.rst | 23 ++++ .../data_encryption_overview.rst | 10 ++ .../data_encryption_syntax.rst | 44 +++++++ .../data_encryption/data_encryption_types.rst | 16 +++ .../data_encryption_use_cases.rst | 14 ++ 8 files changed, 157 insertions(+), 123 deletions(-) delete mode 100644 feature_guides/data_encryption.rst create mode 100644 feature_guides/data_encryption/data_encryption.rst create mode 100644 feature_guides/data_encryption/data_encryption_flow.rst create mode 100644 feature_guides/data_encryption/data_encryption_methods.rst create mode 100644 feature_guides/data_encryption/data_encryption_overview.rst create mode 100644 feature_guides/data_encryption/data_encryption_syntax.rst create mode 100644 feature_guides/data_encryption/data_encryption_types.rst create mode 100644 feature_guides/data_encryption/data_encryption_use_cases.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst deleted file mode 100644 index e3e1af5f3..000000000 --- a/feature_guides/data_encryption.rst +++ /dev/null @@ -1,123 +0,0 @@ -.. _data_encryption: - -*********************** -Data Encryption -*********************** - -The **Data Encryption** page describes the following: - -.. contents:: - :local: - :depth: 1 - - -Overview -============== -**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. - -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. - -For more information on GDPR compliance requirements, see the `GDPR checklist `_. - -Column/Table-level encryption - More granular approach, encrypt only what you really need to - - - -Encryption Methods -============== -The **Encryption Methods** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Encrypting Data in Transit ----------------- -**In-transit data** refers to data files inserted from customer repositories using the COPY FROM command, and is transmitted to SQream over a TLS-encrypted channel using a JDBC or ODBC connection. - -For more information, see the following: - -* :ref:`copy_from` -* :ref:`jdbc` -* :ref:`odbc` - -Encrypting Data at Rest ----------------- - -Data Types -============== - -Syntax -============== -The following is the correct syntax for **encrypting** a new table: - -.. code-block:: console - - CREATE TABLE client_name ( - first_name TEXT(128), - last_name TEXT(128), - salary INT(6) ENCRYPT); - -The following is an example of encrypting a new table: - -.. code-block:: console - - EXAMPLE - -The following is the correct syntax for **decrypting** a new table: - -.. code-block:: console - - SELECT * FROM TABLE; - -The following is an example of decrypting a new table: - -.. code-block:: console - - EXAMPLE - -How Encryption Works -============== -The **How Encryption Works** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Encryption ----------------- - - - -Decryption ----------------- - - - -Encrypted Columns ----------------- - - - -Constraints ----------------- -Describe these in one of the existing sections. - - - -Use Case Considerations -============== -Include the relevant content from this section in the correct places in this document. - - - -Permissions -============== - - - -Usage Notes -============== -Include the relevant content from this section in the correct places in this document. - - diff --git a/feature_guides/data_encryption/data_encryption.rst b/feature_guides/data_encryption/data_encryption.rst new file mode 100644 index 000000000..e312e7fff --- /dev/null +++ b/feature_guides/data_encryption/data_encryption.rst @@ -0,0 +1,18 @@ +.. _data_encryption: + +*********************** +Data Encryption +*********************** + +The **Data Encryption** page describes the following: + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + data_encryption_overview + data_encryption_methods + data_encryption_types + data_encryption_syntax + data_encryption_flow + data_encryption_use_cases \ No newline at end of file diff --git a/feature_guides/data_encryption/data_encryption_flow.rst b/feature_guides/data_encryption/data_encryption_flow.rst new file mode 100644 index 000000000..f65b1d240 --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_flow.rst @@ -0,0 +1,32 @@ +.. _data_encryption_flow: + +*********************** +Data Encryption Flow +*********************** +The **Data Encryption Flow** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Encryption +---------------- + + + +Decryption +---------------- + + + +Encrypted Columns +---------------- +Column/Table-level encryption - More granular approach, encrypt only what you really need to + + + + +Constraints +---------------- +Describe these in one of the existing sections. + diff --git a/feature_guides/data_encryption/data_encryption_methods.rst b/feature_guides/data_encryption/data_encryption_methods.rst new file mode 100644 index 000000000..031f263b3 --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_methods.rst @@ -0,0 +1,23 @@ +.. _data_encryption_methods: + +*********************** +Encryption Methods +*********************** +The **Encryption Methods** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Encrypting Data in Transit +---------------- +**In-transit data** refers to data files inserted from customer repositories using the COPY FROM command, and is transmitted to SQream over a TLS-encrypted channel using a JDBC or ODBC connection. + +For more information, see the following: + +* :ref:`copy_from` +* :ref:`jdbc` +* :ref:`odbc` + +Encrypting Data at Rest +---------------- diff --git a/feature_guides/data_encryption/data_encryption_overview.rst b/feature_guides/data_encryption/data_encryption_overview.rst new file mode 100644 index 000000000..5b3f3e344 --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_overview.rst @@ -0,0 +1,10 @@ +.. _data_encryption_overview: + +*********************** +Overview +*********************** +**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. + +For more information on GDPR compliance requirements, see the `GDPR checklist `_. \ No newline at end of file diff --git a/feature_guides/data_encryption/data_encryption_syntax.rst b/feature_guides/data_encryption/data_encryption_syntax.rst new file mode 100644 index 000000000..8df3e0d33 --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_syntax.rst @@ -0,0 +1,44 @@ +.. _data_encryption_syntax: + +*********************** +Syntax +*********************** + +The **Syntax** page describes the following: + +.. contents:: + :local: + :depth: 1 + +The following is the correct syntax for **encrypting** a new table: + +.. code-block:: console + + CREATE TABLE client_name ( + first_name TEXT(128), + last_name TEXT(128), + salary INT(6) ENCRYPT); + +The following is an example of encrypting a new table: + +.. code-block:: console + + EXAMPLE + +The following is the correct syntax for **decrypting** a new table: + +.. code-block:: console + + SELECT * FROM TABLE; + +The following is an example of decrypting a new table: + +.. code-block:: console + + EXAMPLE + +Usage notes - this should be included on this page. + +When inputting the wrong master key/location in encryption/decryption an error should be raised to the user + +The master key needs to be masked in logs to protect user privacy, the responsibility maintaining the master key for the remote repository is on the user side \ No newline at end of file diff --git a/feature_guides/data_encryption/data_encryption_types.rst b/feature_guides/data_encryption/data_encryption_types.rst new file mode 100644 index 000000000..331b14f58 --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_types.rst @@ -0,0 +1,16 @@ +.. _data_encryption_types: + +*********************** +Data Types +*********************** + + +Per the research done and per customer requirement the data types that should be supported are the following: + +Int + +BigInt + +String + +On most cases this data type, if encrypted, will be populated by PII value (Personal Identifiable Information) such as credit card number and other personal and sensitive information \ No newline at end of file diff --git a/feature_guides/data_encryption/data_encryption_use_cases.rst b/feature_guides/data_encryption/data_encryption_use_cases.rst new file mode 100644 index 000000000..9e9ddeb4a --- /dev/null +++ b/feature_guides/data_encryption/data_encryption_use_cases.rst @@ -0,0 +1,14 @@ +.. _data_encryption_use_cases: + +*********************** +Use Cases +*********************** + + + + + +Use Case Considerations +============== +Include the relevant content from this section in the correct places in this document. + From 8c9a1a4facaddd59b0f40a0a4a1544567a731409 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 21 Mar 2022 10:08:21 +0200 Subject: [PATCH 0005/1892] Updated Menu to include Data Encryption --- feature_guides/{data_encryption => }/data_encryption.rst | 0 feature_guides/{data_encryption => }/data_encryption_flow.rst | 0 feature_guides/{data_encryption => }/data_encryption_methods.rst | 0 feature_guides/{data_encryption => }/data_encryption_overview.rst | 0 feature_guides/{data_encryption => }/data_encryption_syntax.rst | 0 feature_guides/{data_encryption => }/data_encryption_types.rst | 0 .../{data_encryption => }/data_encryption_use_cases.rst | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename feature_guides/{data_encryption => }/data_encryption.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_flow.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_methods.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_overview.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_syntax.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_types.rst (100%) rename feature_guides/{data_encryption => }/data_encryption_use_cases.rst (100%) diff --git a/feature_guides/data_encryption/data_encryption.rst b/feature_guides/data_encryption.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption.rst rename to feature_guides/data_encryption.rst diff --git a/feature_guides/data_encryption/data_encryption_flow.rst b/feature_guides/data_encryption_flow.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_flow.rst rename to feature_guides/data_encryption_flow.rst diff --git a/feature_guides/data_encryption/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_methods.rst rename to feature_guides/data_encryption_methods.rst diff --git a/feature_guides/data_encryption/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_overview.rst rename to feature_guides/data_encryption_overview.rst diff --git a/feature_guides/data_encryption/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_syntax.rst rename to feature_guides/data_encryption_syntax.rst diff --git a/feature_guides/data_encryption/data_encryption_types.rst b/feature_guides/data_encryption_types.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_types.rst rename to feature_guides/data_encryption_types.rst diff --git a/feature_guides/data_encryption/data_encryption_use_cases.rst b/feature_guides/data_encryption_use_cases.rst similarity index 100% rename from feature_guides/data_encryption/data_encryption_use_cases.rst rename to feature_guides/data_encryption_use_cases.rst From cdbd5588263595ef3bb6b5e8276a05a2ffd4ebec Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 21 Mar 2022 14:06:16 +0200 Subject: [PATCH 0006/1892] Added Update --- reference/sql/sql_statements/index.rst | 4 + reference/sql/sql_statements/update.rst | 245 ++++++++++++++++++++++++ 2 files changed, 249 insertions(+) create mode 100644 reference/sql/sql_statements/update.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 955e1212f..e14041385 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -11,6 +11,8 @@ SQream DB supports commands from ANSI SQL. Data Definition Commands (DDL) ================================ + update + .. list-table:: DDL Commands :widths: auto :header-rows: 1 @@ -20,6 +22,8 @@ Data Definition Commands (DDL) - Usage * - :ref:`ADD COLUMN` - Add a new column to a table + * - :ref:`UPDATE` + - Modify the value of certain columns in existing rows without creating a table * - :ref:`ALTER DEFAULT SCHEMA` - Change the default schema for a role * - :ref:`ALTER TABLE` diff --git a/reference/sql/sql_statements/update.rst b/reference/sql/sql_statements/update.rst new file mode 100644 index 000000000..143363b3b --- /dev/null +++ b/reference/sql/sql_statements/update.rst @@ -0,0 +1,245 @@ +.. _update: + +********************** +UPDATE +********************** + +The **UPDATE** statement page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +========== +The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. + +It can be used to do the following: + +* Perform localized changes in existing data, such as correcting mistakes discovered after ingesting data. + +* Setting columns based on the values of others. + +Syntax +========== +The following is the correct syntax for the ``UPDATE`` command: + +.. code-block:: postgres + + UPDATE target_table_name [[AS] alias1] + SET column_name = expression [,...] + [FROM additional_table_name [[AS] alias2][,...]] + [WHERE condition] + +The following is the correct syntax for triggering a clean-up: + +.. code-block:: postgres + + SELECT cleanup_chunks('schema_name','table_name'); + SELECT cleanup_extents('schema_name','table_name'); + +**Comment** - *The cleanup example above is different than the one used on the DELETED page. Is this correct?* + +Parameters +============ +The following table describes the ``UPDATE`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``target_table_name`` + - Specifies the table containing the data to be updated. + * - ``column_name`` + - Specifies the column containing the data to be updated. + * - ``additional_table_name`` + - Additional tables used in the WHERE condition for performing complex joins. + * - ``condition`` + - Specifies the condition for updating the data. + +.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. + +Examples +=========== +The **Examples** section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Updating an Entire Table +----------------- +The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: + +.. image:: /_static/images/delete_optimization.png + +The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 WHERE true; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; + +Performing Simple Updates +----------------- +The following is an example of performing a simple update: + +.. code-block:: postgres + + UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; + +Updating Tables that Contain Multi-Table Conditions +----------------- +The following shows an example of updating tables that contain multi-table conditions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + 1 + WHERE EXISTS ( + SELECT 1 FROM countries + WHERE countries.id=bands.country_id + AND country.name = 'Sweden' + ); + +You can also write the statement above using the FROM clause: + +.. code-block:: psql + + UPDATE bands + SET records_sold = records_sold + 1 + FROM countries + WHERE countries.id=bands.country_id AND country.name = 'Sweden'; + +Updating Tables that Contain Multi-Table Expressions +----------------- +The following shows an example of updating tables that contain multi-table expressions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + + CASE + WHEN c.name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c + +Configuring Update Behavior +----------------- +The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. + +**Note to self** - *Check if the Studio documentation must be updated for this flag.* + +For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. + +When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). + +You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. + +**Comment** - *Does the system actually choose one, or does it generate an error?* + +Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: + +.. code-block:: postgres + + UPDATE bands + SET record_count = record_count + 1 + FROM countries c + WHERE c.name = 'Israel' + +However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. + +**Comment** - *Please review the paragraph above. I'm pretty sure I described this correctly.* + +For more information, see `SQream Acceleration Studio `_. + +Identifying and Cleaning Up Tables +--------------------------------------- +**Comment** - *I copied and pasted this entire section from "DELETE". Does anything have to adjusted here for "UPDATE"?* + +The following section shows examples of each phase required for cleaning up tables: + +* :ref:`Listing tables that require clean-up` +* :ref:`Identifying clean-up predicates` +* :ref:`Triggering a clean-up` + +.. _listing_tables_that_require_cleanup: + +Listing Tables that Require Clean-Up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing tables that require clean-up: + +.. code-block:: psql + + farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + GROUP BY 1; + cool_animals + + 1 row + +.. _identifying_cleanup_predicates: + +Identifying Clean-Up Predicates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing the clean-up predicates: + +.. code-block:: psql + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + weight > 1000 + + 1 row + +.. _triggering_a_cleanup: + +Triggering a Clean-Up +^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of triggering a clean-up: + +.. code-block:: psql + + -- Chunk reorganization (SWEEP) + farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); + executed + + -- Delete leftover files (VACUUM) + farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); + executed + + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + + 0 rows + +Permissions +============= +Executing an ``UPDATE`` statement requires the following permissions: + +* Both ``UPDATE`` and ``SELECT`` permissions on the target table. +* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). + +Locking and Concurrency +============= +Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file From fade107ea80f689f5a0d304f6438c9a7ad63d29f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 09:59:21 +0200 Subject: [PATCH 0007/1892] Updated for RN Release - Preview --- data_ingestion/avro.rst | 344 ++++++++++++++++++ data_ingestion/index.rst | 3 +- feature_guides/data_encryption_methods.rst | 2 +- feature_guides/index.rst | 2 +- .../{ => dml_commands}/update.rst | 0 reference/sql/sql_statements/index.rst | 6 +- releases/2022.1.rst | 104 ++++++ releases/index.rst | 5 +- 8 files changed, 458 insertions(+), 8 deletions(-) create mode 100644 data_ingestion/avro.rst rename reference/sql/sql_statements/{ => dml_commands}/update.rst (100%) create mode 100644 releases/2022.1.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst new file mode 100644 index 000000000..920b6d44b --- /dev/null +++ b/data_ingestion/avro.rst @@ -0,0 +1,344 @@ +.. _avro: + +************************** +Inserting Data from Avro +************************** +The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=========== +**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. + +Avro Data Types +=========== + +Avro includes the following data types: + +.. contents:: + :local: + :depth: 1 + +Primitive Data Types +-------------- +The following table shows the supported **Primitive** data types: + ++-------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++=============+========+===============+========+=========+ +| ``null`` | ✓ | ✓ | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``boolean`` | | | ✓ | ✓ | ++-------------+--------+---------------+--------+---------+ +| ``int`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``long`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``float`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``double`` | ✓ | | ✓ | | ++-------------+--------+---------------+--------+---------+ +| ``bytes`` | | | | | ++-------------+--------+---------------+--------+---------+ +| ``string`` | | ✓ | ✓ | | ++-------------+--------+---------------+--------+---------+ + + + + + + +Complex Data Types +-------------- +The following table shows the supported **Complex** data types: + ++------------+-------------------------------------------+ +| | SQream Type | +| +--------+---------------+--------+---------+ +|Avro Type | Number | Date/Datetime | String | Boolean | ++============+========+===============+========+=========+ +| ``record`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``enum`` | | | ✓ | | ++------------+--------+---------------+--------+---------+ +| ``array`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``map`` | | | | | ++------------+--------+---------------+--------+---------+ +| ``union`` | ✓ | ✓ | ✓ | ✓ | ++------------+--------+---------------+--------+---------+ +| ``fixed`` | | | | | ++------------+--------+---------------+--------+---------+ + + +Logical Data Types +-------------- +The following table shows the supported **Logical** data types: + ++----------------------------+-------------------------------------------+ +| Avro Type | SQream Type | +| +--------+---------------+--------+---------+ +| | Number | Date/Datetime | String | Boolean | ++============================+========+===============+========+=========+ +| ``decimal`` | ✓ | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``uuid`` | | | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``date`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``time-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-millis`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``timestamp-micros`` | | ✓ | ✓ | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-millis`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``local-timestamp-micros`` | | | | | ++----------------------------+--------+---------------+--------+---------+ +| ``duration`` | | | | | ++----------------------------+--------+---------------+--------+---------+ + + +Mapping Objects to Rows +=============== +When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. + +Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. + +Ingesting Avro Files +==================== +This section describes how to ingest Avro files into SQream and covers the following: + + +.. contents:: + :local: + :depth: 1 + + +Preparing Your Avro Source File +---------- +Prepare your Avro source files according to the following requirements: + +* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). + + :: + +* Files are encoded with UTF-8 or ASCII. + + :: + +* Field delimiter is an ASCII character or characters. + + :: + +* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). + + :: + +* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + :: + +* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: + + * The record delimiter or field delimiter. + + :: + + * A double quote character. + + :: + + * A newline. + +SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. + +``NULL`` values can be marked in the following ways in Avro files: + + * An explicit null marker. For example, ``col1,\N,col3``. + + :: + + * An empty field delimited by the field delimiter. For example, ``col1,,col3``. + + .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. + +For more information about standard CSV files, see `RFC 4180 standard CSVs `_. + +Making Avro Files Accessible to Workers +--------------------- +To give workers access to files every node must have the same view of the storage being used. + +The following apply for Avro files to be accessible to workers: + +* For files hosted on NFS, ensure that the mount is accessible from all servers. + +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Basing Your Table Structure on Inserted Tables +--------------------- +Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.parquet`` table shown below: + +.. csv-table:: nba.parquet + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + Name VARCHAR(40), + Team VARCHAR(40), + Number BIGINT, + Position VARCHAR(2), + Age BIGINT, + Height VARCHAR(4), + Weight BIGINT, + College VARCHAR(40), + Salary FLOAT + ) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.parquet' + ); + +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. + +Verifying Your Table Output +--------------------- +Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. + +The following is an example of the output based on the **nba.parquet** table: + +.. code-block:: psql + + t=> SELECT * FROM ext_nba LIMIT 10; + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. + +Loading Data into SQream +--------------------- + +Syntax +~~~~~~~~~~~~~~~~~~~~~ +The following is the correct syntax for loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE AS + SELECT * FROM ; + +The following is an example of loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT * FROM ext_nba; + +For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. + +Examples +~~~~~~~~~~~~~~~~~~~~~ + +This section includes the following examples of loading data into SQream: + +.. contents:: + :local: + :depth: 1 + +Omitting Unsupported Column Types +********************** +When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. + +In the example below, the ``Position`` column is not supported due its type. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + + +Modifying Data Before Loading +********************** +One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. + +For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement + +In the example below, the ``Position`` column is set to the default ``NULL``. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary + FROM ext_nba + ORDER BY weight; + + +Loading a Table from a Directory of Avro Files on HDFS +********************** +The following is an example of loading a table from a directory of Avro files on HDFS: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; + +For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. + +Loading a Table from a Directory of Avro Files on S3 +********************** +The following is an example of loading a table from a directory of Avro files on S3: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index 83aca40ea..12582b8e4 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -10,9 +10,10 @@ The **Data Ingestion Sources** provides information about the following: :glob: inserting_data + avro csv parquet orc oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index 031f263b3..c0aae030d 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -16,7 +16,7 @@ Encrypting Data in Transit For more information, see the following: * :ref:`copy_from` -* :ref:`jdbc` +* `JDBC `_ * :ref:`odbc` Encrypting Data at Rest diff --git a/feature_guides/index.rst b/feature_guides/index.rst index c5f472785..650638c17 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -5,7 +5,7 @@ Feature Guides *********************** The **Feature Guides** section describes background processes that SQream uses to manage several areas of operation, such as data ingestion, load balancing, and access control. -This section describes the following features: +This section describes the following features: .. toctree:: :maxdepth: 1 diff --git a/reference/sql/sql_statements/update.rst b/reference/sql/sql_statements/dml_commands/update.rst similarity index 100% rename from reference/sql/sql_statements/update.rst rename to reference/sql/sql_statements/dml_commands/update.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index e14041385..8ecd680df 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -11,8 +11,6 @@ SQream DB supports commands from ANSI SQL. Data Definition Commands (DDL) ================================ - update - .. list-table:: DDL Commands :widths: auto :header-rows: 1 @@ -22,8 +20,6 @@ Data Definition Commands (DDL) - Usage * - :ref:`ADD COLUMN` - Add a new column to a table - * - :ref:`UPDATE` - - Modify the value of certain columns in existing rows without creating a table * - :ref:`ALTER DEFAULT SCHEMA` - Change the default schema for a role * - :ref:`ALTER TABLE` @@ -86,6 +82,8 @@ Data Manipulation Commands (DML) - Select rows and column from a table * - :ref:`TRUNCATE` - Delete all rows from a table + * - :ref:`UPDATE` + - Modify the value of certain columns in existing rows without creating a table * - :ref:`VALUES` - Return rows containing literal values diff --git a/releases/2022.1.rst b/releases/2022.1.rst new file mode 100644 index 000000000..d36bc9463 --- /dev/null +++ b/releases/2022.1.rst @@ -0,0 +1,104 @@ +.. _2022.1: + +************************** +Release Notes 2022.1 +************************** +The 2022.1 release notes were released on x/xx/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + + +Version Content +---------- +The 2022.1 Release Notes describes the following: + +* Example - Major feature release targeted for all on-premises customers. +* Example - Basic Cloud functionality. + + +New Features +---------- +The 2022.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Data Encryption +************ + + +Update Feature +************ + + +Avro Ingestion +************ + + + + +Main Features +-------- +The following list describes the main features: + +* xxx +* xx + + +Resolved Issues +--------- +The following list describes the resolved issues: + +The following table lists the issues that were resolved in Version 2021.2: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-xxxx + - Text + * - SQ-xxxx + - Text + * - SQ-xxxx + - Text + +Operations and Configuration Changes +-------- + +Subject +************ +Text + + + + +Subject +************ +Text + + + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +No features were depecrated. + +Known Issues and Limitations +-------- +The the list below describes the following known issues and limitations: + +* xxx +* xxx + + +Upgrading to v2022.1 +------- + diff --git a/releases/index.rst b/releases/index.rst index 472197afc..9158933a4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,7 +12,9 @@ Release Notes * - Version - Release Date - * - :ref:`2021.2` + * - :ref:`2022.1` + - April 17, 2022 + * - :ref:`2022.1` - September 13, 2021 * - :ref:`2021.1` - June 13, 2021 @@ -30,6 +32,7 @@ Release Notes :glob: :hidden: + 2022.1 2021.2_index 2021.1_index 2020.3_index From d80c9427434d4abd73b5879f80e97f34a75e3e0a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 10:21:44 +0200 Subject: [PATCH 0008/1892] Not Published --- releases/2022.1.rst | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index d36bc9463..51a7333cc 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -7,8 +7,7 @@ The 2022.1 release notes were released on x/xx/2022 and describe the following: .. contents:: :local: - :depth: 1 - + :depth: 1 Version Content ---------- @@ -17,6 +16,7 @@ The 2022.1 Release Notes describes the following: * Example - Major feature release targeted for all on-premises customers. * Example - Basic Cloud functionality. +**Comment** - *This will be done at the end.* New Features ---------- @@ -28,30 +28,33 @@ The 2022.1 Release Notes include the following new features: Data Encryption ************ +SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. +For more information, see `Data Encryption `_. Update Feature ************ +SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows without creating a table. +For more information, see `UPDATE `_. Avro Ingestion ************ +SQream now supports ingesting data from Avro files. - - +For more information, see `Inserting Data from Avro `_. Main Features -------- The following list describes the main features: -* xxx -* xx +* Main feature +* Main feature +**Comment** - *This will be done at the end.* Resolved Issues --------- -The following list describes the resolved issues: - The following table lists the issues that were resolved in Version 2021.2: .. list-table:: @@ -65,10 +68,14 @@ The following table lists the issues that were resolved in Version 2021.2: * - SQ-xxxx - Text * - SQ-xxxx - - Text + - Text + +**Comment** - *I will be updated regarding which resolved issues to include.* Operations and Configuration Changes -------- +**Comment** - *TBD* + Subject ************ @@ -85,20 +92,30 @@ Text Naming Changes ------- +**Comment** - *TBD* + No relevant naming changes were made. Deprecated Features ------- +**Comment** - *TBD* + No features were depecrated. Known Issues and Limitations -------- +**Comment** - *TBD* + The the list below describes the following known issues and limitations: -* xxx -* xxx +* Text +* Text + +End of Support +------- +**Comment** - *TBD* Upgrading to v2022.1 ------- - +**Comment** - *TBD* \ No newline at end of file From 3cd71e0265075b7229b2681ca950d08333b326e5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 13:02:48 +0200 Subject: [PATCH 0009/1892] Replaced left menu with multi-layered list Left menu was too long. Running idea by Product. --- .../sql_functions/scalar_functions/index.rst | 93 ++++++++++++++++--- 1 file changed, 80 insertions(+), 13 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index 1a7d639b3..114d26cd6 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -1,20 +1,87 @@ .. _scalar_functions: **************** -Built-In Scalar functions +Built-In Scalar Functions **************** -Built-in scalar functions return one value per call. +The **Built-In Scalar Functions** page describes functions that return one value per call: +.. hlist:: + :columns: 5 -.. toctree:: - :maxdepth: 1 - :caption: Built-in scalar functions - :glob: - - bitwise/* - conditionals/* - conversion/* - date_and_time/* - numeric/* - string/* \ No newline at end of file + + * `AND `_ + * `NOT `_ + * `OR `_ + * `SHIFT_LEFT `_ + * `SHIFT_RIGHT `_ + * `XOR `_ + * :ref:`between` + * :ref:`case` + * :ref:`coalesce` + * :ref:`in` + * :ref:`is_ascii` + * :ref:`is_null` + * :ref:`isnull` + * :ref:`from_unixts` + * :ref:`to_hex` + * :ref:`to_unixts` + * :ref:`curdate` + * :ref:`current_date` + * :ref:`current_timestamp` + * :ref:`dateadd` + * :ref:`datediff` + * :ref:`datepart` + * :ref:`eomonth` + * :ref:`extract` + * :ref:`getdate` + * :ref:`sysdate` + * :ref:`trunc` + * :ref:`abs` + * :ref:`acos` + * :ref:`asin` + * :ref:`atan` + * :ref:`atn2` + * :ref:`ceiling` + * :ref:`cos` + * :ref:`cot` + * :ref:`crc64` + * :ref:`degrees` + * :ref:`exp` + * :ref:`floor` + * :ref:`log` + * :ref:`log10` + * :ref:`mod` + * :ref:`pi` + * :ref:`power` + * :ref:`radians` + * :ref:`round` + * :ref:`sin` + * :ref:`sqrt` + * :ref:`square` + * :ref:`tan` + * :ref:`trunc` + * :ref:`char_length` + * :ref:`charindex` + * :ref:`concat` + * :ref:`isprefixof` + * :ref:`left` + * :ref:`len` + * :ref:`like` + * :ref:`lower` + * :ref:`ltrim` + * :ref:`octet_length` + * :ref:`patindex` + * :ref:`regexp_count` + * :ref:`regexp_instr` + * :ref:`regexp_replace` + * :ref:`regexp_substr` + * :ref:`repeat` + * :ref:`replace` + * :ref:`reverse` + * :ref:`right` + * :ref:`rlike` + * :ref:`rtrim` + * :ref:`substring` + * :ref:`trim` + * :ref:`upper` \ No newline at end of file From 58c097b2b9d0f8eca39b1ca90a85843d176fde3b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 13:50:14 +0200 Subject: [PATCH 0010/1892] Updated System Functions Menu --- .../system_functions/explain.rst | 59 ++++ .../sql_functions/system_functions/index.rst | 12 +- .../system_functions/show_connections.rst | 78 +++++ .../system_functions/show_locks.rst | 79 +++++ .../system_functions/show_node_info.rst | 310 ++++++++++++++++++ .../system_functions/show_server_status.rst | 108 ++++++ .../system_functions/stop_statement.rst | 77 +++++ 7 files changed, 719 insertions(+), 4 deletions(-) create mode 100644 reference/sql/sql_functions/system_functions/explain.rst create mode 100644 reference/sql/sql_functions/system_functions/show_connections.rst create mode 100644 reference/sql/sql_functions/system_functions/show_locks.rst create mode 100644 reference/sql/sql_functions/system_functions/show_node_info.rst create mode 100644 reference/sql/sql_functions/system_functions/show_server_status.rst create mode 100644 reference/sql/sql_functions/system_functions/stop_statement.rst diff --git a/reference/sql/sql_functions/system_functions/explain.rst b/reference/sql/sql_functions/system_functions/explain.rst new file mode 100644 index 000000000..e9b7e7ee9 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/explain.rst @@ -0,0 +1,59 @@ +.. _explain: + +***************** +EXPLAIN +***************** + +``EXPLAIN`` returns a static query plan, which can be used to debug query plans. + +To see an actively running query or statement, use :ref:`show_node_info` instead. + +See also :ref:`show_node_info`, :ref:`show_server_status`. + + +Permissions +============= + +The role must have the ``SELECT`` permissions for any tables referenced by the query. + +Syntax +========== + +.. code-block:: postgres + + explain_statement ::= + SELECT EXPLAIN(query_stmt) + ; + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``query_stmt`` + - The select query to generate the plan for. + +Notes +=========== + +Use dollar-quoting to escape the query text + +Examples +=========== + +Generating a static query plan +---------------------------------- + +.. code-block:: psql + + t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); + Select + Specific (TTNative Gpu) (dateadd@null := dt@null, + dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) + Table Scan + public.cool_dates ("dt@null", "dt@val") [] + diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst index 734a9133a..a27dfda62 100644 --- a/reference/sql/sql_functions/system_functions/index.rst +++ b/reference/sql/sql_functions/system_functions/index.rst @@ -3,14 +3,18 @@ ******************** System Functions ******************** +**System functions** are used for returning system information, such as version and node information, and for maintenance operations that are not regularly accessed from any interface. -System functions are used for working with database objects, settings, and values. - +The System Functions page describes the following: .. toctree:: :maxdepth: 1 :glob: - :hidden: + explain show_version - + show_connections + show_locks + show_node_info + show_server_status + stop_statement \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_connections.rst b/reference/sql/sql_functions/system_functions/show_connections.rst new file mode 100644 index 000000000..1bd320a4c --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_connections.rst @@ -0,0 +1,78 @@ +.. _show_connections: + +******************** +SHOW_CONNECTIONS +******************** + +``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. + +To see sessions across the cluster, see :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_connections_statement ::= + SELECT SHOW_CONNECTIONS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``ip`` + - The worker hostname or IP + * - ``conn_id`` + - Connection ID + * - ``conn_start_time`` + - Connection start timestamp + * - ``stmt_id`` + - Statement ID. Connections with no active statement display ``-1``. + * - ``stmt_start_time`` + - Statement start timestamp + * - ``stmt`` + - Statement text + + +Notes +=========== + +* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. + +* A connection is typically reused. There could be many statements under a single connection ID. + +Examples +=========== + +Using ``SHOW_CONNECTIONS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_locks.rst b/reference/sql/sql_functions/system_functions/show_locks.rst new file mode 100644 index 000000000..d5e7c02ec --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_locks.rst @@ -0,0 +1,79 @@ +.. _show_locks: + +******************** +SHOW_LOCKS +******************** + +``SHOW_LOCKS`` returns a list of locks from across the cluster. + +Read more about locks in :ref:`concurrency_and_locks`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_locks_statement ::= + SELECT SHOW_LOCKS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``stmt_id`` + - Statement ID that caused the lock. + * - ``stmt_string`` + - Statement text + * - ``username`` + - The role that executed the statement + * - ``server`` + - The worker node's IP + * - ``port`` + - The worker node's port + * - ``locked_object`` + - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` + * - ``lockmode`` + - The locking mode (:ref:`inclusive` or :ref:`exclusive`). + * - ``statement_start_time`` + - Timestamp the statement started + * - ``lock_start_time`` + - Timestamp the lock was obtained + + +Examples +=========== + +Using ``SHOW_LOCKS`` to see active locks +--------------------------------------------------- + +In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. + + +.. code-block:: psql + + t=> SELECT SHOW_LOCKS(); + statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time + -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + + diff --git a/reference/sql/sql_functions/system_functions/show_node_info.rst b/reference/sql/sql_functions/system_functions/show_node_info.rst new file mode 100644 index 000000000..345d16440 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_node_info.rst @@ -0,0 +1,310 @@ +.. _show_node_info: + +******************** +SHOW_NODE_INFO +******************** + +``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. + +The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. + +See also :ref:`explain`, :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_node_info_statement ::= + SELECT SHOW_NODE_INFO(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to explore + +Returns +========= + +This utility returns details of the execution nodes, if the statement is still running. + +If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - Column name + - Description + * - ``stmt_id`` + - The ID for the statement + * - ``node_id`` + - This node's ID in this execution plan + * - ``node_type`` + - The node type + * - ``rows`` + - Total number of rows this node has processed + * - ``chunks`` + - Number of chunks this node has processed + * - ``avg_rows_in_chunk`` + - Average amount of rows that this node processes in each chunk (``rows / chunks``) + * - ``time`` + - Timestamp for this node's creation + * - ``parent_node_id`` + - The ``node_id`` of this node's parent + * - ``read`` + - Total data read from disk + * - ``write`` + - Total data written to disk + * - ``comment`` + - Additional information (e.g. table name for ``ReadTable``) + * - ``timesum`` + - Total elapsed time for this execution node's processing + + +.. _node_types: + +Node types +============= + +This is a full list of node types: + +.. list-table:: Node types + :widths: auto + :header-rows: 1 + + * - Column name + - Execution location + - Description + * - ``AddChunkId`` + - + - Used during insert operations + * - ``AddSequences`` + - + - Used during insert operations, with :ref:`identity columns` + * - ``AddMinMaxMetadata`` + - + - Used to calculate ranges for the :ref:`chunk metadata system` + * - ``AddTopSortFilters`` + - + - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Compress`` + - CPU and GPU + - Compress data with both CPU and GPU schemes + * - ``CpuDecompress`` + - CPU + - Decompression operation, common for longer ``VARCHAR`` types + * - ``CpuLoopJoin`` + - CPU + - A non-indexed nested loop join, performed on the CPU + * - ``CpuReduce`` + - CPU + - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) + * - ``CpuToGpu``, ``GpuToCpu`` + - + - An operation that moves data to or from the GPU for processing + * - ``CpuTransform`` + - CPU + - A transform operation performed on the CPU, usually a :ref:`scalar function` + * - ``CrossJoin`` + - + - A join without a join condition + * - ``DeferredGather`` + - CPU + - Merges the results of GPU operations with a result set [#f0]_ + * - ``Distinct`` + - GPU + - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) + * - ``Distinct_Merge`` + - CPU + - The merge operation of the ``Distinct`` operation + * - ``Filter`` + - GPU + - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause + * - ``GpuCopy`` + - GPU + - Copies data between GPUs or within a single GPU + * - ``GpuDecompress`` + - GPU + - Decompression operation + * - ``GpuReduceMerge`` + - GPU + - An operation to optimize part of the merger phases in the GPU + * - ``GpuTransform`` + - GPU + - A transformation operation such as a type cast or :ref:`scalar function` + * - ``Hash`` + - CPU + - Hashes the output result. Used internally. + * - ``JoinSideMarker`` + - + - Used internally. + * - ``LiteralValues`` + - CPU + - Creates a virtual relation (table), when :ref:`values` is used + * - ``LocateFiles`` + - CPU + - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns + * - ``LoopJoin`` + - GPU + - A non-indexed nested loop join, performed on the GPU + * - ``MarkMatchedJoinRows`` + - + - Used in outer joins, matches rows for larger join operations + * - ``NullifyDuplicates`` + - + - Replaces duplicate values with ``NULL`` to calculate distinct aggregates + * - ``NullSink`` + - CPU + - Used internally + * - ``ParseCsv`` + - CPU + - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data + * - ``PopNetworkQueue`` + - CPU + - Fetches data from the network queue (e.g. when used with :ref:`insert`) + * - ``PushToNetworkQueue`` + - CPU + - Sends result sets to a client connected over the network + * - ``ReadCatalog`` + - CPU + - Converts the :ref:`catalog` into a relation (table) + * - ``ReadFiles`` + - CPU + - Reads external flat-files + * - ``ReadOrc`` + - CPU + - Reads data from an ORC file + * - ``ReadParquet`` + - CPU + - Reads data from a Parquet file + * - ``ReadTable`` + - CPU + - Reads data from a standard table stored on disk + * - ``ReadTableMetadata`` + - CPU + - Reads only table metadata as an optimization + * - ``Rechunk`` + - + - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used + * - ``Reduce`` + - GPU + - A reduction operation, such as a ``GROUP BY`` + * - ``ReduceMerge`` + - GPU + - A merge operation of a reduction operation, helps operate on larger-than-RAM data + * - ``ReorderInput`` + - + - Change the order of arguments in preparation for the next operation + * - ``SeparatedGather`` + - GPU + - Gathers additional columns for the result + * - ``Sort`` + - GPU + - Sort operation [#f1]_ + * - ``SortMerge`` + - CPU + - A merge operation of a sort operation, helps operate on larger-than-RAM data + * - ``SortMergeJoin`` + - GPU + - A sort-merge join, performed on the GPU + * - ``TakeRowsFromChunk`` + - + - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Top`` + - + - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) + * - ``UdfTransform`` + - CPU + - Executes a :ref:`user defined function` + * - ``UnionAll`` + - + - Combines two sources of data when ``UNION ALL`` is used + * - ``VarCharJoiner`` + - + - Used internally + * - ``VarCharSplitter`` + - + - Used intenrally + * - ``Window`` + - GPU + - Executes a non-ranking :ref:`window function` + * - ``WindowRanking`` + - GPU + - Executes a ranking :ref:`window function` + * - ``WriteTable`` + - CPU + - Writes the result set to a standard table stored on disk + +.. rubric:: Footnotes + +.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. + +.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. + +Statement statuses +======================= + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Notes +=========== + +* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. + +* This utility is primarily intended for troubleshooting with SQream support. + +Examples +=========== + +Getting execution details for a statement +------------------------------------------------ + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 + sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 + + +The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. + +The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` + +.. code-block:: psql + + t=> SELECT SHOW_NODE_INFO(176); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- + 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 + 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 + 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 + 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 + 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 + 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 + 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 + 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 + 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 + 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 + 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 + diff --git a/reference/sql/sql_functions/system_functions/show_server_status.rst b/reference/sql/sql_functions/system_functions/show_server_status.rst new file mode 100644 index 000000000..f59f79ccc --- /dev/null +++ b/reference/sql/sql_functions/system_functions/show_server_status.rst @@ -0,0 +1,108 @@ +.. _show_server_status: + +******************** +SHOW_SERVER_STATUS +******************** + +``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. + +To list active statements on the current worker only, see :ref:`show_connections`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_server_status_statement ::= + SELECT SHOW_SERVER_STATUS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``service`` + - The service name for the statement + * - ``instance`` + - The worker ID + * - ``connection_id`` + - Connection ID + * - ``serverip`` + - Worker end-point IP + * - ``serverport`` + - Worker end-point port + * - ``database_name`` + - Database name for the statement + * - ``user_name`` + - Username running the statement + * - ``clientip`` + - Client IP + * - ``statementid`` + - Statement ID + * - ``statement`` + - Statement text + * - ``statementstarttime`` + - Statement start timestamp + * - ``statementstatus`` + - Statement status (see table below) + * - ``statementstatusstart`` + - Last updated timestamp + +.. include from here: 66 + + +.. list-table:: Statement status values + :widths: auto + :header-rows: 1 + + * - Status + - Description + * - ``Preparing`` + - Statement is being prepared + * - ``In queue`` + - Statement is waiting for execution + * - ``Initializing`` + - Statement has entered execution checks + * - ``Executing`` + - Statement is executing + * - ``Stopping`` + - Statement is in the process of stopping + + +.. include until here 86 + +Notes +=========== + +* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. + +Examples +=========== + +Using ``SHOW_SERVER_STATUS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- + sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 + +The statement ID is ``128``, running on worker ``192.168.1.91``. diff --git a/reference/sql/sql_functions/system_functions/stop_statement.rst b/reference/sql/sql_functions/system_functions/stop_statement.rst new file mode 100644 index 000000000..30efc25b5 --- /dev/null +++ b/reference/sql/sql_functions/system_functions/stop_statement.rst @@ -0,0 +1,77 @@ +.. _stop_statement: + +******************** +STOP_STATEMENT +******************** + +``STOP_STATEMENT`` stops or aborts an active statement. + +To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. + +.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + stop_statement_statement ::= + SELECT STOP_STATEMENT(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to stop + +Returns +========= + +This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. + + +Notes +=========== + +* This utility always succeeds even if the statement does not exist, or has already stopped. + +Examples +=========== + +Using :ref:`show_connections` to get statement IDs +---------------------------------------------------- + +.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can now stop this statement: + +.. code-block:: psql + + t=> SELECT STOP_STATEMENT(129) + executed + From 19b8851e92a8bce01d1651e9664b17bd119942b2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 23 Mar 2022 15:55:38 +0200 Subject: [PATCH 0011/1892] Corrected error in Release Date table --- releases/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 9158933a4..d06a7a8bf 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -14,7 +14,7 @@ Release Notes - Release Date * - :ref:`2022.1` - April 17, 2022 - * - :ref:`2022.1` + * - :ref:`2021.2` - September 13, 2021 * - :ref:`2021.1` - June 13, 2021 @@ -37,4 +37,4 @@ Release Notes 2021.1_index 2020.3_index 2020.2 - 2020.1 + 2020.1 \ No newline at end of file From 103d94bc1e19d29f308d464f01b91ffb26cbb5cd Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 13:01:52 +0200 Subject: [PATCH 0012/1892] Updated Encryption --- feature_guides/data_encryption.rst | 3 +- feature_guides/data_encryption_flow.rst | 17 +++- feature_guides/data_encryption_methods.rst | 5 +- .../data_encryption_permissions.rst | 19 ++++ feature_guides/data_encryption_process.rst | 88 +++++++++++++++++++ feature_guides/data_encryption_syntax.rst | 25 ++++-- feature_guides/data_encryption_types.rst | 14 ++- 7 files changed, 152 insertions(+), 19 deletions(-) create mode 100644 feature_guides/data_encryption_permissions.rst create mode 100644 feature_guides/data_encryption_process.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index e312e7fff..3e9f485fb 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -13,6 +13,7 @@ The **Data Encryption** page describes the following: data_encryption_overview data_encryption_methods data_encryption_types + data_encryption_permissions data_encryption_syntax - data_encryption_flow + data_encryption_process data_encryption_use_cases \ No newline at end of file diff --git a/feature_guides/data_encryption_flow.rst b/feature_guides/data_encryption_flow.rst index f65b1d240..03f60fb44 100644 --- a/feature_guides/data_encryption_flow.rst +++ b/feature_guides/data_encryption_flow.rst @@ -1,9 +1,9 @@ -.. _data_encryption_flow: +.. _data_encryption_process: *********************** -Data Encryption Flow +Data Encryption Process *********************** -The **Data Encryption Flow** page describes the following: +The **Data Encryption Process** page describes end-to-end encryption process, and describes the following: .. contents:: :local: @@ -11,8 +11,19 @@ The **Data Encryption Flow** page describes the following: Encryption ---------------- +The following describes the encryption process: +1. Users with the required encryption execution permission access the system (see Permissions & privileges section) +User will choose the specific columns he would like to encrypt in the file in which he will upload (see constraints section), the syntax will encapsulates the hint which will trigger the encryption (see syntax section) + +User will provide the location of the master key from which the encryption will be derived in the remote repository (whether KMS or IBM SKLM) see syntax section for the exact convention (this section will not be applied in the MVP scope) + +User will trigger the copy command and the data will be transported upon TLS session (not yet data at rest encryption) + +Once data arrived to Sqream database it will be encrypted and saved + +For more information, see :ref:`data_encryption_permissions`. Decryption ---------------- diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index 031f263b3..0069b161c 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -16,8 +16,11 @@ Encrypting Data in Transit For more information, see the following: * :ref:`copy_from` -* :ref:`jdbc` +* `JDBC `_ * :ref:`odbc` Encrypting Data at Rest ---------------- +For **data at rest,** housed physically on computer data, you can encrypt one or more column as needed according to your specifications. Data at rest is encrypted before being written into files, and decrypted after being read from them. All existing unencrypted historical and data inserted into this column at a later time is encrypted for the specified column values. Data at rest is encrypted (**Comment** - *And decrypted?*) using the **AES-256** algorithm. + +**Comment** - *Because the encryption keys are hidden from users, I didn't document them here. Please confirm that this is correct.* \ No newline at end of file diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst new file mode 100644 index 000000000..309d75654 --- /dev/null +++ b/feature_guides/data_encryption_permissions.rst @@ -0,0 +1,19 @@ +.. _data_encryption_permissions: + +*********************** +Permissions +*********************** +Any user who granted with the appropriated permission privilege's for encryption + +Implementation notes +Date format is out of the scope of this feature as well as Varchar (due to upcoming deprecation) + +one method to encrypt the data with is the TDE: Transparent data encryption which employed by Microsoft/IBM/Oracle etc. + +management. The requirement is that this will be programmatic via API. + +The centralized key management store should be one of the following (R&D to choose which one in accordance to easiness of deployment): + +KMS (AWS)- https://aws.amazon.com/kms/ + +IBM- IBM Security Guardium Key Lifecycle Manager - Overview \ No newline at end of file diff --git a/feature_guides/data_encryption_process.rst b/feature_guides/data_encryption_process.rst new file mode 100644 index 000000000..b84bb2969 --- /dev/null +++ b/feature_guides/data_encryption_process.rst @@ -0,0 +1,88 @@ +.. _data_encryption_process: + +*********************** +Data Encryption Process +*********************** +The **Data Encryption Process** page describes end-to-end encryption process, and describes the following: + +.. contents:: + :local: + :depth: 1 + +The Encryption Process +---------------- +The following describes the encryption process: + +1. A user with the required encryption execution permission accesses the system. + + :: + +#. In the file to be uploaded, the user selects columns to encrypt. The syntax will (**Comment** - *"should" instead of "will"?)* includes the hint that triggers the encryption (see syntax section). + + :: + +#. The user provides the location of the master key for deriving (**Comment** - *...generating/activating?*) the encryption in the remote repository. This applies to both **KMS** and **IBM SKLM**. + + :: + + **Comment** - *The source doc says, "this section will not be applied in the MVP scope." Should it stay in this doc?* + + :: + +#. The user trigger (**Comment** - *"runs"?*) the COPY command to transport the data upon TLS session (not yet data at rest encryption) (**Comment** - *"Upon TLS session = when the TLS session is activated?"* + + :: + +#. When the data is successfully inserted into the SQream database, it is encrypted and saved. + +For more information, see the following: + +* More information on permissions, see :ref:`data_encryption_permissions`. + + :: + +* More information on which columns to encrypt, see the :ref:`Constraints` section below. + + :: + +* More information on triggering the encryption, and the master key location syntax, see :ref:`data_encryption_syntax`. + +The Decryption Process +---------------- +The following describes the encryption process: + +1. A user with the required encryption execution permission accesses the system. + + :: + +#. The user indicates the decryption. **Comment** - *"Indicates" = "triggers"?*) + + :: + +#. The user can view the data derived from a table holding the encrypted data by decrypting the data by providing the location of the master key and selecting the required fields. + + : + + **Comment** - the source doc said, "this section will not be applied in the MVP scope." Should it stay in this doc?* + +Once the specific statement ends- the user will be able to see the data in a human readable convention (plain text) + +For more information, see the following: + +* More information on triggering the decryption, see :ref:`data_encryption_syntax`. + + + + +Encrypted Columns +---------------- +Column/Table-level encryption - More granular approach, encrypt only what you really need to + + + +.. _constraints: + +Constraints +---------------- +Describe these in one of the existing sections. + diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 8df3e0d33..85cef25ee 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -3,13 +3,14 @@ *********************** Syntax *********************** - The **Syntax** page describes the following: .. contents:: :local: :depth: 1 - + +Encrypting a New Table +---------------- The following is the correct syntax for **encrypting** a new table: .. code-block:: console @@ -24,7 +25,11 @@ The following is an example of encrypting a new table: .. code-block:: console EXAMPLE - + +**Comment** - *Please provide an actual example.* + +Decrypting a New Table +---------------- The following is the correct syntax for **decrypting** a new table: .. code-block:: console @@ -37,8 +42,16 @@ The following is an example of decrypting a new table: EXAMPLE -Usage notes - this should be included on this page. +**Comment** - *Please provide an actual example.* + +Incorrectly Encrypting or Decrypting Your Data +---------------- +Using the incorrect master key or location while encrypting or decrypting generates an error. -When inputting the wrong master key/location in encryption/decryption an error should be raised to the user +**Comment** - *Can I get an example of this error to include in the doc?* + +**Comment** - *I thought that the master key was completely hidden from users... The internal doc says, "Master Key- the key will be generated within the server side, it will reside within a repository which will be hidden from the user."* + +In logs, master keys are masked to protect user privacy. Users are responsible for maintaining their master keys for the remote repository. -The master key needs to be masked in logs to protect user privacy, the responsibility maintaining the master key for the remote repository is on the user side \ No newline at end of file +**Comment** - *I'm not sure I fully understand the part about maintaing the master keys on the remote repository.* \ No newline at end of file diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst index 331b14f58..3da9071c2 100644 --- a/feature_guides/data_encryption_types.rst +++ b/feature_guides/data_encryption_types.rst @@ -3,14 +3,12 @@ *********************** Data Types *********************** +SQream's data encryption supports the following data types: +* INT +* BIGINT +* TEXT -Per the research done and per customer requirement the data types that should be supported are the following: +Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. -Int - -BigInt - -String - -On most cases this data type, if encrypted, will be populated by PII value (Personal Identifiable Information) such as credit card number and other personal and sensitive information \ No newline at end of file +For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file From 190ce170b9c1b09401454d8c2a143ba6c6716b48 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 14:14:25 +0200 Subject: [PATCH 0013/1892] Updated --- feature_guides/data_encryption.rst | 3 +- feature_guides/data_encryption_flow.rst | 43 ------------------- feature_guides/data_encryption_overview.rst | 22 +++++++++- .../data_encryption_permissions.rst | 5 ++- feature_guides/data_encryption_process.rst | 24 +++++------ feature_guides/data_encryption_use_cases.rst | 14 ------ 6 files changed, 36 insertions(+), 75 deletions(-) delete mode 100644 feature_guides/data_encryption_flow.rst delete mode 100644 feature_guides/data_encryption_use_cases.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 3e9f485fb..e8f919217 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -15,5 +15,4 @@ The **Data Encryption** page describes the following: data_encryption_types data_encryption_permissions data_encryption_syntax - data_encryption_process - data_encryption_use_cases \ No newline at end of file + data_encryption_process \ No newline at end of file diff --git a/feature_guides/data_encryption_flow.rst b/feature_guides/data_encryption_flow.rst deleted file mode 100644 index 03f60fb44..000000000 --- a/feature_guides/data_encryption_flow.rst +++ /dev/null @@ -1,43 +0,0 @@ -.. _data_encryption_process: - -*********************** -Data Encryption Process -*********************** -The **Data Encryption Process** page describes end-to-end encryption process, and describes the following: - -.. contents:: - :local: - :depth: 1 - -Encryption ----------------- -The following describes the encryption process: - -1. Users with the required encryption execution permission access the system (see Permissions & privileges section) - -User will choose the specific columns he would like to encrypt in the file in which he will upload (see constraints section), the syntax will encapsulates the hint which will trigger the encryption (see syntax section) - -User will provide the location of the master key from which the encryption will be derived in the remote repository (whether KMS or IBM SKLM) see syntax section for the exact convention (this section will not be applied in the MVP scope) - -User will trigger the copy command and the data will be transported upon TLS session (not yet data at rest encryption) - -Once data arrived to Sqream database it will be encrypted and saved - -For more information, see :ref:`data_encryption_permissions`. - -Decryption ----------------- - - - -Encrypted Columns ----------------- -Column/Table-level encryption - More granular approach, encrypt only what you really need to - - - - -Constraints ----------------- -Describe these in one of the existing sections. - diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 5b3f3e344..4c0455291 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -3,8 +3,26 @@ *********************** Overview *********************** -**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. +**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. +Encryption can be used for the following: + +* Deleting encrypted columns. + + :: + +* Creating tables with one or more encrypted columns. + + :: + +* Joining encrypted columns with other tables. + + :: + +* Encrypting existing data. + + :: + +* Selecting data from an encrypted column. For more information on GDPR compliance requirements, see the `GDPR checklist `_. \ No newline at end of file diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst index 309d75654..16f41dc70 100644 --- a/feature_guides/data_encryption_permissions.rst +++ b/feature_guides/data_encryption_permissions.rst @@ -3,10 +3,11 @@ *********************** Permissions *********************** -Any user who granted with the appropriated permission privilege's for encryption +Users with the appropriate encryption permission privilege's can encrypt and decrypt data. + +**Comment** - *The rest of this content seems internal, correct?* Implementation notes -Date format is out of the scope of this feature as well as Varchar (due to upcoming deprecation) one method to encrypt the data with is the TDE: Transparent data encryption which employed by Microsoft/IBM/Oracle etc. diff --git a/feature_guides/data_encryption_process.rst b/feature_guides/data_encryption_process.rst index b84bb2969..e76e6a9cc 100644 --- a/feature_guides/data_encryption_process.rst +++ b/feature_guides/data_encryption_process.rst @@ -61,28 +61,28 @@ The following describes the encryption process: #. The user can view the data derived from a table holding the encrypted data by decrypting the data by providing the location of the master key and selecting the required fields. - : + :: - **Comment** - the source doc said, "this section will not be applied in the MVP scope." Should it stay in this doc?* - -Once the specific statement ends- the user will be able to see the data in a human readable convention (plain text) - -For more information, see the following: - -* More information on triggering the decryption, see :ref:`data_encryption_syntax`. - + **Comment** - *the source doc said, "this section will not be applied in the MVP scope." Should it stay in this doc?* +#. When the statement has ended, the user can view the data in a human readable format as plain text. +For more information on triggering the decryption, see :ref:`data_encryption_syntax`. Encrypted Columns ---------------- -Column/Table-level encryption - More granular approach, encrypt only what you really need to - +**Comment** - *This section and "Constraints" don't really seem like phases in a flow, at least the way they are currently described. If they really are part of a flow, we should discuss how to reword them.* +Tables with encrypted columns are tagged with the ``encrypted`` label, allowing you to select what data to encrypt. .. _constraints: Constraints ---------------- -Describe these in one of the existing sections. +The encryption will be done in the database server- data at rest as the data will be encrypted in transit based on the TLS protocol. + +**Comment** - *I need some clarification on the sentence above.* + +Users without permissions to view tables with one or more encrypted table cannot view the entire table. +**Comment** - *Please confirm that the above sentence is correct. Below is the original sentence:"* \ No newline at end of file diff --git a/feature_guides/data_encryption_use_cases.rst b/feature_guides/data_encryption_use_cases.rst deleted file mode 100644 index 9e9ddeb4a..000000000 --- a/feature_guides/data_encryption_use_cases.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _data_encryption_use_cases: - -*********************** -Use Cases -*********************** - - - - - -Use Case Considerations -============== -Include the relevant content from this section in the correct places in this document. - From 612d83f08446199608cdaf66cb36e025b7af3149 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 14:15:14 +0200 Subject: [PATCH 0014/1892] Updated --- feature_guides/data_encryption.rst | 4 +- feature_guides/data_encryption_flow.rst | 32 ------- feature_guides/data_encryption_methods.rst | 5 +- feature_guides/data_encryption_process.rst | 88 ++++++++++++++++++++ feature_guides/data_encryption_syntax.rst | 25 ++++-- feature_guides/data_encryption_types.rst | 14 ++-- feature_guides/data_encryption_use_cases.rst | 14 ---- 7 files changed, 119 insertions(+), 63 deletions(-) delete mode 100644 feature_guides/data_encryption_flow.rst create mode 100644 feature_guides/data_encryption_process.rst delete mode 100644 feature_guides/data_encryption_use_cases.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index e312e7fff..e8f919217 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -13,6 +13,6 @@ The **Data Encryption** page describes the following: data_encryption_overview data_encryption_methods data_encryption_types + data_encryption_permissions data_encryption_syntax - data_encryption_flow - data_encryption_use_cases \ No newline at end of file + data_encryption_process \ No newline at end of file diff --git a/feature_guides/data_encryption_flow.rst b/feature_guides/data_encryption_flow.rst deleted file mode 100644 index f65b1d240..000000000 --- a/feature_guides/data_encryption_flow.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _data_encryption_flow: - -*********************** -Data Encryption Flow -*********************** -The **Data Encryption Flow** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Encryption ----------------- - - - -Decryption ----------------- - - - -Encrypted Columns ----------------- -Column/Table-level encryption - More granular approach, encrypt only what you really need to - - - - -Constraints ----------------- -Describe these in one of the existing sections. - diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index c0aae030d..0069b161c 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -16,8 +16,11 @@ Encrypting Data in Transit For more information, see the following: * :ref:`copy_from` -* `JDBC `_ +* `JDBC `_ * :ref:`odbc` Encrypting Data at Rest ---------------- +For **data at rest,** housed physically on computer data, you can encrypt one or more column as needed according to your specifications. Data at rest is encrypted before being written into files, and decrypted after being read from them. All existing unencrypted historical and data inserted into this column at a later time is encrypted for the specified column values. Data at rest is encrypted (**Comment** - *And decrypted?*) using the **AES-256** algorithm. + +**Comment** - *Because the encryption keys are hidden from users, I didn't document them here. Please confirm that this is correct.* \ No newline at end of file diff --git a/feature_guides/data_encryption_process.rst b/feature_guides/data_encryption_process.rst new file mode 100644 index 000000000..e76e6a9cc --- /dev/null +++ b/feature_guides/data_encryption_process.rst @@ -0,0 +1,88 @@ +.. _data_encryption_process: + +*********************** +Data Encryption Process +*********************** +The **Data Encryption Process** page describes end-to-end encryption process, and describes the following: + +.. contents:: + :local: + :depth: 1 + +The Encryption Process +---------------- +The following describes the encryption process: + +1. A user with the required encryption execution permission accesses the system. + + :: + +#. In the file to be uploaded, the user selects columns to encrypt. The syntax will (**Comment** - *"should" instead of "will"?)* includes the hint that triggers the encryption (see syntax section). + + :: + +#. The user provides the location of the master key for deriving (**Comment** - *...generating/activating?*) the encryption in the remote repository. This applies to both **KMS** and **IBM SKLM**. + + :: + + **Comment** - *The source doc says, "this section will not be applied in the MVP scope." Should it stay in this doc?* + + :: + +#. The user trigger (**Comment** - *"runs"?*) the COPY command to transport the data upon TLS session (not yet data at rest encryption) (**Comment** - *"Upon TLS session = when the TLS session is activated?"* + + :: + +#. When the data is successfully inserted into the SQream database, it is encrypted and saved. + +For more information, see the following: + +* More information on permissions, see :ref:`data_encryption_permissions`. + + :: + +* More information on which columns to encrypt, see the :ref:`Constraints` section below. + + :: + +* More information on triggering the encryption, and the master key location syntax, see :ref:`data_encryption_syntax`. + +The Decryption Process +---------------- +The following describes the encryption process: + +1. A user with the required encryption execution permission accesses the system. + + :: + +#. The user indicates the decryption. **Comment** - *"Indicates" = "triggers"?*) + + :: + +#. The user can view the data derived from a table holding the encrypted data by decrypting the data by providing the location of the master key and selecting the required fields. + + :: + + **Comment** - *the source doc said, "this section will not be applied in the MVP scope." Should it stay in this doc?* + +#. When the statement has ended, the user can view the data in a human readable format as plain text. + +For more information on triggering the decryption, see :ref:`data_encryption_syntax`. + +Encrypted Columns +---------------- +**Comment** - *This section and "Constraints" don't really seem like phases in a flow, at least the way they are currently described. If they really are part of a flow, we should discuss how to reword them.* + +Tables with encrypted columns are tagged with the ``encrypted`` label, allowing you to select what data to encrypt. + +.. _constraints: + +Constraints +---------------- +The encryption will be done in the database server- data at rest as the data will be encrypted in transit based on the TLS protocol. + +**Comment** - *I need some clarification on the sentence above.* + +Users without permissions to view tables with one or more encrypted table cannot view the entire table. + +**Comment** - *Please confirm that the above sentence is correct. Below is the original sentence:"* \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 8df3e0d33..85cef25ee 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -3,13 +3,14 @@ *********************** Syntax *********************** - The **Syntax** page describes the following: .. contents:: :local: :depth: 1 - + +Encrypting a New Table +---------------- The following is the correct syntax for **encrypting** a new table: .. code-block:: console @@ -24,7 +25,11 @@ The following is an example of encrypting a new table: .. code-block:: console EXAMPLE - + +**Comment** - *Please provide an actual example.* + +Decrypting a New Table +---------------- The following is the correct syntax for **decrypting** a new table: .. code-block:: console @@ -37,8 +42,16 @@ The following is an example of decrypting a new table: EXAMPLE -Usage notes - this should be included on this page. +**Comment** - *Please provide an actual example.* + +Incorrectly Encrypting or Decrypting Your Data +---------------- +Using the incorrect master key or location while encrypting or decrypting generates an error. -When inputting the wrong master key/location in encryption/decryption an error should be raised to the user +**Comment** - *Can I get an example of this error to include in the doc?* + +**Comment** - *I thought that the master key was completely hidden from users... The internal doc says, "Master Key- the key will be generated within the server side, it will reside within a repository which will be hidden from the user."* + +In logs, master keys are masked to protect user privacy. Users are responsible for maintaining their master keys for the remote repository. -The master key needs to be masked in logs to protect user privacy, the responsibility maintaining the master key for the remote repository is on the user side \ No newline at end of file +**Comment** - *I'm not sure I fully understand the part about maintaing the master keys on the remote repository.* \ No newline at end of file diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst index 331b14f58..3da9071c2 100644 --- a/feature_guides/data_encryption_types.rst +++ b/feature_guides/data_encryption_types.rst @@ -3,14 +3,12 @@ *********************** Data Types *********************** +SQream's data encryption supports the following data types: +* INT +* BIGINT +* TEXT -Per the research done and per customer requirement the data types that should be supported are the following: +Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. -Int - -BigInt - -String - -On most cases this data type, if encrypted, will be populated by PII value (Personal Identifiable Information) such as credit card number and other personal and sensitive information \ No newline at end of file +For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file diff --git a/feature_guides/data_encryption_use_cases.rst b/feature_guides/data_encryption_use_cases.rst deleted file mode 100644 index 9e9ddeb4a..000000000 --- a/feature_guides/data_encryption_use_cases.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _data_encryption_use_cases: - -*********************** -Use Cases -*********************** - - - - - -Use Case Considerations -============== -Include the relevant content from this section in the correct places in this document. - From 0a20c1e28ca017b7fef582d9c4415fced9174a5a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 14:23:43 +0200 Subject: [PATCH 0015/1892] Create data_encryption_permissions.rst --- .../data_encryption_permissions.rst | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 feature_guides/data_encryption_permissions.rst diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst new file mode 100644 index 000000000..16f41dc70 --- /dev/null +++ b/feature_guides/data_encryption_permissions.rst @@ -0,0 +1,20 @@ +.. _data_encryption_permissions: + +*********************** +Permissions +*********************** +Users with the appropriate encryption permission privilege's can encrypt and decrypt data. + +**Comment** - *The rest of this content seems internal, correct?* + +Implementation notes + +one method to encrypt the data with is the TDE: Transparent data encryption which employed by Microsoft/IBM/Oracle etc. + +management. The requirement is that this will be programmatic via API. + +The centralized key management store should be one of the following (R&D to choose which one in accordance to easiness of deployment): + +KMS (AWS)- https://aws.amazon.com/kms/ + +IBM- IBM Security Guardium Key Lifecycle Manager - Overview \ No newline at end of file From f57d54e70fdf69de418df37c2c42dd0980657d62 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 15:35:01 +0200 Subject: [PATCH 0016/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 22 +++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 5b3f3e344..4c0455291 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -3,8 +3,26 @@ *********************** Overview *********************** -**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. +**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. +Encryption can be used for the following: + +* Deleting encrypted columns. + + :: + +* Creating tables with one or more encrypted columns. + + :: + +* Joining encrypted columns with other tables. + + :: + +* Encrypting existing data. + + :: + +* Selecting data from an encrypted column. For more information on GDPR compliance requirements, see the `GDPR checklist `_. \ No newline at end of file From a8098779ceca48b97315f701190cc24739e506f7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 15:50:56 +0200 Subject: [PATCH 0017/1892] Update data_encryption.rst --- feature_guides/data_encryption.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index e8f919217..4e51a28aa 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -13,6 +13,6 @@ The **Data Encryption** page describes the following: data_encryption_overview data_encryption_methods data_encryption_types + data_encryption_process data_encryption_permissions - data_encryption_syntax - data_encryption_process \ No newline at end of file + data_encryption_syntax \ No newline at end of file From b673e26fc0d5bcb1aad12e5f207642cac08a1da5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 24 Mar 2022 15:53:11 +0200 Subject: [PATCH 0018/1892] Update data_encryption.rst --- feature_guides/data_encryption.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index e8f919217..4e51a28aa 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -13,6 +13,6 @@ The **Data Encryption** page describes the following: data_encryption_overview data_encryption_methods data_encryption_types + data_encryption_process data_encryption_permissions - data_encryption_syntax - data_encryption_process \ No newline at end of file + data_encryption_syntax \ No newline at end of file From 27b3f7eb1b3aec050bb828f88ef4d39fa3845fe6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 27 Mar 2022 15:23:30 +0300 Subject: [PATCH 0019/1892] Added Missing Statements (2) CLUSTER BY and DROP CLUSTERING KEYS were missing from DDL table. --- .../aggregate_functions/index.rst | 38 +++++++++---------- .../sql_functions/scalar_functions/index.rst | 1 + reference/sql/sql_statements/index.rst | 4 ++ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/index.rst b/reference/sql/sql_functions/aggregate_functions/index.rst index 9bf0527d6..5d3dfc125 100644 --- a/reference/sql/sql_functions/aggregate_functions/index.rst +++ b/reference/sql/sql_functions/aggregate_functions/index.rst @@ -6,31 +6,27 @@ Aggregate Functions Overview =========== - Aggregate functions perform calculations based on a set of values and return a single value. Most aggregate functions ignore null values. Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`select` statement. Available Aggregate Functions =============== The following list shows the available aggregate functions: - -.. toctree:: - :maxdepth: 1 - :glob: +.. hlist:: + :columns: 2 - - avg - corr - count - covar_pop - covar_samp - max - min - mode - percentile_cont - percentile_disc - stddev_pop - stddev_samp - sum - var_pop - var_samp + * :ref:`AVG` + * :ref:`CORR` + * :ref:`COUNT` + * :ref:`COVAR_POP` + * :ref:`COVAR_SAMP` + * :ref:`MAX` + * :ref:`MIN` + * :ref:`MODE` + * :ref:`PERCENTILE_CONT` + * :ref:`PERCENTILE_DISC` + * :ref:`STDDEV_POP` + * :ref:`STDDEV_SAMP` + * :ref:`SUM` + * :ref:`VAR_POP` + * :ref:`VAR_SAMP` \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index 114d26cd6..b21071021 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -3,6 +3,7 @@ **************** Built-In Scalar Functions **************** +FF The **Built-In Scalar Functions** page describes functions that return one value per call: diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 8ecd680df..28096f16a 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -24,6 +24,8 @@ Data Definition Commands (DDL) - Change the default schema for a role * - :ref:`ALTER TABLE` - Change the schema of a table + * - :ref:`CLUSTER BY` + - Change clustering keys in a table * - :ref:`CREATE DATABASE` - Create a new database * - :ref:`CREATE EXTERNAL TABLE` @@ -40,6 +42,8 @@ Data Definition Commands (DDL) - Create a new table in the database using results from a select query * - :ref:`CREATE VIEW` - Create a new view in the database + * - :ref:`DROP CLUSTERING KEY` + - Drops all clustering keys in a table * - :ref:`DROP COLUMN` - Drop a column from a table * - :ref:`DROP DATABASE` From 85f8481db98e14ea9d1fddb8f75c438a7db22540 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 27 Mar 2022 16:02:44 +0300 Subject: [PATCH 0020/1892] Deleted DDL Files (backed up) Tried method of removing the statements from topic menu, and linking directly to them. The list in topic menu was too long. --- .../ddl_commands/add_column.rst | 91 ------ .../ddl_commands/alter_default_schema.rst | 58 ---- .../ddl_commands/alter_table.rst | 33 --- .../ddl_commands/cluster_by.rst | 69 ----- .../ddl_commands/create_database.rst | 55 ---- .../ddl_commands/create_external_table.rst | 156 ---------- .../ddl_commands/create_foreign_table.rst | 165 ----------- .../ddl_commands/create_function.rst | 103 ------- .../ddl_commands/create_schema.rst | 92 ------ .../ddl_commands/create_table.rst | 278 ------------------ .../ddl_commands/create_table_as.rst | 96 ------ .../ddl_commands/create_view.rst | 79 ----- .../ddl_commands/drop_clustering_key.rst | 64 ---- .../ddl_commands/drop_column.rst | 63 ---- .../ddl_commands/drop_database.rst | 63 ---- .../ddl_commands/drop_function.rst | 66 ----- .../ddl_commands/drop_schema.rst | 77 ----- .../ddl_commands/drop_table.rst | 70 ----- .../sql_statements/ddl_commands/drop_view.rst | 72 ----- .../ddl_commands/rename_column.rst | 65 ---- .../ddl_commands/rename_table.rst | 57 ---- reference/sql/sql_statements/index.rst | 84 +++--- 22 files changed, 42 insertions(+), 1914 deletions(-) delete mode 100644 reference/sql/sql_statements/ddl_commands/add_column.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/alter_default_schema.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/alter_table.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/cluster_by.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_database.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_external_table.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_foreign_table.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_function.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_schema.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_table.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_table_as.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/create_view.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_column.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_database.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_function.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_schema.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_table.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/drop_view.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/rename_column.rst delete mode 100644 reference/sql/sql_statements/ddl_commands/rename_table.rst diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst deleted file mode 100644 index d532c956f..000000000 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. _add_column: - -********************** -ADD COLUMN -********************** - -The ``ADD COLUMN`` command is used to add columns to an existing table. - - - -Syntax -========== -The following is the correct syntax for adding a table: - -.. code-block:: postgres - - alter_table_add_column_statement ::= - ALTER TABLE [schema_name.]table_name { ADD COLUMN column_def [, ...] } - ; - - table_name ::= identifier - - schema_name ::= identifier - - column_def :: = { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - DEFAULT default_value - - - -Parameters -============ -The following parameters can be used for adding a table: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``table_name`` - - The table name to apply the change to. - * - ``ADD COLUMN column_def`` - - A comma separated list of ADD COLUMN commands - * - ``column_def`` - - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - -.. note:: - * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. - * A new column added to the table can not contain an IDENTITY or be of the TEXT type. - - -Permissions -============= -The role must have the ``DDL`` permission at the database or table level. - -Examples -=========== -This section includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Adding a Simple Column with a Default Value ------------------------------------------ -This example shows how to add a simple column with a default value: - -.. code-block:: postgres - - ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; - - -Adding Several Columns in One Command -------------------------------------------- -This example shows how to add several columns in one command: - -.. code-block:: postgres - - ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, - ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; diff --git a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst deleted file mode 100644 index e40a8af7c..000000000 --- a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst +++ /dev/null @@ -1,58 +0,0 @@ -.. _alter_default_schema: - -********************** -ALTER DEFAULT SCHEMA -********************** - -The ``ALTER DEFAULT SCHEMA`` command can be used to change a role's default schema. The default schema in SQream is ``public``. - -For more information, see :ref:`create_schema` and :ref:`drop_schema`. - - - -Syntax -========== -The following is the correct syntax for altering a default schema: - -.. code-block:: postgres - - alter_default_schema_statement ::= - ALTER DEFAULT SCHEMA FOR role_name TO schema_name - ; - - role_name ::= identifier - - schema_name ::= identifier - - - -Parameters -============ -The following parameters can be used when altering a default schema: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``role_name`` - - The name of the role the change will apply to. - * - ``schema_name`` - - The new default schema name. - -Permissions -============= -No special permissions are required. - -Examples -=========== -This section includes an example of **altering the default schema for a role**: - -.. code-block:: postgres - - SELECT * FROM users; -- Refers to public.users - - ALTER DEFAULT SCHEMA FOR bgilfoyle TO staging; - - SELECT * FROM users; -- Now refers to staging.users, rather than public.users diff --git a/reference/sql/sql_statements/ddl_commands/alter_table.rst b/reference/sql/sql_statements/ddl_commands/alter_table.rst deleted file mode 100644 index 6afb84be1..000000000 --- a/reference/sql/sql_statements/ddl_commands/alter_table.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _alter_table: - -********************** -ALTER TABLE -********************** -You can use the ``ALTER TABLE`` command to make schema changes to a table, and can be used in conjunction with several sub-commands. - -Locks -======= -Making changes to a schema makes an exclusive lock on tables. While these operations do not typically take much time, other statements may have to wait until the schema changes are completed. - -Sub-Commands -============== -The following table shows the sub-commands that can be used with the ``ALTER TABLE`` command: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`ADD COLUMN` - - Adds a new column to a table. - * - :ref:`DROP COLUMN` - - Drops a column from a table. - * - :ref:`RENAME COLUMN` - - Renames a column. - * - :ref:`RENAME TABLE` - - Renames a table. - * - :ref:`CLUSTER BY` - - Modifies (adds or reorders) the clustering keys in a table. - * - :ref:`DROP CLUSTERING KEY` - - Drops all clustering keys. diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst deleted file mode 100644 index 1a6972b1e..000000000 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _cluster_by: - -********************** -CLUSTER BY -********************** - -``CLUSTER BY`` can be used to change clustering keys in a table. - - -Read our :ref:`data_clustering` guide for more information. - -See also: :ref:`drop_clustering_key`, :ref:`create_table`. - - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] - ; - - table_name ::= identifier - - column_name ::= identifier - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``table_name`` - - The table name to apply the change to. - * - ``column_name [, ... ]`` - - Comma separated list of columns to create clustering keys for - - -Usage notes -================= - -Removing clustering keys does not affect existing data. - -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). - - -Examples -=========== - -Reclustering a table ------------------------------------------ - -.. code-block:: postgres - - ALTER TABLE public.users CLUSTER BY start_date; - - diff --git a/reference/sql/sql_statements/ddl_commands/create_database.rst b/reference/sql/sql_statements/ddl_commands/create_database.rst deleted file mode 100644 index db7ffda3f..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_database.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _create_database: - -***************** -CREATE DATABASE -***************** - -``CREATE DATABASE`` creates a new database in SQream DB - -Permissions -============= - -Only a superuser can create a new database - -Syntax -========== - -.. code-block:: postgres - - create_database_statement ::= - - CREATE DATABASE database_name ; - - database_name ::= identifier - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``database_name`` - - The name of the database name. The database name must be unique, and follows :ref:`Identifier rules ` - -Examples -=========== - -.. code-block:: postgres - - CREATE DATABASE raviga; - -.. code-block:: postgres - - CREATE DATABASE my_db; - -If the database already exists, an error will appear: - -.. code-block:: psql - - master=> CREATE DATABASE MY_DB; - Database 'my_db' already exists - -.. note:: SQream DB :ref:`identifiers ` are always converted to lowercase, so ``my_db`` is the same as ``MY_DB``, unless explicitly quoted as ``"MY_DB"``. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/create_external_table.rst b/reference/sql/sql_statements/ddl_commands/create_external_table.rst deleted file mode 100644 index fc05ca71e..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_external_table.rst +++ /dev/null @@ -1,156 +0,0 @@ -.. _create_external_table: - -*********************** -CREATE EXTERNAL TABLE -*********************** - -.. warning:: - - The ``CREATE EXTERNAL TABLE`` syntax is deprecated, and will be removed in future versions. - - Starting with SQream DB v2020.2, external tables have been renamed to :ref:`foreign tables`, and use a more flexible foreign data wrapper concept. See :ref:`create_foreign_table` instead. - - Upgrading to a new version of SQream DB converts existing tables automatically. When creating a new external tables, use the new foreign table syntax. - - -``CREATE TABLE`` creates a new external table in an existing database. - -See more in the :ref:`External tables guide`. - -.. tip:: - - * Data in an external table can change if the sources change, and frequent access to remote files may harm performance. - - * To create a regular table, see :ref:`CREATE TABLE ` - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] EXTERNAL TABLE [schema_name].table_name ( - { column_def [, ...] } - ) - USING FORMAT format_def - WITH { external_table_option [ ...] } - ; - - schema_name ::= identifier - - table_name ::= identifier - - format_def ::= { PARQUET | ORC | CSV } - - external_table_option ::= { - PATH '{ path_spec }' - | FIELD DELIMITER '{ field_delimiter }' - | RECORD DELIMITER '{ record_delimiter }' - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS SECRET }' - } - - path_spec ::= { local filepath | S3 URI | HDFS URI } - - field_delimiter ::= delimiter_character - - record_delimiter ::= delimiter_character - - column_def ::= { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - -.. _cet_parameters: - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - * - ``USING FORMAT ...`` - - Specifies the format of the source files, such as ``PARQUET``, ``ORC``, or ``CSV``. - * - ``WITH PATH ...`` - - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. - * - ``FIELD DELIMITER`` - - Specifies the field delimiter for CSV files. Defaults to ``,``. - * - ``RECORD DELIMITER`` - - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` - * - ``AWS_ID``, ``AWS_SECRET`` - - Credentials for authenticated S3 access - - -Examples -=========== - -A simple table from Tab-delimited file (TSV) ----------------------------------------------- - -.. code-block:: postgres - - CREATE OR REPLACE EXTERNAL TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) - USING FORMAT csv - WITH PATH '/home/rhendricks/cool_animals.csv' - FIELD DELIMITER '\t'; - - -A table from a directory of Parquet files on HDFS ------------------------------------------------------ - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet'; - -A table from a bucket of files on S3 --------------------------------------- - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 's3://pp-secret-bucket/users/*.parquet' - AWS_ID 'our_aws_id' - AWS_SECRET 'our_aws_secret'; - - -Changing an external table to a regular table ------------------------------------------------- - -Materializes an external table into a regular table. - -.. tip: Using an external table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files - -.. code-block:: postgres - - CREATE TABLE real_table - AS SELECT * FROM external_table; - diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst deleted file mode 100644 index d50e13380..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ /dev/null @@ -1,165 +0,0 @@ -.. _create_foreign_table: - -*********************** -CREATE FOREIGN TABLE -*********************** - -.. note:: - - Starting with SQream DB v2020.2, external tables have been renamed to foreign tables, and use a more flexible foreign data wrapper concept. - - Upgrading to a new version of SQream DB converts existing external tables automatically. - - -``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. - -See more in the :ref:`Foreign tables guide`. - -.. tip:: - - * Data in a foreign table can change if the sources change, and frequent access to remote files may harm performance. - - * To create a regular table, see :ref:`CREATE TABLE ` - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] FOREIGN TABLE [schema_name].table_name ( - { column_def [, ...] } - ) - [ FOREIGN DATA ] WRAPPER fdw_name - [ OPTIONS ( option_def [, ... ] ) ] - ; - - schema_name ::= identifier - - table_name ::= identifier - - fdw_name ::= - { csv_fdw | orc_fdw | parquet_fdw } - - option_def ::= - { - LOCATION = '{ path_spec }' - | DELIMITER = '{ field_delimiter }' -- for CSV only - | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS SECRET }' - } - - path_spec ::= { local filepath | S3 URI | HDFS URI } - - field_delimiter ::= delimiter_character - - record_delimiter ::= delimiter_character - - column_def ::= - { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - -.. _cft_parameters: - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - * - ``WRAPPER ...`` - - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, or ``csv_fdw``. - * - ``LOCATION = ...`` - - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. - * - ``DELIMITER = ...`` - - Specifies the field delimiter for CSV files. Defaults to ``,``. - * - ``RECORD_DELIMITER = ...`` - - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` - * - ``AWS_ID``, ``AWS_SECRET`` - - Credentials for authenticated S3 access - - -Examples -=========== - -A simple table from Tab-delimited file (TSV) ----------------------------------------------- - -.. code-block:: postgres - - CREATE OR REPLACE FOREIGN TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) - WRAPPER csv_fdw - OPTIONS - ( LOCATION = '/home/rhendricks/cool_animals.csv', - DELIMITER = '\t' - ) - ; - - -A table from a directory of Parquet files on HDFS ------------------------------------------------------ - -.. code-block:: postgres - - CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' - ); - -A table from a bucket of ORC files on S3 ------------------------------------------- - -.. code-block:: postgres - - CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) - WRAPPER orc_fdw - OPTIONS - ( - LOCATION = 's3://pp-secret-bucket/users/*.orc', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); - - -Changing a foreign table to a regular table ------------------------------------------------- - -Materializes a foreign table into a regular table. - -.. tip: Using a foreign table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files - -.. code-block:: postgres - - CREATE TABLE real_table - AS SELECT * FROM some_foreign_table; - diff --git a/reference/sql/sql_statements/ddl_commands/create_function.rst b/reference/sql/sql_statements/ddl_commands/create_function.rst deleted file mode 100644 index 339543a0a..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_function.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. _create_function: - -***************** -CREATE FUNCTION -***************** - -``CREATE FUNCTION`` creates a new user-defined function (UDF) in an existing database. - -See more in our :ref:`Python UDF (user-defined functions)` guide. - -Permissions -============= - -The role must have the ``CREATE FUNCTION`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - create_function_statement ::= - CREATE [ OR REPLACE ] FUNCTION function_name (argument_list) - RETURNS return_type - AS $$ - { function_body } - $$ LANGUAGE python - ; - - function_name ::= identifier - - argument_list :: = { value_name type_name [, ...] } - - value_name ::= identifier - - return_type ::= type_name - - function_body ::= Valid Python code - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new function, and overwrite any existing function by the same name. Does not return an error if the function already exists. ``CREATE OR REPLACE`` does not check the function contents or structure, only the function name. - * - ``function_name`` - - The name of the function to create, which must be unique inside the database. - * - ``argument_list`` - - A comma separated list of column definitions. A column definition includes a name identifier and a datatype. - * - ``return_type`` - - The SQL datatype of the return value, such as ``INT``, ``VARCHAR``, etc. - * - ``function_body`` - - Python code, dollar-quoted (``$$``). - -Examples -=========== - -Calculate distance between two points --------------------------------------- - -.. code-block:: postgres - - CREATE OR REPLACE FUNCTION my_distance (x1 float, y1 float, x2 float, y2 float) - RETURNS FLOAT - AS $$ - import math - if y1 < x1: - return 0.0 - else: - return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) - $$ LANGUAGE PYTHON; - - -- Usage: - SELECT city, my_location, my_distance(x1,y1,x2,y2) from cities; - - -Calling files from other locations ---------------------------------------- - -.. code-block:: postgres - - -- Our script my_code.py is in ~/my_python_stuff - - CREATE FUNCTION write_log() - RETURNS INT - AS $$ - import sys - sys.path.append("/home/user/my_python_stuff") - - import my_code as f - - f.main() - - return 1 - - $$ LANGUAGE PYTHON; - - -- Usage: - SELECT write_log(); diff --git a/reference/sql/sql_statements/ddl_commands/create_schema.rst b/reference/sql/sql_statements/ddl_commands/create_schema.rst deleted file mode 100644 index e85f328a9..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_schema.rst +++ /dev/null @@ -1,92 +0,0 @@ -.. _create_schema: - -***************** -CREATE SCHEMA -***************** -The **CREATE SCHEMA** page describes the following: - - -.. contents:: - :local: - :depth: 2 - -Overview -============ - -``CREATE SCHEMA`` creates a new schema in an existing database. A schema is a virtual space for storing tables. - -The default schema in SQream DB is ``public``. - -.. tip:: Use schemas to separate between use-cases, such as staging and production. - -The **CREATE SCHEMA** statement can be used to query tables from different schemas without providing an alias, as in the following example: - -.. code-block:: postgres - - select .table_name.column_name from .table_name - -See also: :ref:`drop_schema`, :ref:`alter_default_schema`. - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level. - -Syntax -========== -The following example shows the correct syntax for creating a schema: - -.. code-block:: postgres - - create_schema_statement ::= - CREATE SCHEMA schema_name - ; - - schema_name ::= identifier - - -Parameters -============ -The following table shows the ``schema_name`` parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The name of the schema to create. - -Examples -=========== -This section includes the following examples: - -.. contents:: - :local: - :depth: 1 - - -Creating a Schema --------------------- -The following example shows an example of the syntax for creating a schema: - -.. code-block:: postgres - - CREATE SCHEMA staging; - - CREATE TABLE staging.users AS SELECT * FROM public.users; - - SELECT * FROM staging.users; - -Altering the Default Schema for a Role ------------------------------------------ -The following example shows an example of the syntax for altering the default schema for a role: - -.. code-block:: postgres - - SELECT * FROM users; -- Refers to public.users - - ALTER DEFAULT SCHEMA FOR bgilfoyle TO staging; - - SELECT * FROM users; -- Now refers to staging.users, rather than public.users diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst deleted file mode 100644 index b660e442c..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ /dev/null @@ -1,278 +0,0 @@ -.. _create_table: - -***************** -CREATE TABLE -***************** - -The ``CREATE TABLE`` statement is used to create a new table in an existing database. - -.. tip:: - * To create a table based on the result of a select query, see :ref:`CREATE TABLE AS `. - * To create a table based on files like Parquet and ORC, see :ref:`CREATE FOREIGN TABLE ` - - - -Syntax -========== -The following is the correct syntax for creating a table: - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( - { column_def [, ...] } - ) - [ CLUSTER BY { column_name [, ...] } ] - ; - - schema_name ::= identifier - - table_name ::= identifier - - column_def :: = { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - -Parameters -============ -The following parameters can be used when creating a table: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - * - ``CLUSTER BY column_name1 ...`` - - - A commma separated list of clustering column keys. - - See :ref:`data_clustering` for more information. - * - ``LIKE`` - - Duplicates the column structure of an existing table. - - -.. _default_values: - -Default Value Constraints -=============== - -The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. - -The value may be either a literal or **GETDATE()**, which is evaluated at the time the row is created. - -.. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. - -Syntax ---------- -The following is the correct syntax for using the **DEFAULT** value constraints: - - -.. code-block:: postgres - - column_def :: = { column_name type_name [ default ] [ column_constraint ] } - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - - check_specification ::= - CHECK( 'CS compression_spec' ) - - compression_spec ::= - { "default" | "p4d" | "dict" | "rle" | "sequence" | "flat" } - - -.. _identity: - -Identity ------------------------ -The ``Identity`` (or sequence) columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. - -The **identity** property on a column guarantees that each new row inserted is generated based on the current seed & increment. - -.. warning:: - The identity property on a column does not guarantee uniqueness. The identity value can be bypassed by specifying it in an :ref:`insert` command. - -The following table describes the identity parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``start_with`` - - A value that is used for the very first row loaded into the table. - * - ``increment_by`` - - Incremental value that is added to the identity value of the previous row that was loaded. - -Examples -=========== -This section includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Creating a Standard Table ------------------ -The following is an example of the syntax used to create a standard table: - -.. code-block:: postgres - - CREATE TABLE cool_animals ( - id INT NOT NULL, - name varchar(30) NOT NULL, - weight FLOAT, - is_agressive BOOL - ); - -Creating a Table with Default Value Constraints for Some Columns ---------------------------------------------------- -The following is an example of the syntax used to create a table with default value constraints for some columns: - - -.. code-block:: postgres - - CREATE TABLE cool_animals ( - id INT NOT NULL, - name varchar(30) NOT NULL, - weight FLOAT, - is_agressive BOOL DEFAULT false NOT NULL - ); - -.. note:: The nullable/non-nullable constraint appears at the end, after the default option - -Creating a Table with an Identity Column ---------------------------------------------------- -The following is an example of the syntax used to create a table with an identity (auto-increment) column: - - -.. code-block:: postgres - - CREATE TABLE users ( - id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name VARCHAR(30) NOT NULL, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL - ); - -.. note:: - * Identity columns are supported on ``BIGINT`` columns. - - * Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. - -Creating a Table from a SELECT Query ------------------------------------------ -The following is an example of the syntax used to create a table from a SELECT query: - -.. code-block:: postgres - - CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; - -For more information on creating a new table from the results of a SELECT query, see :ref:`CREATE TABLE AS `. - -Creating a Table with a Clustering Key ----------------------------------------------- -When data in a table is stored in a sorted order, the sorted columns are considered clustered. Good clustering can have a significant positive impact on performance. - -In the following example, we expect the ``start_date`` column to be naturally clustered, as new users sign up and get a newer start date. - -When the clustering key is set, if the incoming data isn’t naturally clustered, it will be clustered by SQream DB during insert or bulk load. - -The following is an example of the syntax used to create a table with a clustering key: - -.. code-block:: postgres - - CREATE TABLE users ( - name VARCHAR(30) NOT NULL, - start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY start_date; - -For more information on data clustering, see :ref:`data_clustering`. - -Duplicating the Column Structure of an Existing Table ------------------ - -Syntax -************ -The following is the correct syntax for duplicating the column structure of an existing table: - -.. code-block:: postgres - - CREATE [OR REPLACE] TABLE table_name - { - (column_name column_type [{NULL | NOT NULL}] [,...]) - | LIKE source_table_name - } - [CLUSTER BY ...] - ; - -Examples -************** -This section includes the following examples of duplicating the column structure of an existing table using the ``LIKE`` clause: - -.. contents:: - :local: - :depth: 3 - -Creating a Table Using an Explicit Column List -~~~~~~~~~~~~ -The following is an example of creating a table using an explict column list: - -.. code-block:: postgres - - CREATE TABLE t1(x int default 0 not null, y text(10) null); - -Creating a Second Table Based on the Structure of Another Table -~~~~~~~~~~~~ -Either of the following examples can be used to create a second table based on the structure of another table. - -**Example 1** - -.. code-block:: postgres - - CREATE TABLE t2 LIKE t1; - -**Example 2** - -.. code-block:: postgres - - CREATE TABLE t2(x int default 0 not null, y text(10) null); - -The generated output of both of the statements above is identical. - -Creating a Table based on External Tables and Views -~~~~~~~~~~~~ -The following is example of creating a table based on external tables and views: - - -.. code-block:: postgres - - CREATE VIEW v as SELECT x+1,y,y || 'abc' from t1; - CREATE TABLE t3 LIKE v; - -When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. - -Permissions -============= -The role must have the ``CREATE`` permission at the schema level. diff --git a/reference/sql/sql_statements/ddl_commands/create_table_as.rst b/reference/sql/sql_statements/ddl_commands/create_table_as.rst deleted file mode 100644 index a7f9dd4d4..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_table_as.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. _create_table_as: - -***************** -CREATE TABLE AS -***************** - -The ``CREATE TABLE AS`` commands creates a new table from the result of a select query. - - -Syntax -========== -The following is the correct syntax for creating a table from the result of a select query: - - -.. CREATE [ OR REPLACE ] TABLE [schema_name].table_name ( -.. { column_def [, ...] } -.. ) AS query - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] TABLE [schema_name].table_name AS query - ; - - schema_name ::= identifier - - table_name ::= identifier - - -.. _ctas_params: - -Parameters -============ -The following parameters can be used when creating a table from the result of a select query: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``query`` - - A select query that returns data - -.. * - ``column_def`` -.. - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - -Permissions -============= -The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. - - -Examples -=========== -This section includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Creating a Copy of a Foreign Table or View ---------------------------------------------------------------------------- - -.. code-block:: postgres - - CREATE TABLE users AS SELECT * FROM users_source; - -For more information, see :ref:`CREATE FOREIGN TABLE `. - -Filtering ------------- - -.. code-block:: postgres - - CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; - -Adding Columns ------------------------ - -.. code-block:: postgres - - CREATE TABLE users_uk_new AS SELECT GETDATE() as "Date",*,false as is_new FROM users_uk; - -Creating a Table From Values ------------------------------------------ - -.. code-block:: postgres - - CREATE TABLE new_users - AS VALUES(GETDATE(),'Richard','Foxworthy','1984-03-03',True) diff --git a/reference/sql/sql_statements/ddl_commands/create_view.rst b/reference/sql/sql_statements/ddl_commands/create_view.rst deleted file mode 100644 index 9812ddeec..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_view.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _create_view: - -***************** -CREATE VIEW -***************** - -``CREATE VIEW`` creates a new view in an existing database. A view is a virtual table. - -.. tip:: - * Use views to simplify complex queries or present only partial data to specific roles. - * If an underlying table has changed (new columns, changed names, etc.) - a view may be invalidated. To recompile the view, see :ref:`SELECT RECOMPILE_VIEW(\)` - - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level, as well as ``SELECT`` permissions for any tables referenced by the view. - -Syntax -========== - -.. code-block:: postgres - - create_view_statement ::= - CREATE VIEW [schema_name].view_name [ column_list ] - AS - query - ; - - schema_name ::= identifier - - view_name ::= identifier - - column_list ::= ( { column_name [, ...] } ) - - column_name ::= identifier - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The name of the schema in which to create the view. - * - ``view_name`` - - The name of the view to create, which must be unique inside the schema. - * - ``column_list`` - - An optional comma separated list of column names for the view. If specified, these column names will override the column names in the response of the query in the ``AS query`` statement. - * - ``AS query`` - - The select query to execute when the view is referenced. - -.. * - ``OR REPLACE`` -.. - Create a new view, and overwrite any existing views by the same name. Does not return an error if the view already exists. - -Examples -=========== - -A simple view ------------------ - -.. code-block:: postgres - - CREATE VIEW only_agressive_animals AS - SELECT * FROM cool_animals WHERE is_agressive=true; - - SELECT * FROM only_agressive_animals; - -Overriding default column names ---------------------------------- - -.. code-block:: postgres - - CREATE VIEW only_relaxed_animals (animal_id, animal_name, should_i_worry) AS - SELECT id, name, is_agressive FROM cool_animals WHERE is_agressive=false; diff --git a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst deleted file mode 100644 index 41b10bdfa..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst +++ /dev/null @@ -1,64 +0,0 @@ -.. _drop_clustering_key: - -********************** -DROP CLUSTERING KEY -********************** - -``DROP CLUSTERING KEY`` drops all clustering keys in a table. - -Read our :ref:`data_clustering` guide for more information. - -See also: :ref:`cluster_by`, :ref:`create_table`. - - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]table_name DROP CLUSTERING KEY - ; - - table_name ::= identifier - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``table_name`` - - The table name to apply the change to. - -Usage notes -================= - -Removing clustering keys does not affect existing data. - -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). - - - - -Examples -=========== - -Dropping clustering keys in a table ------------------------------------------ - -.. code-block:: postgres - - ALTER TABLE public.users DROP CLUSTERING KEY - - diff --git a/reference/sql/sql_statements/ddl_commands/drop_column.rst b/reference/sql/sql_statements/ddl_commands/drop_column.rst deleted file mode 100644 index 391367e16..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_column.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. _drop_column: - -********************** -DROP COLUMN -********************** - -``DROP COLUMN`` can be used to remove columns from a table. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - alter_table_drop_column_statement ::= - ALTER TABLE [schema_name.]table_name DROP COLUMN column_name - ; - - table_name ::= identifier - - schema_name ::= identifier - - column_name ::= identifier - - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``table_name`` - - The table name to apply the change to. - * - ``column_name`` - - The column to remove. - -Examples -=========== - -Removing a column ------------------------------------------ - -.. code-block:: postgres - - -- Remove the 'weight' column - ALTER TABLE users DROP COLUMN weight; - -Removing a column with a quoted identifier name ----------------------------------------------------- - -.. code-block:: postgres - - ALTER TABLE users DROP COLUMN "Weight in kilograms"; \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_database.rst b/reference/sql/sql_statements/ddl_commands/drop_database.rst deleted file mode 100644 index 0cfbbcd30..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_database.rst +++ /dev/null @@ -1,63 +0,0 @@ -.. _drop_database: - -********************** -DROP DATABASE -********************** - -``DROP DATABASE`` can be used to remove a database and all of its objects. - -Permissions -============= - -The role must have the ``DDL`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - drop_database_statement ::= - DROP DATABASE database_name - ; - - database_name ::= identifier - - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``database_name`` - - The name of the database to drop. This can not be the current database in use. - -Examples -=========== - -Dropping a database and all of its objects ---------------------------------------------- - -.. code-block:: psql - - master=> DROP DATABASE raviga; - executed - - -Dropping the current database --------------------------------- - -The current database in use can't be dropped. Switch to another database first. - -.. code-block:: psql - - raviga=> DROP DATABASE raviga; - Current open database 'raviga' cannot be dropped. - - raviga=> \c master - master=> DROP DATABASE raviga; - executed \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_function.rst b/reference/sql/sql_statements/ddl_commands/drop_function.rst deleted file mode 100644 index 726085f9f..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_function.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. _drop_function: - -********************** -DROP FUNCTION -********************** - -``DROP FUNCTION`` can be used to remove a user defined function. - -Permissions -============= - -The role must have the ``DDL`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - drop_function_statement ::= - DROP FUNCTION [ IF EXISTS ] function_name(); - ; - - function_name ::= identifier - - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``IF EXISTS`` - - Drop the function if it exists. Does not error if the function does not exist. - * - ``function_name()`` - - The name of the function to drop. - -Examples -=========== - -Dropping a function ---------------------------------------------- - -.. code-block:: postgres - - DROP FUNCTION my_distance(); - - -Dropping a function (always succeeds) -------------------------------------- - -.. code-block:: psql - - farm=> DROP FUNCTION my_distance(); - executed - - farm=> DROP FUNCTION my_distance(); - Function 'my_distance' not found - - -- This will succeed, even though the function does not exist - farm=> DROP FUNCTION IF EXISTS my_distance(); - executed - diff --git a/reference/sql/sql_statements/ddl_commands/drop_schema.rst b/reference/sql/sql_statements/ddl_commands/drop_schema.rst deleted file mode 100644 index c10ab7f8f..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_schema.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _drop_schema: - -********************** -DROP SCHEMA -********************** - -``DROP SCHEMA`` can be used to remove a schema. - -The schema has to be empty before removal. - -SQream DB does not support dropping a schema with objects. - -See also: :ref:`create_schema`, :ref:`alter_default_schema`. - -Permissions -============= - -The role must have the ``DDL`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - drop_schema_statement ::= - DROP SCHEMA schema_name - ; - - schema_name ::= identifier - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The name of the schema to drop - -Examples -=========== - -Dropping a schema ---------------------------------------------- - -.. code-block:: postgres - - DROP SCHEMA test; - -Dropping a schema if it's not empty ----------------------------------------------- - -If a schema contains several tables, SQream DB will alert you that these tables need to be dropped first. - -This prevents accidental dropping of full schemas. - -.. code-block:: psql - - t=> DROP SCHEMA test; - Schema 'test' contains the following objects: - Tables - 'test.foo' , 'test.bar' - Please drop its content and then try again. - -To drop the schema, drop the schema's tables first, and then drop the schema: - -.. code-block:: psql - - t=> DROP TABLE test.foo; - executed - t=> DROP TABLE test.bar; - executed - t=> DROP SCHEMA test; - executed \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_table.rst b/reference/sql/sql_statements/ddl_commands/drop_table.rst deleted file mode 100644 index e2a704ff8..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_table.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. _drop_table: - -********************** -DROP TABLE -********************** - -``DROP TABLE`` can be used to remove a table and all of its contents. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - drop_table_statement ::= - DROP TABLE [ IF EXISTS ] [schema_name.]table_name - ; - - table_name ::= identifier - - schema_name ::= identifier - - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``IF EXISTS`` - - Drop the table if it exists. Does not error if the table does not exist. - * - ``schema_name`` - - The name of the schema from which to drop the table. - * - ``table_name`` - - The name of the table to drop. - -Examples -=========== - -Dropping a table ---------------------------------------------- - -.. code-block:: postgres - - DROP TABLE cool_animals; - - -Dropping a table (always succeeds) -------------------------------------- - -.. code-block:: psql - - farm=> DROP TABLE cool_animals; - executed - - farm=> DROP TABLE cool_animals; - Table 'public.cool_animals' not found - - -- This will succeed, even though the table does not exist - farm=> DROP TABLE IF EXISTS cool_animals; - executed - diff --git a/reference/sql/sql_statements/ddl_commands/drop_view.rst b/reference/sql/sql_statements/ddl_commands/drop_view.rst deleted file mode 100644 index e93629ab4..000000000 --- a/reference/sql/sql_statements/ddl_commands/drop_view.rst +++ /dev/null @@ -1,72 +0,0 @@ -.. _drop_view: - -********************** -DROP VIEW -********************** - -``DROP VIEW`` can be used to remove a view. - -Because a view is logical, this does not affect any data in any of the referenced tables. - -Permissions -============= - -The role must have the ``DDL`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - drop_view_statement ::= - DROP VIEW [ IF EXISTS ] [schema_name.]view_name - ; - - view_name ::= identifier - - schema_name ::= identifier - - - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``IF EXISTS`` - - Drop the view if it exists. Does not error if the view does not exist. - * - ``schema_name`` - - The name of the schema from which to drop the view. - * - ``view_name`` - - The name of the view to drop. - -Examples -=========== - -Dropping a table ---------------------------------------------- - -.. code-block:: postgres - - DROP VIEW angry_animals; - - -Dropping a view (always succeeds) -------------------------------------- - -.. code-block:: psql - - farm=> DROP VIEW angry_animals; - executed - - farm=> DROP VIEW angry_animals; - View 'public.angry_animals' not found - - -- This will succeed, even though the view does not exist - farm=> DROP VIEW IF EXISTS angry_animals; - executed - diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst deleted file mode 100644 index f91933f71..000000000 --- a/reference/sql/sql_statements/ddl_commands/rename_column.rst +++ /dev/null @@ -1,65 +0,0 @@ -.. _rename_column: - -********************** -RENAME COLUMN -********************** - -``RENAME COLUMN`` can be used to rename columns in a table. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - alter_table_rename_column_statement ::= - ALTER TABLE [schema_name.]table_name RENAME COLUMN current_name TO new_name - ; - - table_name ::= identifier - - schema_name ::= identifier - - current_name ::= identifier - - new_name ::= identifier - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``table_name`` - - The table name to apply the change to. - * - ``current_name`` - - The column to rename. - * - ``new_name`` - - The new column name. - -Examples -=========== - -Renaming a column ------------------------------------------ - -.. code-block:: postgres - - -- Remove the 'weight' column - ALTER TABLE users RENAME COLUMN weight TO mass; - -Renaming a quoted name --------------------------- - -.. code-block:: postgres - - ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/rename_table.rst b/reference/sql/sql_statements/ddl_commands/rename_table.rst deleted file mode 100644 index e24ba6efe..000000000 --- a/reference/sql/sql_statements/ddl_commands/rename_table.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. _rename_table: - -********************** -RENAME TABLE -********************** - -``RENAME TABLE`` can be used to rename a table. - -.. warning:: Renaming a table can void existing views that use this table. See more about :ref:`recompiling views `. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - -Syntax -========== - -.. code-block:: postgres - - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]current_name RENAME TO new_name - ; - - current_name ::= identifier - - schema_name ::= identifier - - new_name ::= identifier - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. - * - ``current_name`` - - The table name to apply the change to. - * - ``new_name`` - - The new table name. - -Examples -=========== - -Renaming a table ------------------------------------------ - -.. code-block:: postgres - - ALTER TABLE public.users RENAME TO former_users; - - diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 28096f16a..9525955d2 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -18,48 +18,48 @@ Data Definition Commands (DDL) * - Command - Usage - * - :ref:`ADD COLUMN` - - Add a new column to a table - * - :ref:`ALTER DEFAULT SCHEMA` - - Change the default schema for a role - * - :ref:`ALTER TABLE` - - Change the schema of a table - * - :ref:`CLUSTER BY` - - Change clustering keys in a table - * - :ref:`CREATE DATABASE` - - Create a new database - * - :ref:`CREATE EXTERNAL TABLE` - - Create a new external table in the database (deprecated) - * - :ref:`CREATE FOREIGN TABLE` - - Create a new foreign table in the database - * - :ref:`CREATE FUNCTION ` - - Create a new user defined function in the database - * - :ref:`CREATE SCHEMA` - - Create a new schema in the database - * - :ref:`CREATE TABLE` - - Create a new table in the database - * - :ref:`CREATE TABLE AS` - - Create a new table in the database using results from a select query - * - :ref:`CREATE VIEW` - - Create a new view in the database - * - :ref:`DROP CLUSTERING KEY` - - Drops all clustering keys in a table - * - :ref:`DROP COLUMN` - - Drop a column from a table - * - :ref:`DROP DATABASE` - - Drop a database and all of its objects - * - :ref:`DROP FUNCTION` - - Drop a function - * - :ref:`DROP SCHEMA` - - Drop a schema - * - :ref:`DROP TABLE` - - Drop a table and its contents from a database - * - :ref:`DROP VIEW` - - Drop a view - * - :ref:`RENAME COLUMN` - - Rename a column - * - :ref:`RENAME TABLE` - - Rename a table + * - `ADD COLUMN `_ + - Add a new column to a table + * - `ALTER DEFAULT SCHEMA `_ + - Change the default schema for a role + * - `ALTER TABLE `_ + - Change the schema of a table + * - `CLUSTER BY `_ + - Change clustering keys in a table + * - `CREATE DATABASE `_ + - Create a new database + * - `CREATE EXTERNAL TABLE `_ + - Create a new external table in the database (deprecated) + * - `CREATE FOREIGN TABLE `_ + - Create a new foreign table in the database + * - `CREATE FUNCTION `_ + - Create a new user defined function in the database + * - `CREATE SCHEMA `_ + - Create a new schema in the database + * - `CREATE TABLE `_ + - Create a new table in the database + * - `CREATE TABLE AS `_ + - Create a new table in the database using results from a select query + * - `CREATE VIEW `_ + - Create a new view in the database + * - `DROP CLUSTERING KEY `_ + - Drops all clustering keys in a table + * - `DROP COLUMN `_ + - Drop a column from a table + * - `DROP DATABASE `_ + - Drop a database and all of its objects + * - `DROP FUNCTION `_ + - Drop a function + * - `DROP SCHEMA `_ + - Drop a schema + * - `DROP TABLE `_ + - Drop a table and its contents from a database + * - `DROP VIEW `_ + - Drop a view + * - `RENAME COLUMN `_ + - Rename a column + * - `RENAME TABLE `_ + - Rename a table Data Manipulation Commands (DML) ================================ From 8e2ae851867dcd97e61fdbc6d5b407f49813d3c9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 27 Mar 2022 17:01:05 +0300 Subject: [PATCH 0021/1892] Returned deleted files --- .../ddl_commands/add_column.rst | 91 ++++++ .../ddl_commands/alter_default_schema.rst | 58 ++++ .../ddl_commands/alter_table.rst | 33 ++ .../ddl_commands/cluster_by.rst | 69 ++++ .../ddl_commands/create_database.rst | 55 ++++ .../ddl_commands/create_external_table.rst | 156 +++++++++ .../ddl_commands/create_foreign_table.rst | 165 ++++++++++ .../ddl_commands/create_function.rst | 103 ++++++ .../ddl_commands/create_schema.rst | 92 ++++++ .../ddl_commands/create_table.rst | 296 ++++++++++++++++++ .../ddl_commands/create_table_as.rst | 96 ++++++ .../ddl_commands/create_view.rst | 79 +++++ .../ddl_commands/drop_clustering_key.rst | 64 ++++ .../ddl_commands/drop_column.rst | 63 ++++ .../ddl_commands/drop_database.rst | 63 ++++ .../ddl_commands/drop_function.rst | 66 ++++ .../ddl_commands/drop_schema.rst | 77 +++++ .../ddl_commands/drop_table.rst | 70 +++++ .../sql_statements/ddl_commands/drop_view.rst | 72 +++++ .../ddl_commands/rename_column.rst | 65 ++++ .../ddl_commands/rename_table.rst | 57 ++++ reference/sql/sql_statements/index.rst | 84 ++--- 22 files changed, 1932 insertions(+), 42 deletions(-) create mode 100644 reference/sql/sql_statements/ddl_commands/add_column.rst create mode 100644 reference/sql/sql_statements/ddl_commands/alter_default_schema.rst create mode 100644 reference/sql/sql_statements/ddl_commands/alter_table.rst create mode 100644 reference/sql/sql_statements/ddl_commands/cluster_by.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_database.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_external_table.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_foreign_table.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_function.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_schema.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_table.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_table_as.rst create mode 100644 reference/sql/sql_statements/ddl_commands/create_view.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_column.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_database.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_function.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_schema.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_table.rst create mode 100644 reference/sql/sql_statements/ddl_commands/drop_view.rst create mode 100644 reference/sql/sql_statements/ddl_commands/rename_column.rst create mode 100644 reference/sql/sql_statements/ddl_commands/rename_table.rst diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst new file mode 100644 index 000000000..cec4aec7b --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -0,0 +1,91 @@ +.. _add_column: + +********************** +ADD COLUMN +********************** + +The ``ADD COLUMN`` command is used to add columns to an existing table. + + + +Syntax +========== +The following is the correct syntax for adding a table: + +.. code-block:: postgres + + alter_table_add_column_statement ::= + ALTER TABLE [schema_name.]table_name { ADD COLUMN column_def [, ...] } + ; + + table_name ::= identifier + + schema_name ::= identifier + + column_def :: = { column_name type_name [ default ] [ column_constraint ] } + + column_name ::= identifier + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + DEFAULT default_value + + + +Parameters +============ +The following parameters can be used for adding a table: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``table_name`` + - The table name to apply the change to. + * - ``ADD COLUMN column_def`` + - A comma separated list of ADD COLUMN commands + * - ``column_def`` + - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + +.. note:: + * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. + * A new column added to the table can not contain an IDENTITY or be of the TEXT type. + + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. + +Examples +=========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Adding a Simple Column with a Default Value +----------------------------------------- +This example shows how to add a simple column with a default value: + +.. code-block:: postgres + + ALTER TABLE cool_animals + ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; + + +Adding Several Columns in One Command +------------------------------------------- +This example shows how to add several columns in one command: + +.. code-block:: postgres + + ALTER TABLE cool_animals + ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, + ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; diff --git a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst new file mode 100644 index 000000000..bca483060 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst @@ -0,0 +1,58 @@ +.. _alter_default_schema: + +********************** +ALTER DEFAULT SCHEMA +********************** + +The ``ALTER DEFAULT SCHEMA`` command can be used to change a role's default schema. The default schema in SQream is ``public``. + +For more information, see :ref:`create_schema` and :ref:`drop_schema`. + + + +Syntax +========== +The following is the correct syntax for altering a default schema: + +.. code-block:: postgres + + alter_default_schema_statement ::= + ALTER DEFAULT SCHEMA FOR role_name TO schema_name + ; + + role_name ::= identifier + + schema_name ::= identifier + + + +Parameters +============ +The following parameters can be used when altering a default schema: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``role_name`` + - The name of the role the change will apply to. + * - ``schema_name`` + - The new default schema name. + +Permissions +============= +No special permissions are required. + +Examples +=========== +This section includes an example of **altering the default schema for a role**: + +.. code-block:: postgres + + SELECT * FROM users; -- Refers to public.users + + ALTER DEFAULT SCHEMA FOR bgilfoyle TO staging; + + SELECT * FROM users; -- Now refers to staging.users, rather than public.users diff --git a/reference/sql/sql_statements/ddl_commands/alter_table.rst b/reference/sql/sql_statements/ddl_commands/alter_table.rst new file mode 100644 index 000000000..4046a31fe --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/alter_table.rst @@ -0,0 +1,33 @@ +.. _alter_table: + +********************** +ALTER TABLE +********************** +You can use the ``ALTER TABLE`` command to make schema changes to a table, and can be used in conjunction with several sub-commands. + +Locks +======= +Making changes to a schema makes an exclusive lock on tables. While these operations do not typically take much time, other statements may have to wait until the schema changes are completed. + +Sub-Commands +============== +The following table shows the sub-commands that can be used with the ``ALTER TABLE`` command: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Command + - Usage + * - :ref:`ADD COLUMN` + - Adds a new column to a table. + * - :ref:`DROP COLUMN` + - Drops a column from a table. + * - :ref:`RENAME COLUMN` + - Renames a column. + * - :ref:`RENAME TABLE` + - Renames a table. + * - :ref:`CLUSTER BY` + - Modifies (adds or reorders) the clustering keys in a table. + * - :ref:`DROP CLUSTERING KEY` + - Drops all clustering keys. diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst new file mode 100644 index 000000000..2a389e254 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -0,0 +1,69 @@ +.. _cluster_by: + +********************** +CLUSTER BY +********************** + +``CLUSTER BY`` can be used to change clustering keys in a table. + + +Read our :ref:`data_clustering` guide for more information. + +See also: :ref:`drop_clustering_key`, :ref:`create_table`. + + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + alter_table_rename_table_statement ::= + ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] + ; + + table_name ::= identifier + + column_name ::= identifier + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``table_name`` + - The table name to apply the change to. + * - ``column_name [, ... ]`` + - Comma separated list of columns to create clustering keys for + + +Usage notes +================= + +Removing clustering keys does not affect existing data. + +To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). + + +Examples +=========== + +Reclustering a table +----------------------------------------- + +.. code-block:: postgres + + ALTER TABLE public.users CLUSTER BY start_date; + + diff --git a/reference/sql/sql_statements/ddl_commands/create_database.rst b/reference/sql/sql_statements/ddl_commands/create_database.rst new file mode 100644 index 000000000..a0496feb2 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_database.rst @@ -0,0 +1,55 @@ +.. _create_database: + +***************** +CREATE DATABASE +***************** + +``CREATE DATABASE`` creates a new database in SQream. + +Permissions +============= + +Only a superuser can create a new database + +Syntax +========== + +.. code-block:: postgres + + create_database_statement ::= + + CREATE DATABASE database_name ; + + database_name ::= identifier + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The name of the database name. The database name must be unique, and follows :ref:`Identifier rules ` + +Examples +=========== + +.. code-block:: postgres + + CREATE DATABASE raviga; + +.. code-block:: postgres + + CREATE DATABASE my_db; + +If the database already exists, an error will appear: + +.. code-block:: psql + + master=> CREATE DATABASE MY_DB; + Database 'my_db' already exists + +.. note:: SQream DB :ref:`identifiers ` are always converted to lowercase, so ``my_db`` is the same as ``MY_DB``, unless explicitly quoted as ``"MY_DB"``. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/create_external_table.rst b/reference/sql/sql_statements/ddl_commands/create_external_table.rst new file mode 100644 index 000000000..7674889a6 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_external_table.rst @@ -0,0 +1,156 @@ +.. _create_external_table: + +*********************** +CREATE EXTERNAL TABLE +*********************** + +.. warning:: + + The ``CREATE EXTERNAL TABLE`` syntax is deprecated, and will be removed in future versions. + + Starting with SQream DB v2020.2, external tables have been renamed to :ref:`foreign tables`, and use a more flexible foreign data wrapper concept. See :ref:`create_foreign_table` instead. + + Upgrading to a new version of SQream DB converts existing tables automatically. When creating a new external tables, use the new foreign table syntax. + + +``CREATE TABLE`` creates a new external table in an existing database. + +See more in the :ref:`External tables guide`. + +.. tip:: + + * Data in an external table can change if the sources change, and frequent access to remote files may harm performance. + + * To create a regular table, see :ref:`CREATE TABLE ` + +Permissions +============= + +The role must have the ``CREATE`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + create_table_statement ::= + CREATE [ OR REPLACE ] EXTERNAL TABLE [schema_name].table_name ( + { column_def [, ...] } + ) + USING FORMAT format_def + WITH { external_table_option [ ...] } + ; + + schema_name ::= identifier + + table_name ::= identifier + + format_def ::= { PARQUET | ORC | CSV } + + external_table_option ::= { + PATH '{ path_spec }' + | FIELD DELIMITER '{ field_delimiter }' + | RECORD DELIMITER '{ record_delimiter }' + | AWS_ID '{ AWS ID }' + | AWS_SECRET '{ AWS SECRET }' + } + + path_spec ::= { local filepath | S3 URI | HDFS URI } + + field_delimiter ::= delimiter_character + + record_delimiter ::= delimiter_character + + column_def ::= { column_name type_name [ default ] [ column_constraint ] } + + column_name ::= identifier + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] + +.. _cet_parameters: + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``OR REPLACE`` + - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``schema_name`` + - The name of the schema in which to create the table. + * - ``table_name`` + - The name of the table to create, which must be unique inside the schema. + * - ``column_def`` + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + * - ``USING FORMAT ...`` + - Specifies the format of the source files, such as ``PARQUET``, ``ORC``, or ``CSV``. + * - ``WITH PATH ...`` + - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. + * - ``FIELD DELIMITER`` + - Specifies the field delimiter for CSV files. Defaults to ``,``. + * - ``RECORD DELIMITER`` + - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` + * - ``AWS_ID``, ``AWS_SECRET`` + - Credentials for authenticated S3 access + + +Examples +=========== + +A simple table from Tab-delimited file (TSV) +---------------------------------------------- + +.. code-block:: postgres + + CREATE OR REPLACE EXTERNAL TABLE cool_animals + (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) + USING FORMAT csv + WITH PATH '/home/rhendricks/cool_animals.csv' + FIELD DELIMITER '\t'; + + +A table from a directory of Parquet files on HDFS +----------------------------------------------------- + +.. code-block:: postgres + + CREATE EXTERNAL TABLE users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + USING FORMAT Parquet + WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet'; + +A table from a bucket of files on S3 +-------------------------------------- + +.. code-block:: postgres + + CREATE EXTERNAL TABLE users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + USING FORMAT Parquet + WITH PATH 's3://pp-secret-bucket/users/*.parquet' + AWS_ID 'our_aws_id' + AWS_SECRET 'our_aws_secret'; + + +Changing an external table to a regular table +------------------------------------------------ + +Materializes an external table into a regular table. + +.. tip: Using an external table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files + +.. code-block:: postgres + + CREATE TABLE real_table + AS SELECT * FROM external_table; + diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst new file mode 100644 index 000000000..3a766852a --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -0,0 +1,165 @@ +.. _create_foreign_table: + +*********************** +CREATE FOREIGN TABLE +*********************** + +.. note:: + + Starting with SQream DB v2020.2, external tables have been renamed to foreign tables, and use a more flexible foreign data wrapper concept. + + Upgrading to a new version of SQream DB converts existing external tables automatically. + + +``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. + +See more in the :ref:`Foreign tables guide`. + +.. tip:: + + * Data in a foreign table can change if the sources change, and frequent access to remote files may harm performance. + + * To create a regular table, see :ref:`CREATE TABLE ` + +Permissions +============= + +The role must have the ``CREATE`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + create_table_statement ::= + CREATE [ OR REPLACE ] FOREIGN TABLE [schema_name].table_name ( + { column_def [, ...] } + ) + [ FOREIGN DATA ] WRAPPER fdw_name + [ OPTIONS ( option_def [, ... ] ) ] + ; + + schema_name ::= identifier + + table_name ::= identifier + + fdw_name ::= + { csv_fdw | orc_fdw | parquet_fdw } + + option_def ::= + { + LOCATION = '{ path_spec }' + | DELIMITER = '{ field_delimiter }' -- for CSV only + | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only + | AWS_ID '{ AWS ID }' + | AWS_SECRET '{ AWS SECRET }' + } + + path_spec ::= { local filepath | S3 URI | HDFS URI } + + field_delimiter ::= delimiter_character + + record_delimiter ::= delimiter_character + + column_def ::= + { column_name type_name [ default ] [ column_constraint ] } + + column_name ::= identifier + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] + +.. _cft_parameters: + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``OR REPLACE`` + - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``schema_name`` + - The name of the schema in which to create the table. + * - ``table_name`` + - The name of the table to create, which must be unique inside the schema. + * - ``column_def`` + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + * - ``WRAPPER ...`` + - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, or ``csv_fdw``. + * - ``LOCATION = ...`` + - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. + * - ``DELIMITER = ...`` + - Specifies the field delimiter for CSV files. Defaults to ``,``. + * - ``RECORD_DELIMITER = ...`` + - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` + * - ``AWS_ID``, ``AWS_SECRET`` + - Credentials for authenticated S3 access + + +Examples +=========== + +A simple table from Tab-delimited file (TSV) +---------------------------------------------- + +.. code-block:: postgres + + CREATE OR REPLACE FOREIGN TABLE cool_animals + (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) + WRAPPER csv_fdw + OPTIONS + ( LOCATION = '/home/rhendricks/cool_animals.csv', + DELIMITER = '\t' + ) + ; + + +A table from a directory of Parquet files on HDFS +----------------------------------------------------- + +.. code-block:: postgres + + CREATE FOREIGN TABLE users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + +A table from a bucket of ORC files on S3 +------------------------------------------ + +.. code-block:: postgres + + CREATE FOREIGN TABLE users + (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + WRAPPER orc_fdw + OPTIONS + ( + LOCATION = 's3://pp-secret-bucket/users/*.orc', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + +Changing a foreign table to a regular table +------------------------------------------------ + +Materializes a foreign table into a regular table. + +.. tip: Using a foreign table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files + +.. code-block:: postgres + + CREATE TABLE real_table + AS SELECT * FROM some_foreign_table; + diff --git a/reference/sql/sql_statements/ddl_commands/create_function.rst b/reference/sql/sql_statements/ddl_commands/create_function.rst new file mode 100644 index 000000000..971b51298 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_function.rst @@ -0,0 +1,103 @@ +.. _create_function: + +***************** +CREATE FUNCTION +***************** + +``CREATE FUNCTION`` creates a new user-defined function (UDF) in an existing database. + +See more in our :ref:`Python UDF (user-defined functions)` guide. + +Permissions +============= + +The role must have the ``CREATE FUNCTION`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + create_function_statement ::= + CREATE [ OR REPLACE ] FUNCTION function_name (argument_list) + RETURNS return_type + AS $$ + { function_body } + $$ LANGUAGE python + ; + + function_name ::= identifier + + argument_list :: = { value_name type_name [, ...] } + + value_name ::= identifier + + return_type ::= type_name + + function_body ::= Valid Python code + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``OR REPLACE`` + - Create a new function, and overwrite any existing function by the same name. Does not return an error if the function already exists. ``CREATE OR REPLACE`` does not check the function contents or structure, only the function name. + * - ``function_name`` + - The name of the function to create, which must be unique inside the database. + * - ``argument_list`` + - A comma separated list of column definitions. A column definition includes a name identifier and a datatype. + * - ``return_type`` + - The SQL datatype of the return value, such as ``INT``, ``VARCHAR``, etc. + * - ``function_body`` + - Python code, dollar-quoted (``$$``). + +Examples +=========== + +Calculate distance between two points +-------------------------------------- + +.. code-block:: postgres + + CREATE OR REPLACE FUNCTION my_distance (x1 float, y1 float, x2 float, y2 float) + RETURNS FLOAT + AS $$ + import math + if y1 < x1: + return 0.0 + else: + return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) + $$ LANGUAGE PYTHON; + + -- Usage: + SELECT city, my_location, my_distance(x1,y1,x2,y2) from cities; + + +Calling files from other locations +--------------------------------------- + +.. code-block:: postgres + + -- Our script my_code.py is in ~/my_python_stuff + + CREATE FUNCTION write_log() + RETURNS INT + AS $$ + import sys + sys.path.append("/home/user/my_python_stuff") + + import my_code as f + + f.main() + + return 1 + + $$ LANGUAGE PYTHON; + + -- Usage: + SELECT write_log(); diff --git a/reference/sql/sql_statements/ddl_commands/create_schema.rst b/reference/sql/sql_statements/ddl_commands/create_schema.rst new file mode 100644 index 000000000..aefa64b4f --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_schema.rst @@ -0,0 +1,92 @@ +.. _create_schema: + +***************** +CREATE SCHEMA +***************** +The **CREATE SCHEMA** page describes the following: + + +.. contents:: + :local: + :depth: 2 + +Overview +============ + +``CREATE SCHEMA`` creates a new schema in an existing database. A schema is a virtual space for storing tables. + +The default schema in SQream DB is ``public``. + +.. tip:: Use schemas to separate between use-cases, such as staging and production. + +The **CREATE SCHEMA** statement can be used to query tables from different schemas without providing an alias, as in the following example: + +.. code-block:: postgres + + select .table_name.column_name from .table_name + +See also: :ref:`drop_schema`, :ref:`alter_default_schema`. + +Permissions +============= + +The role must have the ``CREATE`` permission at the database level. + +Syntax +========== +The following example shows the correct syntax for creating a schema: + +.. code-block:: postgres + + create_schema_statement ::= + CREATE SCHEMA schema_name + ; + + schema_name ::= identifier + + +Parameters +============ +The following table shows the ``schema_name`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema to create. + +Examples +=========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + + +Creating a Schema +-------------------- +The following example shows an example of the syntax for creating a schema: + +.. code-block:: postgres + + CREATE SCHEMA staging; + + CREATE TABLE staging.users AS SELECT * FROM public.users; + + SELECT * FROM staging.users; + +Altering the Default Schema for a Role +----------------------------------------- +The following example shows an example of the syntax for altering the default schema for a role: + +.. code-block:: postgres + + SELECT * FROM users; -- Refers to public.users + + ALTER DEFAULT SCHEMA FOR bgilfoyle TO staging; + + SELECT * FROM users; -- Now refers to staging.users, rather than public.users diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst new file mode 100644 index 000000000..10b1a9836 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -0,0 +1,296 @@ +.. _create_table: + +***************** +CREATE TABLE +***************** + +The ``CREATE TABLE`` statement is used to create a new table in an existing database. + +.. tip:: + * To create a table based on the result of a select query, see :ref:`CREATE TABLE AS `. + * To create a table based on files like Parquet and ORC, see :ref:`CREATE FOREIGN TABLE ` + + + +Syntax +========== +The following is the correct syntax for creating a table: + +.. code-block:: postgres + + create_table_statement ::= + CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( + { column_def [, ...] } + ) + [ CLUSTER BY { column_name [, ...] } ] + ; + + schema_name ::= identifier + + table_name ::= identifier + + column_def :: = { column_name type_name [ default ] [ column_constraint ] } + + column_name ::= identifier + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] + +Parameters +============ +The following parameters can be used when creating a table: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``OR REPLACE`` + - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``schema_name`` + - The name of the schema in which to create the table. + * - ``table_name`` + - The name of the table to create, which must be unique inside the schema. + * - ``column_def`` + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + * - ``CLUSTER BY column_name1 ...`` + - + A commma separated list of clustering column keys. + + See :ref:`data_clustering` for more information. + * - ``LIKE`` + - Duplicates the column structure of an existing table. + + +.. _default_values: + +Default Value Constraints +=============== + +The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. + +The value may be a literal, which is evaluated at the time the row is created. + +.. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. + +Syntax +--------- +The following is the correct syntax for using the **DEFAULT** value constraints: + + +.. code-block:: postgres + + column_def :: = { column_name type_name [ default ] [ column_constraint ] } + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] + + check_specification ::= + CHECK( 'CS compression_spec' ) + + compression_spec ::= + { "default" | "p4d" | "dict" | "rle" | "sequence" | "flat" } + + +.. _identity: + +Identity +----------------------- +The ``Identity`` (or sequence) columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. + +The **identity** property on a column guarantees that each new row inserted is generated based on the current seed & increment. + +.. warning:: + The identity property on a column does not guarantee uniqueness. The identity value can be bypassed by specifying it in an :ref:`insert` command. + +The following table describes the identity parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``start_with`` + - A value that is used for the very first row loaded into the table. + * - ``increment_by`` + - Incremental value that is added to the identity value of the previous row that was loaded. + +Examples +=========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Creating a Standard Table +----------------- +The following is an example of the syntax used to create a standard table: + +.. code-block:: postgres + + CREATE TABLE cool_animals ( + id INT NOT NULL, + name varchar(30) NOT NULL, + weight FLOAT, + is_agressive BOOL + ); + +Creating a Table with Default Value Constraints for Some Columns +--------------------------------------------------- +The following is an example of the syntax used to create a table with default value constraints for some columns: + + +.. code-block:: postgres + + CREATE TABLE cool_animals ( + id INT NOT NULL, + name varchar(30) NOT NULL, + weight FLOAT, + is_agressive BOOL DEFAULT false NOT NULL + ); + +.. note:: The nullable/non-nullable constraint appears at the end, after the default option + +Creating a Table with an Identity Column +--------------------------------------------------- +The following is an example of the syntax used to create a table with an identity (auto-increment) column: + + +.. code-block:: postgres + + CREATE TABLE users ( + id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 + name VARCHAR(30) NOT NULL, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + ); + +.. note:: + * Identity columns are supported on ``BIGINT`` columns. + + * Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. + +Creating a Table from a SELECT Query +----------------------------------------- +The following is an example of the syntax used to create a table from a SELECT query: + +.. code-block:: postgres + + CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; + +For more information on creating a new table from the results of a SELECT query, see :ref:`CREATE TABLE AS `. + +Creating a Table with a Clustering Key +---------------------------------------------- +When data in a table is stored in a sorted order, the sorted columns are considered clustered. Good clustering can have a significant positive impact on performance. + +In the following example, we expect the ``start_date`` column to be naturally clustered, as new users sign up and get a newer start date. + +When the clustering key is set, if the incoming data isn’t naturally clustered, it will be clustered by SQream DB during insert or bulk load. + +The following is an example of the syntax used to create a table with a clustering key: + +.. code-block:: postgres + + CREATE TABLE users ( + name VARCHAR(30) NOT NULL, + start_date datetime not null, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + ) CLUSTER BY start_date; + +For more information on data clustering, see :ref:`data_clustering`. + +Duplicating the Column Structure of an Existing Table +----------------- + +Syntax +************ +The following is the correct syntax for duplicating the column structure of an existing table: + +.. code-block:: postgres + + CREATE [OR REPLACE] TABLE table_name + { + (column_name column_type [{NULL | NOT NULL}] [,...]) + | LIKE source_table_name + } + [CLUSTER BY ...] + ; + +Examples +************** +This section includes the following examples of duplicating the column structure of an existing table using the ``LIKE`` clause: + +.. contents:: + :local: + :depth: 3 + +Creating a Table Using an Explicit Column List +~~~~~~~~~~~~ +The following is an example of creating a table using an explict column list: + +.. code-block:: postgres + + CREATE TABLE t1(x int default 0 not null, y text(10) null); + +Creating a Second Table Based on the Structure of Another Table +~~~~~~~~~~~~ +Either of the following examples can be used to create a second table based on the structure of another table. + +**Example 1** + +.. code-block:: postgres + + CREATE TABLE t2 LIKE t1; + +**Example 2** + +.. code-block:: postgres + + CREATE TABLE t2(x int default 0 not null, y text(10) null); + +The generated output of both of the statements above is identical. + +Creating a Table based on External Tables and Views +~~~~~~~~~~~~ +The following is example of creating a table based on external tables and views: + + +.. code-block:: postgres + + CREATE VIEW v as SELECT x+1,y,y || 'abc' from t1; + CREATE TABLE t3 LIKE v; + +When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. + +The following table describes the properties that must be copied from the target table: + ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| **Property** | **Native Table** | **External Table** | **View** | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Column names | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Column types | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| ``NULL``/``NOT NULL`` | Must be copied | Must be copied | Must be copied | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| ``text`` length constraints | Must be copied | Must be copied | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Compression specification | Must be copied | Does not exist in source object | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ +| Default/identity | Must be copied | Does not exist in source object | Does not exist in source object | ++-----------------------------+------------------+---------------------------------+---------------------------------+ + +Permissions +============= +The role must have the ``CREATE`` permission at the schema level. diff --git a/reference/sql/sql_statements/ddl_commands/create_table_as.rst b/reference/sql/sql_statements/ddl_commands/create_table_as.rst new file mode 100644 index 000000000..c0d941f21 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_table_as.rst @@ -0,0 +1,96 @@ +.. _create_table_as: + +***************** +CREATE TABLE AS +***************** + +The ``CREATE TABLE AS`` commands creates a new table from the result of a select query. + + +Syntax +========== +The following is the correct syntax for creating a table from the result of a select query: + + +.. CREATE [ OR REPLACE ] TABLE [schema_name].table_name ( +.. { column_def [, ...] } +.. ) AS query + +.. code-block:: postgres + + create_table_statement ::= + CREATE [ OR REPLACE ] TABLE [schema_name].table_name AS query + ; + + schema_name ::= identifier + + table_name ::= identifier + + +.. _ctas_params: + +Parameters +============ +The following parameters can be used when creating a table from the result of a select query: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``OR REPLACE`` + - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``schema_name`` + - The name of the schema in which to create the table. + * - ``table_name`` + - The name of the table to create, which must be unique inside the schema. + * - ``query`` + - A select query that returns data + +.. * - ``column_def`` +.. - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + +Permissions +============= +The role must have the ``CREATE`` permission at the schema level, as well as ``SELECT`` permissions for any tables referenced by the statement. + + +Examples +=========== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Creating a Copy of a Foreign Table or View +--------------------------------------------------------------------------- + +.. code-block:: postgres + + CREATE TABLE users AS SELECT * FROM users_source; + +For more information, see :ref:`CREATE FOREIGN TABLE `. + +Filtering +------------ + +.. code-block:: postgres + + CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; + +Adding Columns +----------------------- + +.. code-block:: postgres + + CREATE TABLE users_uk_new AS SELECT GETDATE() as "Date",*,false as is_new FROM users_uk; + +Creating a Table From Values +----------------------------------------- + +.. code-block:: postgres + + CREATE TABLE new_users + AS VALUES(GETDATE(),'Richard','Foxworthy','1984-03-03',True) diff --git a/reference/sql/sql_statements/ddl_commands/create_view.rst b/reference/sql/sql_statements/ddl_commands/create_view.rst new file mode 100644 index 000000000..4c6a98427 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/create_view.rst @@ -0,0 +1,79 @@ +.. _create_view: + +***************** +CREATE VIEW +***************** + +``CREATE VIEW`` creates a new view in an existing database. A view is a virtual table. + +.. tip:: + * Use views to simplify complex queries or present only partial data to specific roles. + * If an underlying table has changed (new columns, changed names, etc.) - a view may be invalidated. To recompile the view, see :ref:`SELECT RECOMPILE_VIEW(\)` + + +Permissions +============= + +The role must have the ``CREATE`` permission at the database level, as well as ``SELECT`` permissions for any tables referenced by the view. + +Syntax +========== + +.. code-block:: postgres + + create_view_statement ::= + CREATE VIEW [schema_name].view_name [ column_list ] + AS + query + ; + + schema_name ::= identifier + + view_name ::= identifier + + column_list ::= ( { column_name [, ...] } ) + + column_name ::= identifier + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema in which to create the view. + * - ``view_name`` + - The name of the view to create, which must be unique inside the schema. + * - ``column_list`` + - An optional comma separated list of column names for the view. If specified, these column names will override the column names in the response of the query in the ``AS query`` statement. + * - ``AS query`` + - The select query to execute when the view is referenced. + +.. * - ``OR REPLACE`` +.. - Create a new view, and overwrite any existing views by the same name. Does not return an error if the view already exists. + +Examples +=========== + +A simple view +----------------- + +.. code-block:: postgres + + CREATE VIEW only_agressive_animals AS + SELECT * FROM cool_animals WHERE is_agressive=true; + + SELECT * FROM only_agressive_animals; + +Overriding default column names +--------------------------------- + +.. code-block:: postgres + + CREATE VIEW only_relaxed_animals (animal_id, animal_name, should_i_worry) AS + SELECT id, name, is_agressive FROM cool_animals WHERE is_agressive=false; diff --git a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst new file mode 100644 index 000000000..06cb848ad --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst @@ -0,0 +1,64 @@ +.. _drop_clustering_key: + +********************** +DROP CLUSTERING KEY +********************** + +``DROP CLUSTERING KEY`` drops all clustering keys in a table. + +Read our :ref:`data_clustering` guide for more information. + +See also: :ref:`cluster_by`, :ref:`create_table`. + + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + alter_table_rename_table_statement ::= + ALTER TABLE [schema_name.]table_name DROP CLUSTERING KEY + ; + + table_name ::= identifier + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``table_name`` + - The table name to apply the change to. + +Usage notes +================= + +Removing clustering keys does not affect existing data. + +To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). + + + + +Examples +=========== + +Dropping clustering keys in a table +----------------------------------------- + +.. code-block:: postgres + + ALTER TABLE public.users DROP CLUSTERING KEY + + diff --git a/reference/sql/sql_statements/ddl_commands/drop_column.rst b/reference/sql/sql_statements/ddl_commands/drop_column.rst new file mode 100644 index 000000000..f4c4e4504 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_column.rst @@ -0,0 +1,63 @@ +.. _drop_column: + +********************** +DROP COLUMN +********************** + +``DROP COLUMN`` can be used to remove columns from a table. + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + alter_table_drop_column_statement ::= + ALTER TABLE [schema_name.]table_name DROP COLUMN column_name + ; + + table_name ::= identifier + + schema_name ::= identifier + + column_name ::= identifier + + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``table_name`` + - The table name to apply the change to. + * - ``column_name`` + - The column to remove. + +Examples +=========== + +Removing a column +----------------------------------------- + +.. code-block:: postgres + + -- Remove the 'weight' column + ALTER TABLE users DROP COLUMN weight; + +Removing a column with a quoted identifier name +---------------------------------------------------- + +.. code-block:: postgres + + ALTER TABLE users DROP COLUMN "Weight in kilograms"; \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_database.rst b/reference/sql/sql_statements/ddl_commands/drop_database.rst new file mode 100644 index 000000000..f45b0a5c4 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_database.rst @@ -0,0 +1,63 @@ +.. _drop_database: + +********************** +DROP DATABASE +********************** + +``DROP DATABASE`` can be used to remove a database and all of its objects. + +Permissions +============= + +The role must have the ``DDL`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + drop_database_statement ::= + DROP DATABASE database_name + ; + + database_name ::= identifier + + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The name of the database to drop. This can not be the current database in use. + +Examples +=========== + +Dropping a database and all of its objects +--------------------------------------------- + +.. code-block:: psql + + master=> DROP DATABASE raviga; + executed + + +Dropping the current database +-------------------------------- + +The current database in use can't be dropped. Switch to another database first. + +.. code-block:: psql + + raviga=> DROP DATABASE raviga; + Current open database 'raviga' cannot be dropped. + + raviga=> \c master + master=> DROP DATABASE raviga; + executed \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_function.rst b/reference/sql/sql_statements/ddl_commands/drop_function.rst new file mode 100644 index 000000000..98b957ad8 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_function.rst @@ -0,0 +1,66 @@ +.. _drop_function: + +********************** +DROP FUNCTION +********************** + +``DROP FUNCTION`` can be used to remove a user defined function. + +Permissions +============= + +The role must have the ``DDL`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + drop_function_statement ::= + DROP FUNCTION [ IF EXISTS ] function_name(); + ; + + function_name ::= identifier + + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``IF EXISTS`` + - Drop the function if it exists. Does not error if the function does not exist. + * - ``function_name()`` + - The name of the function to drop. + +Examples +=========== + +Dropping a function +--------------------------------------------- + +.. code-block:: postgres + + DROP FUNCTION my_distance(); + + +Dropping a function (always succeeds) +------------------------------------- + +.. code-block:: psql + + farm=> DROP FUNCTION my_distance(); + executed + + farm=> DROP FUNCTION my_distance(); + Function 'my_distance' not found + + -- This will succeed, even though the function does not exist + farm=> DROP FUNCTION IF EXISTS my_distance(); + executed + diff --git a/reference/sql/sql_statements/ddl_commands/drop_schema.rst b/reference/sql/sql_statements/ddl_commands/drop_schema.rst new file mode 100644 index 000000000..0f2dfd454 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_schema.rst @@ -0,0 +1,77 @@ +.. _drop_schema: + +********************** +DROP SCHEMA +********************** + +``DROP SCHEMA`` can be used to remove a schema. + +The schema has to be empty before removal. + +SQream DB does not support dropping a schema with objects. + +See also: :ref:`create_schema`, :ref:`alter_default_schema`. + +Permissions +============= + +The role must have the ``DDL`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + drop_schema_statement ::= + DROP SCHEMA schema_name + ; + + schema_name ::= identifier + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema to drop + +Examples +=========== + +Dropping a schema +--------------------------------------------- + +.. code-block:: postgres + + DROP SCHEMA test; + +Dropping a schema if it's not empty +---------------------------------------------- + +If a schema contains several tables, SQream DB will alert you that these tables need to be dropped first. + +This prevents accidental dropping of full schemas. + +.. code-block:: psql + + t=> DROP SCHEMA test; + Schema 'test' contains the following objects: + Tables - 'test.foo' , 'test.bar' + Please drop its content and then try again. + +To drop the schema, drop the schema's tables first, and then drop the schema: + +.. code-block:: psql + + t=> DROP TABLE test.foo; + executed + t=> DROP TABLE test.bar; + executed + t=> DROP SCHEMA test; + executed \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_table.rst b/reference/sql/sql_statements/ddl_commands/drop_table.rst new file mode 100644 index 000000000..53fdc8445 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_table.rst @@ -0,0 +1,70 @@ +.. _drop_table: + +********************** +DROP TABLE +********************** + +``DROP TABLE`` can be used to remove a table and all of its contents. + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + drop_table_statement ::= + DROP TABLE [ IF EXISTS ] [schema_name.]table_name + ; + + table_name ::= identifier + + schema_name ::= identifier + + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``IF EXISTS`` + - Drop the table if it exists. Does not error if the table does not exist. + * - ``schema_name`` + - The name of the schema from which to drop the table. + * - ``table_name`` + - The name of the table to drop. + +Examples +=========== + +Dropping a table +--------------------------------------------- + +.. code-block:: postgres + + DROP TABLE cool_animals; + + +Dropping a table (always succeeds) +------------------------------------- + +.. code-block:: psql + + farm=> DROP TABLE cool_animals; + executed + + farm=> DROP TABLE cool_animals; + Table 'public.cool_animals' not found + + -- This will succeed, even though the table does not exist + farm=> DROP TABLE IF EXISTS cool_animals; + executed + diff --git a/reference/sql/sql_statements/ddl_commands/drop_view.rst b/reference/sql/sql_statements/ddl_commands/drop_view.rst new file mode 100644 index 000000000..6e18254e6 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/drop_view.rst @@ -0,0 +1,72 @@ +.. _drop_view: + +********************** +DROP VIEW +********************** + +``DROP VIEW`` can be used to remove a view. + +Because a view is logical, this does not affect any data in any of the referenced tables. + +Permissions +============= + +The role must have the ``DDL`` permission at the database level. + +Syntax +========== + +.. code-block:: postgres + + drop_view_statement ::= + DROP VIEW [ IF EXISTS ] [schema_name.]view_name + ; + + view_name ::= identifier + + schema_name ::= identifier + + + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``IF EXISTS`` + - Drop the view if it exists. Does not error if the view does not exist. + * - ``schema_name`` + - The name of the schema from which to drop the view. + * - ``view_name`` + - The name of the view to drop. + +Examples +=========== + +Dropping a table +--------------------------------------------- + +.. code-block:: postgres + + DROP VIEW angry_animals; + + +Dropping a view (always succeeds) +------------------------------------- + +.. code-block:: psql + + farm=> DROP VIEW angry_animals; + executed + + farm=> DROP VIEW angry_animals; + View 'public.angry_animals' not found + + -- This will succeed, even though the view does not exist + farm=> DROP VIEW IF EXISTS angry_animals; + executed + diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst new file mode 100644 index 000000000..41f1e1628 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/rename_column.rst @@ -0,0 +1,65 @@ +.. _rename_column: + +********************** +RENAME COLUMN +********************** + +``RENAME COLUMN`` can be used to rename columns in a table. + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + alter_table_rename_column_statement ::= + ALTER TABLE [schema_name.]table_name RENAME COLUMN current_name TO new_name + ; + + table_name ::= identifier + + schema_name ::= identifier + + current_name ::= identifier + + new_name ::= identifier + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``table_name`` + - The table name to apply the change to. + * - ``current_name`` + - The column to rename. + * - ``new_name`` + - The new column name. + +Examples +=========== + +Renaming a column +----------------------------------------- + +.. code-block:: postgres + + -- Remove the 'weight' column + ALTER TABLE users RENAME COLUMN weight TO mass; + +Renaming a quoted name +-------------------------- + +.. code-block:: postgres + + ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/rename_table.rst b/reference/sql/sql_statements/ddl_commands/rename_table.rst new file mode 100644 index 000000000..96cc7102e --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/rename_table.rst @@ -0,0 +1,57 @@ +.. _rename_table: + +********************** +RENAME TABLE +********************** + +``RENAME TABLE`` can be used to rename a table. + +.. warning:: Renaming a table can void existing views that use this table. See more about :ref:`recompiling views `. + +Permissions +============= + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +========== + +.. code-block:: postgres + + alter_table_rename_table_statement ::= + ALTER TABLE [schema_name.]current_name RENAME TO new_name + ; + + current_name ::= identifier + + schema_name ::= identifier + + new_name ::= identifier + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. + * - ``current_name`` + - The table name to apply the change to. + * - ``new_name`` + - The new table name. + +Examples +=========== + +Renaming a table +----------------------------------------- + +.. code-block:: postgres + + ALTER TABLE public.users RENAME TO former_users; + + diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 9525955d2..a8e27cb6e 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -18,48 +18,48 @@ Data Definition Commands (DDL) * - Command - Usage - * - `ADD COLUMN `_ - - Add a new column to a table - * - `ALTER DEFAULT SCHEMA `_ - - Change the default schema for a role - * - `ALTER TABLE `_ - - Change the schema of a table - * - `CLUSTER BY `_ - - Change clustering keys in a table - * - `CREATE DATABASE `_ - - Create a new database - * - `CREATE EXTERNAL TABLE `_ - - Create a new external table in the database (deprecated) - * - `CREATE FOREIGN TABLE `_ - - Create a new foreign table in the database - * - `CREATE FUNCTION `_ - - Create a new user defined function in the database - * - `CREATE SCHEMA `_ - - Create a new schema in the database - * - `CREATE TABLE `_ - - Create a new table in the database - * - `CREATE TABLE AS `_ - - Create a new table in the database using results from a select query - * - `CREATE VIEW `_ - - Create a new view in the database - * - `DROP CLUSTERING KEY `_ - - Drops all clustering keys in a table - * - `DROP COLUMN `_ - - Drop a column from a table - * - `DROP DATABASE `_ - - Drop a database and all of its objects - * - `DROP FUNCTION `_ - - Drop a function - * - `DROP SCHEMA `_ - - Drop a schema - * - `DROP TABLE `_ - - Drop a table and its contents from a database - * - `DROP VIEW `_ - - Drop a view - * - `RENAME COLUMN `_ - - Rename a column - * - `RENAME TABLE `_ - - Rename a table + * - :ref:`add_column` + - Add a new column to a table + * - :ref:`alter_default_schema` + - Change the default schema for a role + * - :ref:`alter_table` + - Change the schema of a table + * - :ref:`cluster_by` + - Change clustering keys in a table + * - :ref:`create_database` + - Create a new database + * - :ref:`create_external_table` + - Create a new external table in the database (deprecated) + * - :ref:`create_foreign_table` + - Create a new foreign table in the database + * - :ref:`create_function` + - Create a new user defined function in the database + * - :ref:`create_schema` + - Create a new schema in the database + * - :ref:`create_table` + - Create a new table in the database + * - :ref:`create_table_as` + - Create a new table in the database using results from a select query + * - :ref:`create_view` + - Create a new view in the database + * - :ref:`drop_clustering_key` + - Drops all clustering keys in a table + * - :ref:`drop_column` + - Drop a column from a table + * - :ref:`drop_database` + - Drop a database and all of its objects + * - :ref:`drop_function` + - Drop a function + * - :ref:`drop_schema` + - Drop a schema + * - :ref:`drop_table` + - Drop a table and its contents from a database + * - :ref:`drop_view` + - Drop a view + * - :ref:`rename_column` + - Rename a column + * - :ref:`rename_table` + - Rename a table Data Manipulation Commands (DML) ================================ From e0d71c1e5b4446c14b394d10da6ecde5e9393316 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 27 Mar 2022 17:23:31 +0300 Subject: [PATCH 0022/1892] Updated Menus Used new menu documentation method. --- .../sql_functions/scalar_functions/index.rst | 3 -- .../sql_functions/system_functions/index.rst | 19 +++++----- .../user_defined_functions/index.rst | 21 +++-------- .../sql_functions/window_functions/index.rst | 35 ++++++++----------- reference/sql/sql_statements/index.rst | 16 +-------- reference/sql/sql_syntax/index.rst | 24 ++++++------- 6 files changed, 40 insertions(+), 78 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index b21071021..bd05f9bbe 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -3,13 +3,10 @@ **************** Built-In Scalar Functions **************** -FF - The **Built-In Scalar Functions** page describes functions that return one value per call: .. hlist:: :columns: 5 - * `AND `_ * `NOT `_ diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst index a27dfda62..ba99610ba 100644 --- a/reference/sql/sql_functions/system_functions/index.rst +++ b/reference/sql/sql_functions/system_functions/index.rst @@ -7,14 +7,13 @@ System Functions The System Functions page describes the following: -.. toctree:: - :maxdepth: 1 - :glob: +.. hlist:: + :columns: 1 - explain - show_version - show_connections - show_locks - show_node_info - show_server_status - stop_statement \ No newline at end of file + * :ref:`explain` + * :ref:`show_version` + * :ref:`show_connections` + * :ref:`show_locks` + * :ref:`show_node_info` + * :ref:`show_server_status` + * :ref:`stop_statement` \ No newline at end of file diff --git a/reference/sql/sql_functions/user_defined_functions/index.rst b/reference/sql/sql_functions/user_defined_functions/index.rst index 225c9614e..028e35a07 100644 --- a/reference/sql/sql_functions/user_defined_functions/index.rst +++ b/reference/sql/sql_functions/user_defined_functions/index.rst @@ -4,22 +4,9 @@ User-Defined Functions ******************** -The following user-defined functions are functions that can be defined and configured by users: +The following user-defined functions are functions that can be defined and configured by users. +The **User-Defined Functions** page describes the following: - -* `Python user-defined functions `_. -* `Scalar SQL user-defined functions `_. - - - - -.. toctree:: - :maxdepth: 8 - :glob: - :hidden: - - - - python_functions - scalar_sql_udf +* `Python user-defined functions `_ +* `Scalar SQL user-defined functions `_ \ No newline at end of file diff --git a/reference/sql/sql_functions/window_functions/index.rst b/reference/sql/sql_functions/window_functions/index.rst index 4061ad239..e949e0e3c 100644 --- a/reference/sql/sql_functions/window_functions/index.rst +++ b/reference/sql/sql_functions/window_functions/index.rst @@ -4,26 +4,21 @@ Window Functions ******************** -Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query. +Window functions are functions applied over a subset (known as a window) of the rows returned by a :ref:`select` query and describes the following: -Read more about :ref:`window_functions` in the :ref:`sql_syntax` section. - -.. toctree:: - :maxdepth: 1 - :caption: Window Functions: - :glob: - :hidden: +.. hlist:: + :columns: 1 - lag - lead - row_number - rank - first_value - last_value - nth_value - dense_rank - percent_rank - cume_dist - ntile - + * :ref:`lag` + * :ref:`lead` + * :ref:`row_number` + * :ref:`rank` + * :ref:`first_value` + * :ref:`last_value` + * :ref:`nth_value` + * :ref:`dense_rank` + * :ref:`percent_rank` + * :ref:`cume_dist` + * :ref:`ntile` +For more information, see :ref:`window_functions` in the :ref:`sql_syntax` section. \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index a8e27cb6e..bede1de2e 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -204,18 +204,4 @@ Access Control Commands * - :ref:`revoke` - Revoke permissions from a role * - :ref:`rename_role` - - Rename a role - - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :hidden: - :glob: - - ddl_commands/* - dml_commands/* - utility_commands/* - monitoring_commands/* - wlm_commands/* - access_control_commands/* \ No newline at end of file + - Rename a role \ No newline at end of file diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 90caf01e5..9e0422db4 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -4,18 +4,16 @@ SQL Syntax Features ********************** -SQream DB supports SQL from the ANSI 92 syntax. +SQream DB supports SQL from the ANSI 92 syntax and describes the following: -.. toctree:: - :maxdepth: 2 - :caption: SQL Syntax Topics - :glob: +.. hlist:: + :columns: 1 - keywords_and_identifiers - literals - scalar_expressions - joins - common_table_expressions - window_functions - subqueries - null_handling + * :ref:`keywords_and_identifiers` + * :ref:`literals` + * :ref:`scalar_expressions` + * :ref:`joins` + * :ref:`common_table_expressions` + * :ref:`window_functions` + * :ref:`subqueries` + * :ref:`null_handling` \ No newline at end of file From e3dcb2d92dbf1c7415bf5dcb95dc9978ab7d77bf Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:33:25 +0300 Subject: [PATCH 0023/1892] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 040223936..8e42c910d 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -1,7 +1,5 @@ .. _running_sqream_in_a_docker_container: - - *********************** Installing and Running SQream in a Docker Container *********************** @@ -519,19 +517,15 @@ Installing the Docker Engine on an IBM Power9 Processor ---------------------------------------- The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - **To install the Docker Engine on an IBM Power9 processor:** You can install the Docker Engine on an IBM Power9 processor by running the following command: .. code-block:: console - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm - $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - - + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. @@ -576,8 +570,8 @@ After configuring Docker on your local machine you must install the Nvidia Docke This section describes the following: -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor ` .. _install_nvidia_docker2_toolkit_x8664_processor: @@ -601,10 +595,9 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System .. code-block:: console - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: @@ -654,13 +647,10 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System .. code-block:: console - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update + curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list + sudo apt-get update 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: @@ -668,7 +658,9 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System $ sudo apt-get install nvidia-docker2 $ sudo pkill -SIGHUP dockerd + 3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. @@ -795,8 +787,8 @@ For more information about the correct directory to copy the above files into, s For related information, see the following sections: -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files ` +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters ` .. _installing_sqream_software: From 96086da570ac664009d04d989aa9541ff084ed3d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:33:38 +0300 Subject: [PATCH 0024/1892] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 040223936..8e42c910d 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -1,7 +1,5 @@ .. _running_sqream_in_a_docker_container: - - *********************** Installing and Running SQream in a Docker Container *********************** @@ -519,19 +517,15 @@ Installing the Docker Engine on an IBM Power9 Processor ---------------------------------------- The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - **To install the Docker Engine on an IBM Power9 processor:** You can install the Docker Engine on an IBM Power9 processor by running the following command: .. code-block:: console - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - $ wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - $ yum install -y container-selinux-2.9-4.el7.noarch.rpm - $ docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - - + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm + wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm + yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. @@ -576,8 +570,8 @@ After configuring Docker on your local machine you must install the Nvidia Docke This section describes the following: -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor. ` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor. ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor ` +* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor ` .. _install_nvidia_docker2_toolkit_x8664_processor: @@ -601,10 +595,9 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System .. code-block:: console - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ + sudo tee /etc/yum.repos.d/nvidia-docker.repo 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: @@ -654,13 +647,10 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System .. code-block:: console - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L - $ https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update + curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - + distribution=$(. /etc/os-release;echo $ID$VERSION_ID) + curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list + sudo apt-get update 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: @@ -668,7 +658,9 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System $ sudo apt-get install nvidia-docker2 $ sudo pkill -SIGHUP dockerd + 3. Do one of the following: + * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. @@ -795,8 +787,8 @@ For more information about the correct directory to copy the above files into, s For related information, see the following sections: -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. +* :ref:`Configuring the Hadoop and Kubernetes Configuration Files ` +* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters ` .. _installing_sqream_software: From 2e9e91ce5627265a7186b6e1351099fbda087766 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:47:15 +0300 Subject: [PATCH 0025/1892] Update running_sqream_in_a_docker_container.rst --- installation_guides/running_sqream_in_a_docker_container.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 8e42c910d..79caa9f8d 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -3,7 +3,7 @@ *********************** Installing and Running SQream in a Docker Container *********************** -The **Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. +The **Installing and Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. This page describes the following: @@ -102,7 +102,7 @@ You can install the required NTP packages by running the following command: .. code-block:: console - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc Installing the Recommended Tools ---------------- From 2e48016372f05aa75032fc11670e9bc07fcdee7b Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 14:47:48 +0300 Subject: [PATCH 0026/1892] Update running_sqream_in_a_docker_container.rst --- installation_guides/running_sqream_in_a_docker_container.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 8e42c910d..79caa9f8d 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -3,7 +3,7 @@ *********************** Installing and Running SQream in a Docker Container *********************** -The **Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. +The **Installing and Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. This page describes the following: @@ -102,7 +102,7 @@ You can install the required NTP packages by running the following command: .. code-block:: console - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc + $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc Installing the Recommended Tools ---------------- From d11076aa93cb435131a6a5708ded114e9e29f49a Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 15:04:08 +0300 Subject: [PATCH 0027/1892] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 79caa9f8d..aba0d109f 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -146,7 +146,7 @@ After configuring the NTP package you must configure the performance profile. **To configure the performance profile:** -1. Switch the active profile: +1. *Optional* - Switch the active profile: .. code-block:: console @@ -337,10 +337,6 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service -6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - 7. Reboot the server. :: @@ -418,10 +414,6 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 .. code-block:: console $ sudo systemctl enable nvidia-persistenced.service - -#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: #. Reboot your system to initialize the above modifications. @@ -832,7 +824,7 @@ The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the f $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz -When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: + When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: .. code-block:: console @@ -1247,7 +1239,7 @@ You can stop your SQream Studio by running the following command: The following is an example of the expected output: -.. code-block:: console +.. code-block:: sqream_admin stopped @@ -1256,8 +1248,6 @@ The following is an example of the expected output: Using the SQream Client ~~~~~~~~~~~~~~~~~ - - You can use the embedded SQream Client on the following nodes: * Master node From a9a152bb8f169bc0e4865bd27e09b327ed854c15 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 15:11:06 +0300 Subject: [PATCH 0028/1892] Update running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 198 +++++++++--------- 1 file changed, 99 insertions(+), 99 deletions(-) diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index aba0d109f..e85eac925 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -34,19 +34,19 @@ To run SQream in a Docker container you must create a local user. 1. Add a local user: - .. code-block:: console + .. code-block:: $ useradd -m -U 2. Set the local user's password: - .. code-block:: console + .. code-block:: $ passwd 3. Add the local user to the ``wheel`` group: - .. code-block:: console + .. code-block:: $ usermod -aG wheel @@ -62,13 +62,13 @@ After creating a local user you must set a local language. 1. Set the local language: - .. code-block:: console + .. code-block:: $ sudo localectl set-locale LANG=en_US.UTF-8 2. Set the time stamp (time and date) of the locale: - .. code-block:: console + .. code-block:: $ sudo timedatectl set-timezone Asia/Jerusalem @@ -84,13 +84,13 @@ After setting a local language you must add the EPEL repository. 1. RedHat (RHEL 7): - .. code-block:: console + .. code-block:: $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm 2. CentOS 7 - .. code-block:: console + .. code-block:: $ sudo yum install epel-release @@ -100,7 +100,7 @@ After adding the EPEL repository, you must install the required NTP packages. You can install the required NTP packages by running the following command: -.. code-block:: console +.. code-block:: $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc @@ -110,7 +110,7 @@ After installin gthe required NTP packages you must install the recommended tool SQream recommends installing the following recommended tools: -.. code-block:: console +.. code-block:: $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix @@ -134,7 +134,7 @@ After updating to the current version of the operating system you must configure 2. Configure the **ntpd** service to begin running when your machine is started: - .. code-block:: console + .. code-block:: $ sudo systemctl enable ntpd $ sudo systemctl start ntpd @@ -148,13 +148,13 @@ After configuring the NTP package you must configure the performance profile. 1. *Optional* - Switch the active profile: - .. code-block:: console + .. code-block:: $ sudo tuned-adm profile throughput-performance 2. Change the multi-user's default run level: - .. code-block:: console + .. code-block:: $ sudo systemctl set-default multi-user.target @@ -166,19 +166,19 @@ After configuring the performance profile you must configure your security limit 1. Run the **bash** shell as a super-user: - .. code-block:: console + .. code-block:: $ sudo bash 2. Run the following command: - .. code-block:: console + .. code-block:: $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf 3. Run the following command: - .. code-block:: console + .. code-block:: $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf @@ -194,7 +194,7 @@ After configuring your security limits you must disable the following automatic You can abort the above but-reporting tools by running the following command: -.. code-block:: console +.. code-block:: $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done @@ -203,7 +203,7 @@ Installing the Nvidia CUDA Driver 1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: - .. code-block:: console + .. code-block:: $ lspci | grep -i nvidia @@ -211,7 +211,7 @@ Installing the Nvidia CUDA Driver #. Verify that the open-source upstream Nvidia driver is running: - .. code-block:: console + .. code-block:: $ lsmod | grep nouveau @@ -221,7 +221,7 @@ Installing the Nvidia CUDA Driver 1. Disable the open-source upstream Nvidia driver: - .. code-block:: console + .. code-block:: $ sudo bash $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf @@ -231,19 +231,19 @@ Installing the Nvidia CUDA Driver 2. Reboot the server and verify that the Nouveau model has not been loaded: - .. code-block:: console + .. code-block:: $ lsmod | grep nouveau #. Check if the Nvidia CUDA driver has already been installed: - .. code-block:: console + .. code-block:: $ nvidia-smi The following is an example of the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -310,14 +310,14 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab 2. Download the base installer for Linux CentOS 7 x86_64: - .. code-block:: console + .. code-block:: wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm 3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - .. code-block:: console + .. code-block:: $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm $ sudo yum clean all @@ -333,7 +333,7 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab 5. Enable the Nvidia service to start at boot and start it: - .. code-block:: console + .. code-block:: $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service @@ -342,13 +342,13 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab :: 8. Verify that the Nvidia driver has been installed and shows all available GPU's: - .. code-block:: console + .. code-block:: $ nvidia-smi The following is the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -381,14 +381,14 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 1. Download the base installer for Linux CentOS 7 PPC64le: - .. code-block:: console + .. code-block:: wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm #. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - .. code-block:: console + .. code-block:: $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm $ sudo yum clean all @@ -404,14 +404,14 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: - .. code-block:: console + .. code-block:: $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules #. Enable the **nvidia-persisted.service** file: - .. code-block:: console + .. code-block:: $ sudo systemctl enable nvidia-persistenced.service @@ -421,13 +421,13 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 #. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: - .. code-block:: console + .. code-block:: $ nvidia smi The following is the correct output: - .. code-block:: console + .. code-block:: nvidia-smi Wed Oct 30 14:05:42 2019 @@ -453,13 +453,13 @@ Installing the CUDA Driver Version 10.1 for IBM Power9 #. Verify that the **nvidia-persistenced** service is running: - .. code-block:: console + .. code-block:: $ systemctl status nvidia-persistenced The following is the correct output: - .. code-block:: console + .. code-block:: root@gpudb ~]systemctl status nvidia-persistenced nvidia-persistenced.service - NVIDIA Persistence Daemon @@ -513,7 +513,7 @@ The x86_64 processor only supports installing the **Docker Community Edition (CE You can install the Docker Engine on an IBM Power9 processor by running the following command: -.. code-block:: console +.. code-block:: wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm @@ -529,13 +529,13 @@ After installing the Docker engine you must configure Docker on your local machi 1. Enable Docker to start on boot: - .. code-block:: console + .. code-block:: $ sudo systemctl enable docker && sudo systemctl start docker 2. Enable managing Docker as a non-root user: - .. code-block:: console + .. code-block:: $ sudo usermod -aG docker $USER @@ -545,7 +545,7 @@ After installing the Docker engine you must configure Docker on your local machi 4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): - .. code-block:: console + .. code-block:: $ docker run hello-world @@ -585,7 +585,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 1. Install the repository for your distribution: - .. code-block:: console + .. code-block:: distribution=$(. /etc/os-release;echo $ID$VERSION_ID) curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ @@ -593,7 +593,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - .. code-block:: console + .. code-block:: $ sudo yum install nvidia-docker2 $ sudo pkill -SIGHUP dockerd @@ -610,7 +610,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -621,7 +621,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System 5. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi @@ -637,7 +637,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 1. Install the repository for your distribution: - .. code-block:: console + .. code-block:: curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) @@ -646,7 +646,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - .. code-block:: console + .. code-block:: $ sudo apt-get install nvidia-docker2 $ sudo pkill -SIGHUP dockerd @@ -662,7 +662,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -673,7 +673,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System 5. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi @@ -690,7 +690,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. - .. code-block:: console + .. code-block:: $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ @@ -708,7 +708,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: - .. code-block:: console + .. code-block:: https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: [Errno -1] repomd.xml signature could not be verified for nvidia-docker @@ -719,7 +719,7 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 3. Install the ``libnvidia-container`` container. - .. code-block:: console + .. code-block:: $ sudo yum install -y libnvidia-container* @@ -727,13 +727,13 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 4. Install the ``nvidia-container-runtime`` container: - .. code-block:: console + .. code-block:: $ sudo yum install -y nvidia-container-runtime* 5. Add ``nvidia runtime`` to the Docker daemon: - .. code-block:: console + .. code-block:: $ sudo mkdir -p /etc/systemd/system/docker.service.d/ $ sudo vi /etc/systemd/system/docker.service.d/override.conf @@ -744,14 +744,14 @@ This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL 6. Restart Docker: - .. code-block:: console + .. code-block:: $ sudo systemctl daemon-reload $ sudo systemctl restart docker 7. Verify that the NVIDIA-Docker run has been installed correctly: - .. code-block:: console + .. code-block:: $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi @@ -820,13 +820,13 @@ The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the f 2. Extract the tarball file: - .. code-block:: console + .. code-block:: $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: - .. code-block:: console + .. code-block:: drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz @@ -837,13 +837,13 @@ The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the f 4. Verify that the folder you just created contains all of the required files. - .. code-block:: console + .. code-block:: $ ls -la The following is an example of the files included in the new folder: - .. code-block:: console + .. code-block:: drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. @@ -950,7 +950,7 @@ Installing Your License ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -k @@ -961,19 +961,19 @@ Validating Your License ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -K The following mandatory flags must be used in the first run: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -i -k -v The following is an example of the correct command syntax: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest @@ -985,13 +985,13 @@ The information in this section is optional, and is only relevant for Hadoop use The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -p -e : The following is an example of setting the Hadoop and Kubernetes connectivity parameters: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> @@ -1004,7 +1004,7 @@ Modifying Your Data Ingest Folder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: -.. code-block:: console +.. code-block:: $ sudo ./sqream-install -d /home/sqream/data_in @@ -1016,7 +1016,7 @@ Once you've modified your data ingest folder (if needed), you must validate that 1. To verify that your server network and Docker network do not overlap, run the following command: -.. code-block:: console +.. code-block:: $ ifconfig | grep 172. @@ -1025,7 +1025,7 @@ Once you've modified your data ingest folder (if needed), you must validate that * If running the above command output no results, continue the installation process. * If running the above command output results, run the following command: - .. code-block:: console + .. code-block:: $ ifconfig | grep 192.168. @@ -1036,13 +1036,13 @@ Once you've configured your network for Docker, you can check and verify your sy Running the following command shows you all the variables used by your SQream system: -.. code-block:: console +.. code-block:: $ ./sqream-install -s The following is an example of the correct output: -.. code-block:: console +.. code-block:: SQREAM_CONSOLE_TAG=1.5.4 SQREAM_TAG=2019.2.1 @@ -1092,7 +1092,7 @@ Starting Your SQream Console You can start your SQream console by running the following command: -.. code-block:: console +.. code-block:: $ ./sqream-console @@ -1105,13 +1105,13 @@ Starting the SQream Master 1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: - .. code-block:: console + .. code-block:: $ sqream master --start The following is the correct output: - .. code-block:: console + .. code-block:: sqream-console> sqream master --start starting master server in single_host mode ... @@ -1120,7 +1120,7 @@ Starting the SQream Master 2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: - .. code-block:: console + .. code-block:: $ sqream-console>sqream master --start -p 4105 -m 43108 $ starting master server in single_host mode ... @@ -1137,13 +1137,13 @@ Starting SQream Workers When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. -.. code-block:: console +.. code-block:: $ sqream worker --start The following is an example of expected output when setting the ```` value to ``2``: - .. code-block:: console + .. code-block:: sqream-console>sqream worker --start 2 started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 @@ -1157,13 +1157,13 @@ Listing the Running Services You can list running SQream services to look for container names and ID's by running the following command: -.. code-block:: console +.. code-block:: $ sqream master --list The following is an example of the expected output: -.. code-block:: console +.. code-block:: sqream-console>sqream master --list container name: sqream_single_host_worker_0, container id: c919e8fb78c8 @@ -1179,13 +1179,13 @@ You can stop running services either for a single SQream worker, or all SQream s The following is the command for stopping a running service for a single SQream worker: -.. code-block:: console +.. code-block:: $ sqream worker --stop The following is an example of expected output when stopping a running service for a single SQream worker: -.. code-block:: console +.. code-block:: sqream worker stop stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 @@ -1193,13 +1193,13 @@ The following is an example of expected output when stopping a running service f You can stop all running SQream services (both master and worker) by running the following command: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --stop --all The following is an example of expected output when stopping all running services: -.. code-block:: console +.. code-block:: sqream-console>sqream master --stop --all stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 @@ -1216,13 +1216,13 @@ SQream Studio is an SQL statement editor. 1. Run the following command: - .. code-block:: console + .. code-block:: $ sqream studio --start The following is an example of the expected output: - .. code-block:: console + .. code-block:: SQream Acceleration Studio is available at http://192.168.1.62:8080 @@ -1233,7 +1233,7 @@ The following is an example of the expected output: You can stop your SQream Studio by running the following command: -.. code-block:: console +.. code-block:: $ sqream studio --stop @@ -1261,7 +1261,7 @@ When using the SQream Client on the Master node, the following default settings The following is an example: -.. code-block:: console +.. code-block:: $ sqream client --master -u sqream -w sqream @@ -1270,7 +1270,7 @@ When using the SQream Client on a Worker node (or nodes), you should use the ``- The following is an example: -.. code-block:: console +.. code-block:: $ sqream client --worker -p 5000 -u sqream -w sqream @@ -1304,7 +1304,7 @@ From the console you can define a spool size value. The following example shows the spool size being set to ``50``: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -m 50 @@ -1321,7 +1321,7 @@ You can start more than one sqreamd on a single GPU by splitting it. The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -g 0 @@ -1332,7 +1332,7 @@ Splitting GPU and Setting the Spool Size You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 2 -g 0 -m 50 @@ -1349,19 +1349,19 @@ The SQream console does not validate the integrity of your external configuratio When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: -.. code-block:: console +.. code-block:: $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json .. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: -.. code-block:: console +.. code-block:: $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json .. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: -.. code-block:: console +.. code-block:: $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json @@ -1372,7 +1372,7 @@ Clustering Your Docker Environment SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. -.. code-block:: console +.. code-block:: $ --master-host $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 @@ -1391,13 +1391,13 @@ Checking the Status of SQream Services from the SQream Console From the SQream console, you can check the status of SQream services by running the following command: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --list The following is an example of the expected output: -.. code-block:: console +.. code-block:: $ sqream-console>sqream master --list $ checking 3 sqream services: @@ -1412,7 +1412,7 @@ Checking the Status of SQream Services from Outside the SQream Console From outside the Sqream Console, you can check the status of SQream services by running the following commands: -.. code-block:: console +.. code-block:: $ sqream-status $ NAMES STATUS PORTS @@ -1438,19 +1438,19 @@ This section describes how to upgrade your SQream system. 3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. - .. code-block:: console + .. code-block:: $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ 4. Navigate to the new folder created as a result of extracting the tarball file: - .. code-block:: console + .. code-block:: $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ 5. Initiate the upgrade process: - .. code-block:: console + .. code-block:: $ ./sqream-install -i From 3f69443d275bc9ddc50e3c654a3ad4f960e4a52d Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Mon, 28 Mar 2022 15:15:39 +0300 Subject: [PATCH 0029/1892] Update running_sqream_in_a_docker_container.rst From 3719aa8ac4c102f462f2aa142b2d0215d455989f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 29 Mar 2022 11:42:53 +0300 Subject: [PATCH 0030/1892] Modified Getting Started and Installation Guides menus Modified Getting Started and Installation Guides menus --- getting_started/creating_a_database.rst | 34 + ...eparing_your_machine_to_install_sqream.rst | 2 +- .../installing_and_launching_sqream.rst | 9 +- installation_guides/installing_monit.rst | 319 ---- .../installing_sqream_with_binary.rst | 279 ---- .../running_sqream_in_a_docker_container.rst | 1480 ----------------- 6 files changed, 36 insertions(+), 2087 deletions(-) create mode 100644 getting_started/creating_a_database.rst delete mode 100644 installation_guides/installing_monit.rst delete mode 100644 installation_guides/installing_sqream_with_binary.rst delete mode 100644 installation_guides/running_sqream_in_a_docker_container.rst diff --git a/getting_started/creating_a_database.rst b/getting_started/creating_a_database.rst new file mode 100644 index 000000000..6b208f123 --- /dev/null +++ b/getting_started/creating_a_database.rst @@ -0,0 +1,34 @@ +.. _creating_a_database: + +**************************** +Creating a Database +**************************** +Once you've installed SQream you can create a database. + +**To create a database:** + +1. Write a :ref:`create_database` statement. + + The following is an example of creating a new database: + + .. code-block:: psql + + master=> CREATE DATABASE test; + executed + +2. Reconnect to the newly created database. + + 1. Exit the client by typing ``\q`` and pressing **Enter**. + 2. From the Linux shell, restart the client with the new database name: + + .. code-block:: psql + + $ sqream sql --port=5000 --username=rhendricks -d test + Password: + + Interactive client mode + To quit, use ^D or \q. + + test=> _ + + The name of the new database that you are connected to is displayed in the prompt. \ No newline at end of file diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index 435f35de0..d57861b1a 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -32,4 +32,4 @@ To prepare your machine to install SQream, do the following: For more information, see the following: * :ref:`recommended_pre-installation_configurations` -* `Hardware Guide `_ +* :ref:`hardware_guide` \ No newline at end of file diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 4ef1ef706..03d5d024f 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -10,11 +10,4 @@ The **Installing SQream Studio** page incudes the following installation guides: :glob: recommended_pre-installation_configurations - installing_sqream_with_binary - running_sqream_in_a_docker_container - installing_sqream_with_kubernetes - installing_monit - launching_sqream_with_monit - - - + installing_sqream_with_kubernetes \ No newline at end of file diff --git a/installation_guides/installing_monit.rst b/installation_guides/installing_monit.rst deleted file mode 100644 index b27800cce..000000000 --- a/installation_guides/installing_monit.rst +++ /dev/null @@ -1,319 +0,0 @@ -.. _installing_monit: - -********************************************* -Installing Monit -********************************************* - -Getting Started -============================== - -Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. - -The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. - - - - - -.. _back_to_top: - -Overview -============================== - - -Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. - -SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. - -The **Installing Monit** procedures describes how to install, configure, and start Monit. - -You can install Monit in one of the following ways: - -* :ref:`Installing Monit on CentOS ` -* :ref:`Installing Monit on CentOS offline ` -* :ref:`Installing Monit on Ubuntu ` -* :ref:`Installing Monit on Ubuntu offline ` - - - - - - - -.. _installing-monit-on-centos: - -Installing Monit on CentOS: ------------------------------------- - - - -**To install Monit on CentOS:** - -1. Install Monit as a superuser on CentOS: - - .. code-block:: console - - $ sudo yum install monit - - -.. _installing-monit-on-centos-offline: - - - -Installing Monit on CentOS Offline: ------------------------------------- - - -Installing Monit on CentOS offline can be done in either of the following ways: - -* :ref:`Building Monit from Source Code ` -* :ref:`Building Monit from Pre-Built Binaries ` - - - - -.. _building_monit_from_source_code: - -Building Monit from Source Code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - - -**To build Monit from source code:** - -1. Copy the Monit package for the current version: - - .. code-block:: console - - $ tar zxvf monit-.tar.gz - - The value ``x.y.z`` denotes the version numbers. - -2. Navigate to the directory where you want to store the package: - - .. code-block:: console - - $ cd monit-x.y.z - -3. Configure the files in the package: - - .. code-block:: console - - $ ./configure (use ./configure --help to view available options) - -4. Build and install the package: - - .. code-block:: console - - $ make && make install - -The following are the default storage directories: - -* The Monit package: **/usr/local/bin/** -* The **monit.1 man-file**: **/usr/local/man/man1/** - -5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. - -.. - _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** - -6. **Optional** - Create an RPM package for CentOS directly from the source code: - - .. code-block:: console - - $ rpmbuild -tb monit-x.y.z.tar.gz - -.. - _**Comment - Is this an optional or mandatory step?** - - - - -.. _building_monit_from_pre_built_binaries: - -Building Monit from Pre-Built Binaries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To build Monit from pre-built binaries:** - -1. Copy the Monit package for the current version: - - .. code-block:: console - - $ tar zxvf monit-x.y.z-linux-x64.tar.gz - - The value ``x.y.z`` denotes the version numbers. - -2. Navigate to the directory where you want to store the package: - - .. code-block:: console$ cd monit-x.y.z - -3. Copy the **bin/monit** and **/usr/local/bin/** directories: - - .. code-block:: console - - $ cp bin/monit /usr/local/bin/ - -4. Copy the **conf/monitrc** and **/etc/** directories: - - .. code-block:: console - - $ cp conf/monitrc /etc/ - -.. - _**Comment - please review this procedure.** - -For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. - -:ref:`Back to top ` - - - -.. _installing-monit-on-ubuntu: - - - -Installing Monit on Ubuntu: ------------------------------------- - - -**To install Monit on Ubuntu:** - -1. Install Monit as a superuser on Ubuntu: - - .. code-block:: console - - $ sudo apt-get install monit - -:ref:`Back to top ` - - - -.. _installing-monit-on-ubuntu-offline: - - -Installing Monit on Ubuntu Offline: -------------------------------------- - - -You can install Monit on Ubuntu when you do not have an internet connection. - -**To install Monit on Ubuntu offline:** - -1. Compress the required file: - - .. code-block:: console - - $ tar zxvf monit--linux-x64.tar.gz - - **NOTICE:** ** denotes the version number. - -2. Navigate to the directory where you want to save the file: - - .. code-block:: console - - $ cd monit-x.y.z - -3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: - - .. code-block:: console - - $ cp bin/monit /usr/local/bin/ - -4. Copy the **conf/monitrc** directory into the **/etc/** directory: - - .. code-block:: console - - $ cp conf/monitrc /etc/ - -:ref:`Back to top ` - - -Configuring Monit -==================================== - -When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. - -The following is an example of a service block: - - .. code-block:: console - - $ #SQREAM1-START - $ check process sqream1 with pidfile /var/run/sqream1.pid - $ start program = "/usr/bin/systemctl start sqream1" - $ stop program = "/usr/bin/systemctl stop sqream1" - $ #SQREAM1-END - -For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: - - .. code-block:: console - - $ #SQREAM2-START - $ check process sqream2 with pidfile /var/run/sqream2.pid - $ start program = "/usr/bin/systemctl start sqream2" - $ stop program = "/usr/bin/systemctl stop sqream2" - $ #SQREAM2-END - -For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: - - .. code-block:: console - - $ #METADATASERVER-START - $ #check process metadataserver with pidfile /var/run/metadataserver.pid - $ #start program = "/usr/bin/systemctl start metadataserver" - $ #stop program = "/usr/bin/systemctl stop metadataserver" - $ #METADATASERVER-END - -**To configure Monit:** - -1. Copy the required block for each required service. -2. Modify all service names in the block. -3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: - - .. code-block:: console - - $ cp monitrc /etc/monit.d/ - -4. Set file permissions to **600** (full read and write access): - - .. code-block:: console - - $ sudo chmod 600 /etc/monit.d/monitrc - -5. Reload the system to activate the current configurations: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: - - .. code-block:: console - - $ cd /etc/sqream - $ sudo ln -s /etc/monit.d/monitrc monitrc - -Starting Monit -==================================== - -After configuring Monit, you can start it. - -**To start Monit:** - -1. Start Monit as a super user: - - .. code-block:: console - - $ sudo systemctl start monit - -2. View Monit's service status: - - .. code-block:: console - - $ sudo systemctl status monit - -3. If Monit is functioning correctly, enable the Monit service to start on boot: - - .. code-block:: console - - $ sudo systemctl enable monit diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst deleted file mode 100644 index dd1207ab7..000000000 --- a/installation_guides/installing_sqream_with_binary.rst +++ /dev/null @@ -1,279 +0,0 @@ -.. _installing_sqream_with_binary: - -********************************************* -Installing SQream Using Binary Packages -********************************************* -This procedure describes how to install SQream using Binary packages and must be done on all servers. - -**To install SQream using Binary packages:** - -1. Copy the SQream package to the **/home/sqream** directory for the current version: - - .. code-block:: console - - $ tar -xf sqream-db-v<2020.2>.tar.gz - -2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: - - .. code-block:: console - - $ mv sqream sqream-db-v<2020.2> - -3. Move the new version of the SQream folder to the **/usr/local/** directory: - - .. code-block:: console - - $ sudo mv sqream-db-v<2020.2> /usr/local/ - -4. Change the ownership of the folder to **sqream folder**: - - .. code-block:: console - - $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> - -5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: - - .. code-block:: console - - $ cd /usr/local - $ sudo ln -s sqream-db-v<2020.2> sqream - -6. Verify that the symbolic link that you created points to the folder that you created: - - .. code-block:: console - - $ ls -l - -7. Verify that the symbolic link that you created points to the folder that you created: - - .. code-block:: console - - $ sqream -> sqream-db-v<2020.2> - -8. Create the SQream configuration file destination folders and set their ownership to **sqream**: - - .. code-block:: console - - $ sudo mkdir /etc/sqream - $ sudo chown -R sqream:sqream /etc/sqream - -9. Create the SQream service log destination folders and set their ownership to **sqream**: - - .. code-block:: console - - $ sudo mkdir /var/log/sqream - $ sudo chown -R sqream:sqream /var/log/sqream - -10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: - - .. code-block:: console - - $ cd /usr/local/sqream/etc/ - $ cp * /etc/sqream - -The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. - -**NOTICE** - Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. - -In each JSON file, the following parameters **must be updated**: - -* instanceId -* machineIP -* metadataServerIp -* spoolMemoryGB -* limitQueryMemoryGB -* gpu -* port -* ssl_port - -Note the following: - -* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. -* The value of the **machineIP** parameter must point to the IP of your local machine. - -It would be same on server running metadataserver and different on other server nodes. - -11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: - - .. code-block:: console - - $ cp sqream2_config.json sqream3_config.json - $ vim sqream3_config.json - -**NOTICE:** A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. - -12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: - - .. code-block:: console - - $ cp sqream2-service.conf sqream3-service.conf - $ vim sqream3-service.conf - -13. For each SQream service configuration file, do the following: - - 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. - - 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. - -**NOTE:** If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. - -14. Set up **servicepicker**: - - 1. Do the following: - - .. code-block:: console - - $ vim /etc/sqream/server_picker.conf - - 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. - - 3. Change the **CLUSTER** to the value of the cluster path. - -15. Set up your service files: - - .. code-block:: console - - $ cd /usr/local/sqream/service/ - $ cp sqream2.service sqream3.service - $ vim sqream3.service - -16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: - - .. code-block:: console - - $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf - -17. Copy and register your service files into systemd: - - .. code-block:: console - - $ sudo cp metadataserver.service /usr/lib/systemd/system/ - $ sudo cp serverpicker.service /usr/lib/systemd/system/ - $ sudo cp sqream*.service /usr/lib/systemd/system/ - -18. Verify that your service files have been copied into systemd: - - .. code-block:: console - - $ ls -l /usr/lib/systemd/system/sqream* - $ ls -l /usr/lib/systemd/system/metadataserver.service - $ ls -l /usr/lib/systemd/system/serverpicker.service - $ sudo systemctl daemon-reload - -19. Copy the license into the **/etc/license** directory: - - .. code-block:: console - - $ cp license.enc /etc/sqream/ - - -If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. - - - - - - -Upgrading SQream Version -------------------------- -Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. - -**To upgrade your version of SQream:** - -1. Stop all actively running SQream services. - -**Notice-** All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. - -For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. - - - -2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: - - .. code-block:: console - - $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. - -3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: - - .. code-block:: console - - $ cd /home/sqream - $ mkdir tempfolder - $ mv sqream-db-v2021.1.tar.gz tempfolder/ - $ tar -xf sqream-db-v2021.1.tar.gz - $ sudo mv sqream /usr/local/sqream-db-v2021.1 - $ cd /usr/local - $ sudo chown -R sqream:sqream sqream-db-v2021.1 - -4. Remove the symbolic link: - - .. code-block:: console - - $ sudo rm sqream - -5. Create a new symbolic link named "sqream" pointing to the new version: - - .. code-block:: console - - $ sudo ln -s sqream-db-v2021.1 sqream - -6. Verify that the symbolic SQream link points to the real folder: - - .. code-block:: console - - $ ls -l - - The following is an example of the correct output: - - .. code-block:: console - - $ sqream -> sqream-db-v2021.1 - -7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: - - .. code-block:: console - - $ cat /etc/sqream/sqream1_config.json |grep cluster - $ ./upgrade_storage - - The following is an example of the correct output: - - .. code-block:: console - - get_leveldb_version path{} - current storage version 23 - upgrade_v24 - upgrade_storage to 24 - upgrade_storage to 24 - Done - upgrade_v25 - upgrade_storage to 25 - upgrade_storage to 25 - Done - upgrade_v26 - upgrade_storage to 26 - upgrade_storage to 26 - Done - validate_leveldb - ... - upgrade_v37 - upgrade_storage to 37 - upgrade_storage to 37 - Done - validate_leveldb - storage has been upgraded successfully to version 37 - -8. Verify that the latest version has been installed: - - .. code-block:: console - - $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" - - The following is an example of the correct output: - - .. code-block:: console - - v2021.1 - 1 row - time: 0.050603s - -For more information, see the `upgrade_storage `_ command line program. - -For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server `_. \ No newline at end of file diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst deleted file mode 100644 index 79caa9f8d..000000000 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ /dev/null @@ -1,1480 +0,0 @@ -.. _running_sqream_in_a_docker_container: - -*********************** -Installing and Running SQream in a Docker Container -*********************** -The **Installing and Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. - -This page describes the following: - -.. contents:: - :local: - :depth: 1 - -Setting Up a Host -==================================== - -Operating System Requirements ------------------------------------- -SQream was tested and verified on the following versions of Linux: - - * x86 CentOS/RHEL 7.6 - 7.9 - * IBM RHEL 7.6 - -SQream recommends installing a clean OS on the host to avoid any installation issues. - -.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. - - -Creating a Local User ----------------- -To run SQream in a Docker container you must create a local user. - -**To create a local user:** - -1. Add a local user: - - .. code-block:: console - - $ useradd -m -U - -2. Set the local user's password: - - .. code-block:: console - - $ passwd - -3. Add the local user to the ``wheel`` group: - - .. code-block:: console - - $ usermod -aG wheel - - You can remove the local user from the ``wheel`` group when you have completed the installation. - -4. Log out and log back in as the local user. - -Setting a Local Language ----------------- -After creating a local user you must set a local language. - -**To set a local language:** - -1. Set the local language: - - .. code-block:: console - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - $ sudo timedatectl set-timezone Asia/Jerusalem - -You can run the ``timedatectl list-timezones`` command to see your timezone. - -Adding the EPEL Repository ----------------- -After setting a local language you must add the EPEL repository. - -**To add the EPEL repository:** - -1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: - - 1. RedHat (RHEL 7): - - .. code-block:: console - - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - 2. CentOS 7 - - .. code-block:: console - - $ sudo yum install epel-release - -Installing the Required NTP Packages ----------------- -After adding the EPEL repository, you must install the required NTP packages. - -You can install the required NTP packages by running the following command: - -.. code-block:: console - - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc - -Installing the Recommended Tools ----------------- -After installin gthe required NTP packages you must install the recommended tools. - -SQream recommends installing the following recommended tools: - -.. code-block:: console - - $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - -Updating to the Current Version of the Operating System ----------------- -After installing the recommended tools you must update to the current version of the operating system. - -SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** - - - -Configuring the NTP Package ----------------- -After updating to the current version of the operating system you must configure the NTP package. - -**To configure the NTP package:** - -1. Add your local servers to the NTP configuration. - - :: - -2. Configure the **ntpd** service to begin running when your machine is started: - - .. code-block:: console - - $ sudo systemctl enable ntpd - $ sudo systemctl start ntpd - $ sudo ntpq -p - -Configuring the Performance Profile ----------------- -After configuring the NTP package you must configure the performance profile. - -**To configure the performance profile:** - -1. Switch the active profile: - - .. code-block:: console - - $ sudo tuned-adm profile throughput-performance - -2. Change the multi-user's default run level: - - .. code-block:: console - - $ sudo systemctl set-default multi-user.target - -Configuring Your Security Limits ----------------- -After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. - -**To configure your security limits:** - -1. Run the **bash** shell as a super-user: - - .. code-block:: console - - $ sudo bash - -2. Run the following command: - - .. code-block:: console - - $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -3. Run the following command: - - .. code-block:: console - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf - -Disabling Automatic Bug-Reporting Tools ----------------- -After configuring your security limits you must disable the following automatic bug-reporting tools: - -* ccpp.service -* oops.service -* pstoreoops.service -* vmcore.service -* xorg.service - -You can abort the above but-reporting tools by running the following command: - -.. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - -Installing the Nvidia CUDA Driver -------------------------------------- - -1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - $ lspci | grep -i nvidia - - The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. - -#. Verify that the open-source upstream Nvidia driver is running: - - .. code-block:: console - - $ lsmod | grep nouveau - - No output should be generated. - -#. If you receive any output, do the following: - - 1. Disable the open-source upstream Nvidia driver: - - .. code-block:: console - - $ sudo bash - $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf - $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf - $ dracut --force - $ modprobe --showconfig | grep nouveau - - 2. Reboot the server and verify that the Nouveau model has not been loaded: - - .. code-block:: console - - $ lsmod | grep nouveau - -#. Check if the Nvidia CUDA driver has already been installed: - - .. code-block:: console - - $ nvidia-smi - - The following is an example of the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the installed CUDA version shown in the output above is ``10.1``. - - :: - - -#. Do one of the following: - - :: - - 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). - :: - - 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. - -#. Do one of the following: - - * Install :ref:`CUDA Driver version 10.1 for x86_64 `. - - :: - - * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. - -.. _CUDA_10.1_x8664: - -Installing the CUDA Driver Version 10.1 for x86_64 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for x86_64:** - -1. Make the following target platform selections: - - :: - - * **Operating system**: Linux - * **Architecture**: x86_64 - * **Distribution**: CentOS - * **Version**: 7 - * **Installer type**: the relevant installer type - -For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. - -2. Download the base installer for Linux CentOS 7 x86_64: - - .. code-block:: console - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - - -3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: console - - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - -4. Follow the command line prompts. - - - :: - - -5. Enable the Nvidia service to start at boot and start it: - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service - -6. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - -7. Reboot the server. - - :: -8. Verify that the Nvidia driver has been installed and shows all available GPU's: - - .. code-block:: console - - $ nvidia-smi - - The following is the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -.. _CUDA_10.1_IBMPower9: - -Installing the CUDA Driver Version 10.1 for IBM Power9 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for IBM Power9:** - -1. Download the base installer for Linux CentOS 7 PPC64le: - - .. code-block:: console - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - - -#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: console - - $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - - - -3. Copy the file to the **/etc/udev/rules.d** directory. - - :: - -4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: - - .. code-block:: console - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules - -#. Enable the **nvidia-persisted.service** file: - - .. code-block:: console - - $ sudo systemctl enable nvidia-persistenced.service - -#. Create a symbolic link from the **/etc/systemd/system/multi-user.target.wants/nvidia-persistenced.service** file to the **/usr/lib/systemd/system/nvidia-persistenced.service** file. - - :: - -#. Reboot your system to initialize the above modifications. - - :: - -#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: - - .. code-block:: console - - $ nvidia smi - - The following is the correct output: - - .. code-block:: console - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the **nvidia-persistenced** service is running: - - .. code-block:: console - - $ systemctl status nvidia-persistenced - - The following is the correct output: - - .. code-block:: console - - root@gpudb ~]systemctl status nvidia-persistenced - nvidia-persistenced.service - NVIDIA Persistence Daemon - Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) - Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago - Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) - Main PID: 8265 (nvidia-persiste) - Tasks: 1 - Memory: 21.0M - CGroup: /system.slice/nvidia-persistenced.service - └─8265 /usr/bin/nvidia-persistenced --verbose - -Installing the Docker Engine (Community Edition) -======================= -After installing the Nvidia CUDA driver you must install the Docker engine. - -This section describes how to install the Docker engine using the following processors: - -* :ref:`Using x86_64 processor on CentOS ` -* :ref:`Using x86_64 processor on Ubuntu ` -* :ref:`Using IBM Power9 (PPC64le) processor ` - - -.. _dockerx8664centos: - -Installing the Docker Engine Using an x86_64 Processor on CentOS ---------------------------------- -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS `_ - - - -.. _dockerx8664ubuntu: - -Installing the Docker Engine Using an x86_64 Processor on Ubuntu ------------------------------------------------------ - - -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu `_ - -.. _docker_ibmpower9: - -Installing the Docker Engine on an IBM Power9 Processor ----------------------------------------- -The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - -**To install the Docker Engine on an IBM Power9 processor:** - -You can install the Docker Engine on an IBM Power9 processor by running the following command: - -.. code-block:: console - - wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - -For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu `_. - -Docker Post-Installation -================================= -After installing the Docker engine you must configure Docker on your local machine. - -**To configure Docker on your local machine:** - -1. Enable Docker to start on boot: - - .. code-block:: console - - $ sudo systemctl enable docker && sudo systemctl start docker - -2. Enable managing Docker as a non-root user: - - .. code-block:: console - - $ sudo usermod -aG docker $USER - -3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. - - :: - -4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): - - .. code-block:: console - - $ docker run hello-world - -If you can run the above Docker command as a non-root user, the following occur: - -* Docker downloads a test image and runs it in a container. -* When the container runs, it prints an informational message and exits. - -For more information on installing the Docker Post-Installation, see `Docker Post-Installation `_. - -Installing the Nvidia Docker2 ToolKit -========================================== -After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor ` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor ` - -.. _install_nvidia_docker2_toolkit_x8664_processor: - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor ----------------------------------------- - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` - -.. _install_nvidia_docker2_toolkit_centos: - -Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** - -1. Install the repository for your distribution: - - .. code-block:: console - - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - sudo tee /etc/yum.repos.d/nvidia-docker.repo - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: console - - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Do one of the following: - - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. - -.. _step_4_centos: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_centos: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` - - -.. _install_nvidia_docker2_toolkit_ubuntu: - -Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** - -1. Install the repository for your distribution: - - .. code-block:: console - - curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - sudo apt-get update - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: console - - $ sudo apt-get install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Do one of the following: - - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 `. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 `. - - .. _step_4_ubuntu: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_ubuntu: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` - -.. _install_nvidia_docker2_toolkit_ppc64le_processor: - -Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor --------------------------------------- - -This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: - -**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** - -1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. - - .. code-block:: console - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - sudo tee /etc/yum.repos.d/nvidia-docker.repo - $ sudo yum install -y libnvidia-container* - -2. Do one of the following: - - * If you received an error when installing the containers, skip to :ref:`Step 3 `. - * If you successfully installed the containers, skip to :ref:`Step 4 `. - -.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: - -3. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: - - .. code-block:: console - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - - :: - - 3. Install the ``libnvidia-container`` container. - - .. code-block:: console - - $ sudo yum install -y libnvidia-container* - - .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: - -4. Install the ``nvidia-container-runtime`` container: - - .. code-block:: console - - $ sudo yum install -y nvidia-container-runtime* - -5. Add ``nvidia runtime`` to the Docker daemon: - - .. code-block:: console - - $ sudo mkdir -p /etc/systemd/system/docker.service.d/ - $ sudo vi /etc/systemd/system/docker.service.d/override.conf - - $ [Service] - $ ExecStart= - $ ExecStart=/usr/bin/dockerd - -6. Restart Docker: - - .. code-block:: console - - $ sudo systemctl daemon-reload - $ sudo systemctl restart docker - -7. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: console - - $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi - -.. _accessing_hadoop_kubernetes_configuration_files: - -Accessing the Hadoop and Kubernetes Configuration Files --------------------------------------- -The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: - -* Hadoop configuration files: - - * core-site.xml - * hdfs-site.xml - - :: - -* Kubernetes files: - - * Configuration file - krb.conf - * Kubernetes Hadoop client certificate - hdfs.keytab - -Once you have the above files, you must copy them into the correct folders in your working directory. - -For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software ` section below. - -For related information, see the following sections: - -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files ` -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters ` - -.. _installing_sqream_software: - -Installing the SQream Software -============================== - -Preparing Your Local Environment -------------------------- -After installing the Nvidia Docker2 toolKit you must prepare your local environment. - -.. note:: You must install the SQream software under a *sqream* and not a *root* user. - -The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: - -* **Log directory** - default: /var/log/sqream/ -* **Configuration directory** - default: /etc/sqream/ -* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* -* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* - -.. _download_sqream_software: - -Deploying the SQream Software -------------------------- -After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. - -**To deploy the SQream software:** - -1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file. - -The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-.tar.gz** file includes the following parameter values: - -* **sqream_installer-nnn** - sqream installer version -* **DBnnn** - SQreamDB version -* **COnnn** - SQream console version -* **EDnnn** - SQream editor version -* **arch** - server arch (applicable to X86.64 and ppc64le) - -2. Extract the tarball file: - - .. code-block:: console - - $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - -When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: - - .. code-block:: console - - drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ - -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - -3. Change the directory to the new folder that you created in the previous step. - -:: - -4. Verify that the folder you just created contains all of the required files. - - .. code-block:: console - - $ ls -la - - The following is an example of the files included in the new folder: - - .. code-block:: console - - drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . - drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. - drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker - drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop - drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install - drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 - drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license - drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream - -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console - -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install - -For information relevant to Hadoop users, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - -.. _configure_hadoop_kubernetes_configuration_files: - -Configuring the Hadoop and Kubernetes Configuration Files ------------------------------ -The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: - -* .hadoop/core-site.xml -* .hadoop/hdfs-site.xml -* .krb5/krb5.conf -* .krb5/hdfs.keytab - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - -Configuring the SQream Software -------------------------------- -After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. - -Configuring the SQream software requires you to do the following: - -* Configure your local environment -* Understand the ``sqream-install`` flags -* Install your SQream license -* Validate your SQream icense -* Change your data ingest folder - -Configuring Your Local Environment -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. - -For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. - -The following table shows the flags that you can use to configure your local directory: - -.. list-table:: - :widths: 10 50 40 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-i** - - Loads all software from the hidden folder **.docker**. - - Mandatory - * - **-k** - - Loads all license packages from the **/license** directory. - - Mandatory - * - **-f** - - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. - - Mandatory - * - **-c** - - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. - - If you are installing the Docker version on a server that already works with SQream, do not use the default path. - * - **-v** - - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. - - Mandatory - * - **-l** - - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. - - - * - **-d** - - The directory containing customer data to be imported and/or copied to SQream. - - - * - **-s** - - Shows system settings. - - - * - **-r** - - Resets the system configuration. This value is run without any other variables. - - Mandatory - * - **-h** - - Help. Shows the available flags. - - Mandatory - * - **-K** - - Runs license validation - - - * - **-e** - - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - - - * - **-p** - - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters `. - - - - -Installing Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: - -.. code-block:: console - - $ sudo ./sqream-install -k - -You do not need to extract this folder after uploading into the **./license**. - - -Validating Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -K - -The following mandatory flags must be used in the first run: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -v - -The following is an example of the correct command syntax: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest - -.. _setting_hadoop_kubernetes_connectivity_parameters: - -Setting the Hadoop and Kubernetes Connectivity Parameters -------------------------------- -The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. - -The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: console - - $ sudo ./sqream-install -p -e : - -The following is an example of setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: console - - $ sudo ./sqream-install -p -e kdc.sq.com:<192.168.1.111> - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files `. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files `. - -Modifying Your Data Ingest Folder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -d /home/sqream/data_in - -Configuring Your Network for Docker -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. - -**To configure your network for Docker:** - -1. To verify that your server network and Docker network do not overlap, run the following command: - -.. code-block:: console - - $ ifconfig | grep 172. - -2. Do one of the following: - - * If running the above command output no results, continue the installation process. - * If running the above command output results, run the following command: - - .. code-block:: console - - $ ifconfig | grep 192.168. - - -Checking and Verifying Your System Settings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your network for Docker, you can check and verify your system settings. - -Running the following command shows you all the variables used by your SQream system: - -.. code-block:: console - - $ ./sqream-install -s - -The following is an example of the correct output: - -.. code-block:: console - - SQREAM_CONSOLE_TAG=1.5.4 - SQREAM_TAG=2019.2.1 - SQREAM_EDITOR_TAG=3.0.0 - license_worker_0=f0:cc: - license_worker_1=26:91: - license_worker_2=20:26: - license_worker_3=00:36: - SQREAM_VOLUME=/media/sqreamdb - SQREAM_DATA_INGEST=/media/sqreamdb/data_in - SQREAM_CONFIG_DIR=/etc/sqream/ - LICENSE_VALID=true - SQREAM_LOG_DIR=/var/log/sqream/ - SQREAM_USER=sqream - SQREAM_HOME=/home/sqream - SQREAM_ENV_PATH=/home/sqream/.sqream/env_file - PROCESSOR=x86_64 - METADATA_PORT=3105 - PICKER_PORT=3108 - NUM_OF_GPUS=2 - CUDA_VERSION=10.1 - NVIDIA_SMI_PATH=/usr/bin/nvidia-smi - DOCKER_PATH=/usr/bin/docker - NVIDIA_DRIVER=418 - SQREAM_MODE=single_host - -Using the SQream Console -========================= -After configuring the SQream software and veriying your system settings you can begin using the SQream console. - -SQream Console - Basic Commands ---------------------------------- -The SQream console offers the following basic commands: - -* :ref:`Starting your SQream console ` -* :ref:`Starting Metadata and Picker ` -* :ref:`Starting the running services ` -* :ref:`Listing the running services ` -* :ref:`Stopping the running services ` -* :ref:`Using the SQream editor ` -* :ref:`Using the SQream Client ` - -.. _starting_sqream_console: - -Starting Your SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can start your SQream console by running the following command: - -.. code-block:: console - - $ ./sqream-console - -.. _starting_metadata_and_picker: - -Starting the SQream Master -~~~~~~~~~~~~~~~~~ - -**To listen to metadata and picker:** - -1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: - - .. code-block:: console - - $ sqream master --start - - The following is the correct output: - - .. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - -2. *Optional* - Change the metadata and server picker ports by adding ``-p `` and ``-m ``: - - .. code-block:: console - - $ sqream-console>sqream master --start -p 4105 -m 43108 - $ starting master server in single_host mode ... - $ sqream_single_host_master is up and listening on ports: 4105,4108 - - - -.. _starting_running_services: - -Starting SQream Workers -~~~~~~~~~~~~~~~~~ - - -When starting SQream workers, setting the ```` value sets how many workers to start. Leaving the ```` value unspecified runs all of the available resources. - - -.. code-block:: console - - $ sqream worker --start - - The following is an example of expected output when setting the ```` value to ``2``: - - .. code-block:: console - - sqream-console>sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - -.. _listing_running_services: - -Listing the Running Services -~~~~~~~~~~~~~~~~~ - -You can list running SQream services to look for container names and ID's by running the following command: - -.. code-block:: console - - $ sqream master --list - -The following is an example of the expected output: - -.. code-block:: console - - sqream-console>sqream master --list - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038-- - - -.. _stopping_running_services: - -Stopping the Running Services -~~~~~~~~~~~~~~~~~ - -You can stop running services either for a single SQream worker, or all SQream services for both master and worker. - -The following is the command for stopping a running service for a single SQream worker: - -.. code-block:: console - - $ sqream worker --stop - -The following is an example of expected output when stopping a running service for a single SQream worker: - -.. code-block:: console - - sqream worker stop - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - - -You can stop all running SQream services (both master and worker) by running the following command: - -.. code-block:: console - - $ sqream-console>sqream master --stop --all - -The following is an example of expected output when stopping all running services: - -.. code-block:: console - - sqream-console>sqream master --stop --all - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - stopped container sqream_single_host_master, id: 55cb7e38eb22 - - -.. _using_sqream_editor: - -Using SQream Studio -~~~~~~~~~~~~~~~~~ -SQream Studio is an SQL statement editor. - -**To start SQream Studio:** - -1. Run the following command: - - .. code-block:: console - - $ sqream studio --start - -The following is an example of the expected output: - - .. code-block:: console - - SQream Acceleration Studio is available at http://192.168.1.62:8080 - -2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. - - -**To stop SQream Studio:** - -You can stop your SQream Studio by running the following command: - -.. code-block:: console - - $ sqream studio --stop - -The following is an example of the expected output: - -.. code-block:: console - - sqream_admin stopped - - -.. _using_sqream_client: - -Using the SQream Client -~~~~~~~~~~~~~~~~~ - - -You can use the embedded SQream Client on the following nodes: - -* Master node -* Worker node - - -When using the SQream Client on the Master node, the following default settings are used: - -* **Default port**: 3108. You can change the default port using the ``-p`` variable. -* **Default database**: master. You can change the default database using the ``-d`` variable. - -The following is an example: - -.. code-block:: console - - $ sqream client --master -u sqream -w sqream - - -When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. - -The following is an example: - -.. code-block:: console - - $ sqream client --worker -p 5000 -u sqream -w sqream - - -Moving from Docker Installation to Standard On-Premises Installation ------------------------------------------------ - -Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. - -SQream Console - Advanced Commands ------------------------------ - -The SQream console offers the following advanced commands: - - -* :ref:`Controlling the spool size ` -* :ref:`Splitting a GPU ` -* :ref:`Splitting a GPU and setting the spool size ` -* :ref:`Using a custom configuration file ` -* :ref:`Clustering your Docker environment ` - - - - -.. _controlling_spool_size: - -Controlling the Spool Size -~~~~~~~~~~~~~~~~~~ - -From the console you can define a spool size value. - -The following example shows the spool size being set to ``50``: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -m 50 - - -If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. - -.. _splitting_gpu: - -Splitting a GPU -~~~~~~~~~~~~~~~~~~ - -You can start more than one sqreamd on a single GPU by splitting it. - - -The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -g 0 - -.. _splitting_gpu_setting_spool_size: - -Splitting GPU and Setting the Spool Size -~~~~~~~~~~~~~~~~~~ - -You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: - -.. code-block:: console - - $ sqream-console>sqream worker --start 2 -g 0 -m 50 - -.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. - -.. _using_custom_configuration_file: - -Using a Custom Configuration File -~~~~~~~~~~~~~~~~~~ - -SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. - -The SQream console does not validate the integrity of your external configuration files. - -When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: - -.. code-block:: console - - $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json - -.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: - -.. code-block:: console - - $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: - -.. code-block:: console - - $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. _clustering_docker_environment: - -Clustering Your Docker Environment -~~~~~~~~~~~~~~~~~~ - -SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. - -.. code-block:: console - - $ --master-host - $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 - -Checking the Status of SQream Services ---------------------------- -SQream lets you check the status of SQream services from the following locations: - -* :ref:`From the Sqream console ` -* :ref:`From outside the Sqream console ` - -.. _inside_sqream_console: - -Checking the Status of SQream Services from the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From the SQream console, you can check the status of SQream services by running the following command: - -.. code-block:: console - - $ sqream-console>sqream master --list - -The following is an example of the expected output: - -.. code-block:: console - - $ sqream-console>sqream master --list - $ checking 3 sqream services: - $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 - $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 - $ sqream_single_host_master up listens on ports: 3105,3108 - -.. _outside_sqream_console: - -Checking the Status of SQream Services from Outside the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From outside the Sqream Console, you can check the status of SQream services by running the following commands: - -.. code-block:: console - - $ sqream-status - $ NAMES STATUS PORTS - $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp - $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp - $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp - $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp - -Upgrading Your SQream System ----------------------------- -This section describes how to upgrade your SQream system. - -**To upgrade your SQream system:** - -1. Contact the SQream Support team for access to the new SQream package tarball file. - - :: - -2. Set a maintenance window to enable stopping the system while upgrading it. - - :: - -3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. - - - .. code-block:: console - - $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -4. Navigate to the new folder created as a result of extracting the tarball file: - - .. code-block:: console - - $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -5. Initiate the upgrade process: - - .. code-block:: console - - $ ./sqream-install -i - - Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. - -6. Do one of the following: - - * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. - * Select **No** to stop the upgrade process. - - SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. - - Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. - -7. When the upgrade is complete, load the SQream console and restart your services. - - For assistance, contact SQream Support. From 14870eec41a11afdd0c17022438632b48b48a030 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 29 Mar 2022 12:34:57 +0300 Subject: [PATCH 0031/1892] Updated According to V2 Requirements ... According to Shachar's comments in SQream Documentation - Table of Contents sheet --- data_ingestion/index.rst | 3 +- data_ingestion/oracle.rst | 353 ------------ feature_guides/index.rst | 1 - getting_started/index.rst | 1 - .../performing_basic_sqream_operations.rst | 1 + index.rst | 2 - operational_guides/external_data.rst | 1 - operational_guides/hdfs.rst | 252 --------- operational_guides/index.rst | 1 - operational_guides/saved_queries.rst | 122 ----- .../client_drivers/cpp/connect_test.cpp | 34 -- .../client_drivers/cpp/index.rst | 87 --- .../client_drivers/cpp/insert_test.cpp | 39 -- third_party_tools/client_drivers/index.rst | 27 +- .../client_drivers/nodejs/index.rst | 382 ------------- .../client_drivers/nodejs/sample.js | 21 - .../client_drivers/python/api-reference.rst | 191 ------- .../client_drivers/python/index.rst | 502 ------------------ .../client_drivers/python/nba-t10.csv | 10 - .../client_drivers/python/test.py | 37 -- .../client_platforms/connect.sas | 27 - .../client_platforms/connect2.sas | 27 - .../client_platforms/connect3.sas | 17 - third_party_tools/client_platforms/index.rst | 37 -- .../client_platforms/informatica.rst | 173 ------ .../client_platforms/microstrategy.rst | 185 ------- .../client_platforms/odbc-sqream.tdc | 25 - .../client_platforms/pentaho.rst | 249 --------- third_party_tools/client_platforms/php.rst | 46 -- .../client_platforms/power_bi.rst | 143 ----- third_party_tools/client_platforms/r.rst | 151 ------ .../client_platforms/sas_viya.rst | 185 ------- .../client_platforms/sql_workbench.rst | 135 ----- .../client_platforms/tableau.rst | 453 ---------------- third_party_tools/client_platforms/talend.rst | 177 ------ third_party_tools/client_platforms/test.php | 16 - .../client_platforms/tibco_spotfire.rst | 387 -------------- third_party_tools/index.rst | 1 - troubleshooting/index.rst | 5 - troubleshooting/node_js_related_issues.rst | 54 -- troubleshooting/sas_viya_related_issues.rst | 55 -- .../solving_code_126_odbc_errors.rst | 14 - ...sqream_sql_installation_related_issues.rst | 33 -- troubleshooting/tableau_related_issues.rst | 73 --- 44 files changed, 3 insertions(+), 4732 deletions(-) delete mode 100644 data_ingestion/oracle.rst delete mode 100644 operational_guides/hdfs.rst delete mode 100644 operational_guides/saved_queries.rst delete mode 100644 third_party_tools/client_drivers/cpp/connect_test.cpp delete mode 100644 third_party_tools/client_drivers/cpp/index.rst delete mode 100644 third_party_tools/client_drivers/cpp/insert_test.cpp delete mode 100644 third_party_tools/client_drivers/nodejs/index.rst delete mode 100644 third_party_tools/client_drivers/nodejs/sample.js delete mode 100644 third_party_tools/client_drivers/python/api-reference.rst delete mode 100644 third_party_tools/client_drivers/python/index.rst delete mode 100644 third_party_tools/client_drivers/python/nba-t10.csv delete mode 100644 third_party_tools/client_drivers/python/test.py delete mode 100644 third_party_tools/client_platforms/connect.sas delete mode 100644 third_party_tools/client_platforms/connect2.sas delete mode 100644 third_party_tools/client_platforms/connect3.sas delete mode 100644 third_party_tools/client_platforms/index.rst delete mode 100644 third_party_tools/client_platforms/informatica.rst delete mode 100644 third_party_tools/client_platforms/microstrategy.rst delete mode 100644 third_party_tools/client_platforms/odbc-sqream.tdc delete mode 100644 third_party_tools/client_platforms/pentaho.rst delete mode 100644 third_party_tools/client_platforms/php.rst delete mode 100644 third_party_tools/client_platforms/power_bi.rst delete mode 100644 third_party_tools/client_platforms/r.rst delete mode 100644 third_party_tools/client_platforms/sas_viya.rst delete mode 100644 third_party_tools/client_platforms/sql_workbench.rst delete mode 100644 third_party_tools/client_platforms/tableau.rst delete mode 100644 third_party_tools/client_platforms/talend.rst delete mode 100644 third_party_tools/client_platforms/test.php delete mode 100644 third_party_tools/client_platforms/tibco_spotfire.rst delete mode 100644 troubleshooting/node_js_related_issues.rst delete mode 100644 troubleshooting/sas_viya_related_issues.rst delete mode 100644 troubleshooting/solving_code_126_odbc_errors.rst delete mode 100644 troubleshooting/sqream_sql_installation_related_issues.rst delete mode 100644 troubleshooting/tableau_related_issues.rst diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index 83aca40ea..ffcb60552 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -13,6 +13,5 @@ The **Data Ingestion Sources** provides information about the following: csv parquet orc - oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file diff --git a/data_ingestion/oracle.rst b/data_ingestion/oracle.rst deleted file mode 100644 index 0b0e6d5c8..000000000 --- a/data_ingestion/oracle.rst +++ /dev/null @@ -1,353 +0,0 @@ -.. _oracle: - -********************** -Migrating Data from Oracle -********************** - -This guide covers actions required for migrating from Oracle to SQream DB with CSV files. - -.. contents:: In this topic: - :local: - - -1. Preparing the tools and login information -==================================================== - -* Migrating data from Oracle requires a username and password for your Oracle system. - -* In this guide, we'll use the `Oracle Data Pump `_ , specifically the `Data Pump Export utility `_ . - - -2. Export the desired schema -=================================== - -Use the Data Pump Export utility to export the database schema. - -The format for using the Export utility is - - ``expdp / DIRECTORY= DUMPFILE= CONTENT=metadata_only NOLOGFILE`` - -The resulting Oracle-only schema is stored in a dump file. - - -Examples ------------- - -Dump all tables -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: console - - $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only NOLOGFILE - - -Dump only specific tables -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this example, we specify two tables for dumping. - -.. code-block:: console - - $ expdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp CONTENT=metadata_only TABLES=employees,jobs NOLOGFILE - -3. Convert the Oracle dump to standard SQL -======================================================= - -Oracle's Data Pump Import utility will help us convert the dump from the previous step to standard SQL. - -The format for using the Import utility is - - ``impdp / DIRECTORY= DUMPFILE= SQLFILE= TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE`` - -* ``TRANSFORM=SEGMENT_ATTRIBUTES:N:table`` excludes segment attributes (both STORAGE and TABLESPACE) from the tables - -* ``PARTITON_OPTIONS=MERGE`` combines all partitions and subpartitions into one table. - -Example ----------- - -.. code-block:: console - - $ impdp rhendricks/secretpassword DIRECTORY=dpumpdir DUMPFILE=tables.dmp SQLFILE=sql_export.sql TRANSFORM=SEGMENT_ATTRIBUTES:N:table PARTITION_OPTIONS=MERGE - -4. Figure out the database structures -=============================================== - -Using the SQL file created in the previous step, write CREATE TABLE statements to match the schemas of the tables. - -Remove unsupported attributes ------------------------------------ - -Trim unsupported primary keys, indexes, constraints, and other unsupported Oracle attributes. - -Match data types ---------------------- - -Refer to the table below to match the Oracle source data type to a new SQream DB type: - -.. list-table:: Data types - :widths: auto - :header-rows: 1 - - * - Oracle Data type - - Precision - - SQream DB data type - * - ``CHAR(n)``, ``CHARACTER(n)`` - - Any ``n`` - - ``VARCHAR(n)`` - * - ``BLOB``, ``CLOB``, ``NCLOB``, ``LONG`` - - - - ``TEXT`` - * - ``DATE`` - - - - ``DATE`` - * - ``FLOAT(p)`` - - p <= 63 - - ``REAL`` - * - ``FLOAT(p)`` - - p > 63 - - ``FLOAT``, ``DOUBLE`` - - * - ``NCHAR(n)``, ``NVARCHAR2(n)`` - - Any ``n`` - - ``TEXT`` (alias of ``NVARCHAR``) - - * - ``NUMBER(p)``, ``NUMBER(p,0)`` - - p < 5 - - ``SMALLINT`` - - * - ``NUMBER(p)``, `NUMBER(p,0)`` - - p < 9 - - ``INT`` - - * - ``NUMBER(p)``, `NUMBER(p,0)`` - - p < 19 - - ``INT`` - - * - ``NUMBER(p)``, `NUMBER(p,0)`` - - p >= 20 - - ``BIGINT`` - - * - ``NUMBER(p,f)``, ``NUMBER(*,f)`` - - f > 0 - - ``FLOAT`` / ``DOUBLE`` - - * - ``VARCHAR(n)``, ``VARCHAR2(n)`` - - Any ``n`` - - ``VARCHAR(n)`` or ``TEXT`` - * - ``TIMESTAMP`` - - - - ``DATETIME`` - -Read more about :ref:`supported data types in SQream DB`. - -Additional considerations ------------------------------ - -* Understand how :ref:`tables are created in SQream DB` - -* Learn how :ref:`SQream DB handles null values`, particularly with regards to constraints. - -* Oracle roles and user management commands need to be rewritten to SQream DB's format. SQream DB supports :ref:`full role-based access control (RBAC)` similar to Oracle. - -5. Create the tables in SQream DB -====================================== - -After rewriting the table strucutres, create them in SQream DB. - -Example ---------- - - -Consider Oracle's ``HR.EMPLOYEES`` sample table: - -.. code-block:: sql - - CREATE TABLE employees - ( employee_id NUMBER(6) - , first_name VARCHAR2(20) - , last_name VARCHAR2(25) - CONSTRAINT emp_last_name_nn NOT NULL - , email VARCHAR2(25) - CONSTRAINT emp_email_nn NOT NULL - , phone_number VARCHAR2(20) - , hire_date DATE - CONSTRAINT emp_hire_date_nn NOT NULL - , job_id VARCHAR2(10) - CONSTRAINT emp_job_nn NOT NULL - , salary NUMBER(8,2) - , commission_pct NUMBER(2,2) - , manager_id NUMBER(6) - , department_id NUMBER(4) - , CONSTRAINT emp_salary_min - CHECK (salary > 0) - , CONSTRAINT emp_email_uk - UNIQUE (email) - ) ; - CREATE UNIQUE INDEX emp_emp_id_pk - ON employees (employee_id) ; - - ALTER TABLE employees - ADD ( CONSTRAINT emp_emp_id_pk - PRIMARY KEY (employee_id) - , CONSTRAINT emp_dept_fk - FOREIGN KEY (department_id) - REFERENCES departments - , CONSTRAINT emp_job_fk - FOREIGN KEY (job_id) - REFERENCES jobs (job_id) - , CONSTRAINT emp_manager_fk - FOREIGN KEY (manager_id) - REFERENCES employees - ) ; - -This table rewritten for SQream DB would be created like this: - -.. code-block:: postgres - - CREATE TABLE employees - ( - employee_id SMALLINT NOT NULL, - first_name VARCHAR(20), - last_name VARCHAR(25) NOT NULL, - email VARCHAR(20) NOT NULL, - phone_number VARCHAR(20), - hire_date DATE NOT NULL, - job_id VARCHAR(10) NOT NULL, - salary FLOAT, - commission_pct REAL, - manager_id SMALLINT, - department_id TINYINT - ); - - -6. Export tables to CSVs -=============================== - -Exporting CSVs from Oracle servers is not a trivial task. - -.. contents:: Options for exporting to CSVs - :local: - -Using SQL*Plus to export data lists ------------------------------------------- - -Here's a sample SQL*Plus script that will export PSVs in a format that SQream DB can read: - -:download:`Download to_csv.sql ` - -.. literalinclude:: to_csv.sql - :language: sql - :caption: Oracle SQL*Plus CSV export script - :linenos: - -Enter SQL*Plus and export tables one-by-one interactively: - -.. code-block:: console - - $ sqlplus rhendricks/secretpassword - - @spool employees - @spool jobs - [...] - EXIT - -Each table is exported as a data list file (``.lst``). - -Creating CSVs using stored procedures -------------------------------------------- - -You can use stored procedures if you have them set-up. - -Examples of `stored procedures for generating CSVs `_` can be found in the Ask The Oracle Mentors forums. - -CSV generation considerations -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* Files should be a valid CSV. By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs `_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). - -* Files are UTF-8 or ASCII encoded - -* Field delimiter is an ASCII character or characters - -* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). - -* Fields are optionally enclosed by double-quotes, or mandatory quoted if they contain one of the following characters: - - * The record delimiter or field delimiter - - * A double quote character - - * A newline - -* - If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. - - Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). - -* ``NULL`` values can be marked in two ways in the CSV: - - - An explicit null marker. For example, ``col1,\N,col3`` - - An empty field delimited by the field delimiter. For example, ``col1,,col3`` - - .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. - - -7. Place CSVs where SQream DB workers can access -======================================================= - -During data load, the :ref:`copy_from` command can run on any worker (unless explicitly speficied with the :ref:`workload_manager`). -It is important that every node has the same view of the storage being used - meaning, every SQream DB worker should have access to the files. - -* For files hosted on NFS, ensure that the mount is accessible from all servers. - -* For HDFS, ensure that SQream DB servers can access the HDFS name node with the correct user-id - -* For S3, ensure network access to the S3 endpoint - -8. Bulk load the CSVs -================================= - -Issue the :ref:`copy_from` commands to SQream DB to insert a table from the CSVs created. - -Repeat the ``COPY FROM`` command for each table exported from Oracle. - -Example -------------- - -For the ``employees`` table, run the following command: - -.. code-block:: postgres - - COPY employees FROM 'employees.lst' WITH DELIMITER '|'; - -9. Rewrite Oracle queries -===================================== - -SQream DB supports a large subset of ANSI SQL. - -You will have to refactor much of Oracle's SQL and functions that often are not ANSI SQL. - -We recommend the following resources: - -* :ref:`sql_feature_support` - to understand SQream DB's SQL feature support. - -* :ref:`sql_best_practices` - to understand best practices for SQL queries and schema design. - -* :ref:`common_table_expressions` - CTEs can be used to rewrite complex queries in a compact form. - -* :ref:`concurrency_and_locks` - to understand the difference between Oracle's transactions and SQream DB's concurrency. - -* :ref:`identity` - SQream DB supports sequences, but no triggers for auto-increment. - -* :ref:`joins` - SQream DB supports ANSI join syntax. Oracle uses the ``+`` operator which SQream DB doesn't support. - -* :ref:`saved_queries` - Saved queries can be used to emulate some stored procedures. - -* :ref:`subqueries` - SQream DB supports a limited set of subqueries. - -* :ref:`python_functions` - SQream DB supports Python User Defined Functions which can be used to run complex operations in-line. - -* :ref:`Views` - SQream DB supports logical views, but does not support materialized views. - -* :ref:`window_functions` - SQream DB supports a wide array of window functions. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index c5f472785..9a5c8621d 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -16,7 +16,6 @@ This section describes the following features: compression flexible_data_clustering python_functions - saved_queries viewing_system_objects_as_ddl workload_manager transactions diff --git a/getting_started/index.rst b/getting_started/index.rst index f9a57a460..e799d047a 100644 --- a/getting_started/index.rst +++ b/getting_started/index.rst @@ -11,6 +11,5 @@ The **Getting Started** page describes the following things you need to start us preparing_your_machine_to_install_sqream installing_sqream - creating_a_database executing_statements_in_sqream performing_basic_sqream_operations \ No newline at end of file diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst index ba0a6fc3f..81ea9b05f 100644 --- a/getting_started/performing_basic_sqream_operations.rst +++ b/getting_started/performing_basic_sqream_operations.rst @@ -11,6 +11,7 @@ After installing SQream you can perform the operations described on this page: running_the_sqream_sql_client creating_your_first_table + creating_a_database listing_tables inserting_rows running_queries diff --git a/index.rst b/index.rst index 26b7459ec..cb7d685b2 100644 --- a/index.rst +++ b/index.rst @@ -72,8 +72,6 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`Third party tools integration` - :ref:`connect_to_tableau` - :ref:`troubleshooting` guide diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index 98d157ab2..576e50ea4 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -11,5 +11,4 @@ SQream DB supports external data sources for use with :ref:`external_tables`, :r :titlesonly: s3 - hdfs diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst deleted file mode 100644 index 274926e36..000000000 --- a/operational_guides/hdfs.rst +++ /dev/null @@ -1,252 +0,0 @@ -.. _hdfs: - -.. _back_to_top_hdfs: - -Using SQream in an HDFS Environment -======================================= - -.. _configuring_an_hdfs_environment_for_the_user_sqream: - -Configuring an HDFS Environment for the User **sqream** ----------------------------------------------------------- - -This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. - -**To configure an HDFS environment for the user sqream:** - -1. Open your **bash_profile** configuration file for editing: - - .. code-block:: console - - $ vim /home/sqream/.bash_profile - -.. - Comment: - see below; do we want to be a bit more specific on what changes we're talking about? - - .. code-block:: console - - $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin - - $ #export PATH - - $ # PS1 - $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') - $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" - - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME - - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - - - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH - -3. Verify that the edits have been made: - - .. code-block:: console - - source /home/sqream/.bash_profile - -4. Check if you can access Hadoop from your machine: - - .. code-block:: console - - $ hadoop fs -ls hdfs://:8020/ - -.. - Comment: - - **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos `_ - - -5. Verify that an HDFS environment exists for SQream services: - - .. code-block:: console - - $ ls -l /etc/sqream/sqream_env.sh - -.. _step_6: - - -6. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): - - .. code-block:: console - - $ #!/bin/bash - - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME - - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - - - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH - -:ref:`Back to top ` - - -.. _authenticate_hadoop_servers_that_require_kerberos: - -Authenticating Hadoop Servers that Require Kerberos ---------------------------------------------------- - -If your Hadoop server requires Kerberos authentication, do the following: - -1. Create a principal for the user **sqream**. - - .. code-block:: console - - $ kadmin -p root/admin@SQ.COM - $ addprinc sqream@SQ.COM - -2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: - - .. code-block:: console - - $ kadmin.local - - Running **kadmin.local** does not require a password. - -3. If a password is not required, change your password to **sqream@SQ.COM**. - - .. code-block:: console - - $ change_password sqream@SQ.COM - -4. Connect to the hadoop name node using ssh: - - .. code-block:: console - - $ cd /var/run/cloudera-scm-agent/process - -5. Check the most recently modified content of the directory above: - - .. code-block:: console - - $ ls -lrt - -5. Look for a recently updated folder containing the text **hdfs**. - -The following is an example of the correct folder name: - - .. code-block:: console - - cd -hdfs- - - This folder should contain a file named **hdfs.keytab** or another similar .keytab file. - - - -.. - Comment: - Does "something" need to be replaced with "file name" - - -6. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. - -7. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: - - * core-site.xml - * hdfs-site.xml - -8. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: - - .. code-block:: console - - $ sudo chown sqream:sqream /home/sqream/hdfs.keytab - $ sudo chmod 600 /home/sqream/hdfs.keytab - -9. Log into the sqream server. - -10. Log in as the user **sqream**. - -11. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: - - .. code-block:: console - - $ klist -kt hdfs.keytab - - The following is an example of the correct output: - - .. code-block:: console - - $ sqream@Host-121 ~ $ klist -kt hdfs.keytab - $ Keytab name: FILE:hdfs.keytab - $ KVNO Timestamp Principal - $ ---- ------------------- ------------------------------------------------------ - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - -12. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. - -13. Run the following: - - .. code-block:: console - - $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM - - 13. Check the output: - - .. code-block:: console - - $ klist - - The following is an example of the correct output: - - .. code-block:: console - - $ Ticket cache: FILE:/tmp/krb5cc_1000 - $ Default principal: sqream@SQ.COM - $ - $ Valid starting Expires Service principal - $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM - -14. List the files located at the defined server name or IP address: - - .. code-block:: console - - $ hadoop fs -ls hdfs://:8020/ - -15. Do one of the following: - - * If the list below is output, continue with Step 16. - * If the list is not output, verify that your environment has been set up correctly. - -If any of the following are empty, verify that you followed :ref:`Step 6 ` in the **Configuring an HDFS Environment for the User sqream** section above correctly: - - .. code-block:: console - - $ echo $JAVA_HOME - $ echo $SQREAM_HOME - $ echo $CLASSPATH - $ echo $HADOOP_COMMON_LIB_NATIVE_DIR - $ echo $LD_LIBRARY_PATH - $ echo $PATH - -16. Verify that you copied the correct keytab file. - -17. Review this procedure to verify that you have followed each step. - -:ref:`Back to top ` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index b7ea1502d..dcad76172 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -20,7 +20,6 @@ This section summarizes the following operational guides: logging monitoring_query_performance security - saved_queries seeing_system_objects_as_ddl configuration optimization_best_practices diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst deleted file mode 100644 index d554b4dc8..000000000 --- a/operational_guides/saved_queries.rst +++ /dev/null @@ -1,122 +0,0 @@ -.. _saved_queries: - -*********************** -Saved Queries -*********************** - -Saved queries can be used to reuse a query plan for a query to eliminate compilation times for repeated queries. They also provide a way to implement 'parameterized views'. - -How saved queries work -========================== - -Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. - -Parameters support -=========================== - -Query parameters can be used as substitutes for literal expressions in queries. - -* Parameters cannot be used to substitute things like column names and table names. - -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) - -Creating a saved query -====================== - -A saved query is created using the :ref:`save_query` utility command. - -Saving a simple query ---------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); - executed - -Saving a parametrized query ------------------------------------------- - -Use parameters to replace them later at execution time. - - - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - executed - -.. TODO tip Use dollar quoting (`$$`) to avoid escaping strings. -.. this makes no sense unless you have a query which would otherwise need escaping -.. t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); -.. executed - - -Listing and executing saved queries -====================================== - -Saved queries are saved as a database objects. They can be listed in one of two ways: - -Using the :ref:`catalog`: - -.. code-block:: psql - - t=> SELECT * FROM sqream_catalog.savedqueries; - name | num_parameters - --------------------------+--------------- - select_all | 0 - select_by_weight | 1 - select_by_weight_and_team | 2 - -Using the :ref:`list_saved_queries` utility function: - -.. code-block:: psql - - t=> SELECT LIST_SAVED_QUERIES(); - saved_query - ------------------------- - select_all - select_by_weight - select_by_weight_and_team - -Executing a saved query requires calling it by it's name in a :ref:`execute_saved_query` statement. A saved query with no parameter is called without parameters. - -.. code-block:: psql - - t=> SELECT EXECUTE_SAVED_QUERY('select_all'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - [...] - -Executing a saved query with parameters requires specifying the parameters in the order they appear in the query: - -.. code-block:: psql - - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- - Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 - James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 - Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 - - -Dropping a saved query -============================= - -When you're done with a saved query, or would like to replace it with another, you can drop it with :ref:`drop_saved_query`: - -.. code-block:: psql - - t=> SELECT DROP_SAVED_QUERY('select_all'); - executed - t=> SELECT DROP_SAVED_QUERY('select_by_weight_and_team'); - executed - - t=> SELECT LIST_SAVED_QUERIES(); - saved_query - ------------------------- - select_by_weight diff --git a/third_party_tools/client_drivers/cpp/connect_test.cpp b/third_party_tools/client_drivers/cpp/connect_test.cpp deleted file mode 100644 index dc199f06b..000000000 --- a/third_party_tools/client_drivers/cpp/connect_test.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Trivial example - -#include - -#include "sqream.h" - -int main () { - - sqream::driver sqc; - - // Connection parameters: Hostname, Port, Use SSL, Username, Password, - // Database name, Service name - sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", - "raviga", "sqream"); - - // create table with data - run_direct_query(&sqc, "CREATE TABLE test_table (x int)"); - run_direct_query(&sqc, "INSERT INTO test_table VALUES (5), (6), (7), (8)"); - - // query it - sqc.new_query("SELECT * FROM test_table"); - sqc.execute_query(); - - // See the results - while (sqc.next_query_row()) { - std::cout << "Received: " << sqc.get_int(0) << std::endl; - } - - sqc.finish_query(); - - // Close the connection completely - sqc.disconnect(); - -} diff --git a/third_party_tools/client_drivers/cpp/index.rst b/third_party_tools/client_drivers/cpp/index.rst deleted file mode 100644 index fbbf6fb39..000000000 --- a/third_party_tools/client_drivers/cpp/index.rst +++ /dev/null @@ -1,87 +0,0 @@ -.. _cpp_native: - -************************* -C++ Driver -************************* - -The SQream DB C++ driver allows C++ programs and tools to connect to SQream DB. - -This tutorial shows how to write a C++ program that uses this driver. - -.. contents:: In this topic: - :depth: 2 - :local: - - -Installing the C++ driver -================================== - -Prerequisites ----------------- - -The SQream DB C++ driver was built on 64-bit Linux, and is designed to work with RHEL 7 and Ubuntu 16.04 and newer. - -Getting the library ---------------------- - -The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. - - -Extract the tarball archive ------------------------------ - -Extract the library files from the tarball - -.. code-block:: console - - $ tar xf libsqream-3.0.tar.gz - -Examples -============================================== - -Assuming there is a SQream DB worker to connect to, we'll connect to it using the application and run some statements. - -Testing the connection to SQream DB --------------------------------------------- - -Download this file by right clicking and saving to your computer :download:`connect_test.cpp `. - -.. literalinclude:: connect_test.cpp - :language: cpp - :caption: Connect to SQream DB - :linenos: - - -Compiling and running the application -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To build this code, place the library and header file in ./libsqream-3.0/ and run - -.. code-block:: console - - $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream connect_test.cpp -o connect_test - $ ./connect_test - -Modify the ``-I`` and ``-L`` arguments to match the ``.so`` library and ``.h`` file if they are in another directory. - -Creating a table and inserting values --------------------------------------------- - -Download this file by right clicking and saving to your computer :download:`insert_test.cpp `. - -.. literalinclude:: insert_test.cpp - :language: cpp - :caption: Inserting data to a SQream DB table - :linenos: - - -Compiling and running the application -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To build this code, use - -.. code-block:: console - - $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream insert_test.cpp -o insert_test - $ ./insert_test - diff --git a/third_party_tools/client_drivers/cpp/insert_test.cpp b/third_party_tools/client_drivers/cpp/insert_test.cpp deleted file mode 100644 index 8a16618a4..000000000 --- a/third_party_tools/client_drivers/cpp/insert_test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Insert with parameterized statement example - -#include - -#include "sqream.h" - -int main () { - - sqream::driver sqc; - - // Connection parameters: Hostname, Port, Use SSL, Username, Password, - // Database name, Service name - sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", - "raviga", "sqream"); - - run_direct_query(&sqc, - "CREATE TABLE animals (id INT NOT NULL, name VARCHAR(10) NOT NULL)"); - - // prepare the statement - sqc.new_query("INSERT INTO animals VALUES (?, ?)"); - sqc.execute_query(); - - // Data to insert - int row0[] = {1,2,3}; - std::string row1[] = {"Dog","Cat","Possum"}; - int len = sizeof(row0)/sizeof(row0[0]); - - for (int i = 0; i < len; ++i) { - sqc.set_int(0, row0[i]); - sqc.set_varchar(1, row1[i]); - sqc.next_query_row(); - } - - // This commits the insert - sqc.finish_query(); - - sqc.disconnect(); - -} diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index 2b486d47f..102827f22 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -20,23 +20,6 @@ The following are applicable to all operating systems: * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) * `JDBC driver `_ - -.. _python: - -* **Python** - Recommended installation via ``pip``: - - * `Python .tar file `_ - pysqream v3.1.3 (.tar.gz) - * `Python driver `_ - - -.. _nodejs: - -* **Node.JS** - Recommended installation via ``npm``: - - * `Node.JS `_ - sqream-v4.2.4 (.tar.gz) - * `Node.JS driver `_ - - .. _tableau_connector: * **Tableau**: @@ -57,7 +40,7 @@ Windows -------------- The following are applicable to Windows: -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `Sqream represenative `_ for this installer. +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `SSream represenative `_ for this installer. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. @@ -82,11 +65,6 @@ The following are applicable to Linux: * ODBC Installer - Please contact your SQream representative for this installer. - :: - -* C++ connector - `libsqream-4.0 `_ -* `C++ shared object library `_ - .. toctree:: :maxdepth: 4 @@ -94,10 +72,7 @@ The following are applicable to Linux: :titlesonly: jdbc/index - python/index - nodejs/index odbc/index - cpp/index diff --git a/third_party_tools/client_drivers/nodejs/index.rst b/third_party_tools/client_drivers/nodejs/index.rst deleted file mode 100644 index cb7db193b..000000000 --- a/third_party_tools/client_drivers/nodejs/index.rst +++ /dev/null @@ -1,382 +0,0 @@ -.. _nodejs: - -************************* -Node.JS -************************* - -The SQream DB Node.JS driver allows Javascript applications and tools connect to SQream DB. -This tutorial shows you how to write a Node application using the Node.JS interface. - -The driver requires Node 10 or newer. - -.. contents:: In this topic: - :local: - -Installing the Node.JS driver -================================== - -Prerequisites ----------------- - -* Node.JS 10 or newer. Follow instructions at `nodejs.org `_ . - -Install with NPM -------------------- - -Installing with npm is the easiest and most reliable method. -If you need to install the driver in an offline system, see the offline method below. - -.. code-block:: console - - $ npm install @sqream/sqreamdb - -Install from an offline package -------------------------------------- - -The Node driver is provided as a tarball for download from the `SQream Drivers page `_ . - -After downloading the tarball, use ``npm`` to install the offline package. - -.. code-block:: console - - $ sudo npm install sqreamdb-4.0.0.tgz - - -Connect to SQream DB with a Node.JS application -==================================================== - -Create a simple test ------------------------------------------- - -Replace the connection parameters with real parameters for a SQream DB installation. - -.. code-block:: javascript - :caption: sqreamdb-test.js - - const Connection = require('@sqream/sqreamdb'); - - const config = { - host: 'localhost', - port: 3109, - username: 'rhendricks', - password: 'super_secret_password', - connectDatabase: 'raviga', - cluster: true, - is_ssl: true, - service: 'sqream' - }; - - const query1 = 'SELECT 1 AS test, 2*6 AS "dozen"'; - - const sqream = new Connection(config); - sqream.execute(query1).then((data) => { - console.log(data); - }, (err) => { - console.error(err); - }); - - -Run the test ----------------- - -A successful run should look like this: - -.. code-block:: console - - $ node sqreamdb-test.js - [ { test: 1, dozen: 12 } ] - - -API reference -==================== - -Connection parameters ---------------------------- - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Item - - Optional - - Default - - Description - * - ``host`` - - ✗ - - None - - Hostname for SQream DB worker. For example, ``127.0.0.1``, ``sqream.mynetwork.co`` - * - ``port`` - - ✗ - - None - - Port for SQream DB end-point. For example, ``3108`` for the load balancer, ``5000`` for a worker. - * - ``username`` - - ✗ - - None - - Username of a role to use for connection. For example, ``rhendricks`` - * - ``password`` - - ✗ - - None - - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` - * - ``connectDatabase`` - - ✗ - - None - - Database name to connect to. For example, ``master`` - * - ``service`` - - ✓ - - ``sqream`` - - Specifices service queue to use. For example, ``etl`` - * - ``is_ssl`` - - ✓ - - ``false`` - - Specifies SSL for this connection. For example, ``true`` - * - ``cluster`` - - ✓ - - ``false`` - - Connect via load balancer (use only if exists, and check port). For example, ``true`` - -Events -------------- - -The connector handles event returns with an event emitter - -getConnectionId - The ``getConnectionId`` event returns the executing connection ID. - -getStatementId - The ``getStatementId`` event returns the executing statement ID. - -getTypes - The ``getTypes`` event returns the results columns types. - -Example -^^^^^^^^^^^^^^^^^ - -.. code-block:: javascript - - const myConnection = new Connection(config); - - myConnection.runQuery(query1, function (err, data){ - myConnection.events.on('getConnectionId', function(data){ - console.log('getConnectionId', data); - }); - - myConnection.events.on('getStatementId', function(data){ - console.log('getStatementId', data); - }); - - myConnection.events.on('getTypes', function(data){ - console.log('getTypes', data); - }); - }); - -Input placeholders -------------------------- - -The Node.JS driver can replace parameters in a statement. - -Input placeholders allow values like user input to be passed as parameters into queries, with proper escaping. - -The valid placeholder formats are provided in the table below. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Placeholder - - Type - * - ``%i`` - - Identifier (e.g. table name, column name) - * - ``%s`` - - A text string - * - ``%d`` - - A number value - * - ``%b`` - - A boolean value - -See the :ref:`input placeholders example` below. - -Examples -=============== - -Setting configuration flags ------------------------------------ - -SQream DB configuration flags can be set per statement, as a parameter to ``runQuery``. - -For example: - -.. code-block:: javascript - - const setFlag = 'SET showfullexceptioninfo = true;'; - - const query_string = 'SELECT 1'; - - const myConnection = new Connection(config); - myConnection.runQuery(query_string, function (err, data){ - console.log(err, data); - }, setFlag); - - -Lazyloading ------------------------------------ - -To process rows without keeping them in memory, you can lazyload the rows with an async: - -.. code-block:: javascript - - - const Connection = require('@sqream/sqreamdb'); - - const config = { - host: 'localhost', - port: 3109, - username: 'rhendricks', - password: 'super_secret_password', - connectDatabase: 'raviga', - cluster: true, - is_ssl: true, - service: 'sqream' - }; - - const sqream = new Connection(config); - - const query = "SELECT * FROM public.a_very_large_table"; - - (async () => { - const cursor = await sqream.executeCursor(query); - let count = 0; - for await (let rows of cursor.fetchIterator(100)) { - // fetch rows in chunks of 100 - count += rows.length; - } - await cursor.close(); - return count; - })().then((total) => { - console.log('Total rows', total); - }, (err) => { - console.error(err); - }); - - -Reusing a connection ------------------------------------ - -It is possible to execeute multiple queries with the same connection (although only one query can be executed at a time). - -.. code-block:: javascript - - const Connection = require('@sqream/sqreamdb'); - - const config = { - host: 'localhost', - port: 3109, - username: 'rhendricks', - password: 'super_secret_password', - connectDatabase: 'raviga', - cluster: true, - is_ssl: true, - service: 'sqream' - }; - - const sqream = new Connection(config); - - (async () => { - - const conn = await sqream.connect(); - try { - const res1 = await conn.execute("SELECT 1"); - const res2 = await conn.execute("SELECT 2"); - const res3 = await conn.execute("SELECT 3"); - conn.disconnect(); - return {res1, res2, res3}; - } catch (err) { - conn.disconnect(); - throw err; - } - - })().then((res) => { - console.log('Results', res) - }, (err) => { - console.error(err); - }); - - -.. _input_placeholders_example: - -Using placeholders in queries ------------------------------------ - -Input placeholders allow values like user input to be passed as parameters into queries, with proper escaping. - -.. code-block:: javascript - - const Connection = require('@sqream/sqreamdb'); - - const config = { - host: 'localhost', - port: 3109, - username: 'rhendricks', - password: 'super_secret_password', - connectDatabase: 'raviga', - cluster: true, - is_ssl: true, - service: 'sqream' - }; - - const sqream = new Connection(config); - - const sql = "SELECT %i FROM public.%i WHERE name = %s AND num > %d AND active = %b"; - - sqream.execute(sql, "col1", "table2", "john's", 50, true); - - -The query that will run is ``SELECT col1 FROM public.table2 WHERE name = 'john''s' AND num > 50 AND active = true`` - - -Troubleshooting and recommended configuration -================================================ - - -Preventing ``heap out of memory`` errors --------------------------------------------- - -Some workloads may cause Node.JS to fail with the error: - -.. code-block:: none - - FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory - -To prevent this error, modify the heap size configuration by setting the ``--max-old-space-size`` run flag. - -For example, set the space size to 2GB: - -.. code-block:: console - - $ node --max-old-space-size=2048 my-application.js - -BIGINT support ------------------------- - -The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. - -The error that appears is: -.. code-block:: none - - TypeError: Do not know how to serialize a BigInt - -This is because JSON specification do not support BIGINT values, even when supported by Javascript engines. - -To resolve this issue, objects with BIGINT values should be converted to string before serializing, and converted back after deserializing. - -For example: - -.. code-block:: javascript - - const rows = [{test: 1n}] - const json = JSON.stringify(rows, , (key, value) => - typeof value === 'bigint' - ? value.toString() - : value // return everything else unchanged - )); - console.log(json); // [{"test": "1"}] - diff --git a/third_party_tools/client_drivers/nodejs/sample.js b/third_party_tools/client_drivers/nodejs/sample.js deleted file mode 100644 index a8ec3db66..000000000 --- a/third_party_tools/client_drivers/nodejs/sample.js +++ /dev/null @@ -1,21 +0,0 @@ -const Connection = require('@sqream/sqreamdb'); - -const config = { - host: 'localhost', - port: 3109, - username: 'rhendricks', - password: 'super_secret_password', - connectDatabase: 'raviga', - cluster: true, - is_ssl: true, - service: 'sqream' - }; - -const query1 = 'SELECT 1 AS test, 2*6 AS "dozen"'; - -const sqream = new Connection(config); -sqream.execute(query1).then((data) => { - console.log(data); -}, (err) => { - console.error(err); -}); \ No newline at end of file diff --git a/third_party_tools/client_drivers/python/api-reference.rst b/third_party_tools/client_drivers/python/api-reference.rst deleted file mode 100644 index 28e1205e6..000000000 --- a/third_party_tools/client_drivers/python/api-reference.rst +++ /dev/null @@ -1,191 +0,0 @@ -.. _pysqream_api_reference: - -************************* -pysqream API reference -************************* - -The SQream Python connector allows Python programs to connect to SQream DB. - -pysqream conforms to Python DB-API specifications `PEP-249 `_ - - -The main module is pysqream, which contains the :py:meth:`Connection` class. - -.. method:: connect(host, port, database, username, password, clustered = False, use_ssl = False, service='sqream', reconnect_attempts=3, reconnect_interval=10) - - Creates a new :py:meth:`Connection` object and connects to SQream DB. - - host - SQream DB hostname or IP - - port - SQream DB port - - database - database name - - username - Username to use for connection - - password - Password for ``username`` - - clustered - Connect through load balancer, or direct to worker (Default: false - direct to worker) - - use_ssl - use SSL connection (default: false) - - service - Optional service queue (default: 'sqream') - - reconnect_attempts - Number of reconnection attempts to attempt before closing the connection - - reconnect_interval - Time in seconds between each reconnection attempt - -.. class:: Connection - - .. attribute:: arraysize - - Specifies the number of rows to fetch at a time with :py:meth:`~Connection.fetchmany`. Defaults to 1 - one row at a time. - - .. attribute:: rowcount - - Unused, always returns -1. - - .. attribute:: description - - Read-only attribute that contains result set metadata. - - This attribute is populated after a statement is executed. - - .. list-table:: - :widths: auto - :header-rows: 1 - - * - Value - - Description - * - ``name`` - - Column name - * - ``type_code`` - - Internal type code - * - ``display_size`` - - Not used - same as ``internal_size`` - * - ``internal_size`` - - Data size in bytes - * - ``precision`` - - Precision of numeric data (not used) - * - ``scale`` - - Scale for numeric data (not used) - * - ``null_ok`` - - Specifies if ``NULL`` values are allowed for this column - - .. method:: execute(self, query, params=None) - - Execute a statement. - - Parameters are not supported - - self - :py:meth:`Connection` - - query - statement or query text - - params - Unused - - .. method:: executemany(self, query, rows_or_cols=None, data_as='rows', amount=None) - - Prepares a statement and executes it against all parameter sequences found in ``rows_or_cols``. - - self - :py:meth:`Connection` - - query - INSERT statement - - rows_or_cols - Data buffer to insert. This should be a sequence of lists or tuples. - - data_as - (Optional) Read data as rows or columns - - amount - (Optional) count of rows to insert - - .. method:: close(self) - - Close a statement and connection. - After a statement is closed, it must be reopened by creating a new cursor. - - self - :py:meth:`Connection` - - .. method:: cursor(self) - - Create a new :py:meth:`Connection` cursor. - - We recommend creating a new cursor for every statement. - - self - :py:meth:`Connection` - - .. method:: fetchall(self, data_as='rows') - - Fetch all remaining records from the result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - data_as - (Optional) Read data as rows or columns - - .. method:: fetchone(self, data_as='rows') - - Fetch one record from the result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - data_as - (Optional) Read data as rows or columns - - - .. method:: fetchmany(self, size=[Connection.arraysize], data_as='rows') - - Fetches the next several rows of a query result set. - - An empty sequence is returned when no more rows are available. - - self - :py:meth:`Connection` - - size - Number of records to fetch. If not set, fetches :py:obj:`Connection.arraysize` (1 by default) records - - data_as - (Optional) Read data as rows or columns - - .. method:: __iter__() - - Makes the cursor iterable. - - -.. attribute:: apilevel = '2.0' - - String constant stating the supported API level. The connector supports API "2.0". - -.. attribute:: threadsafety = 1 - - Level of thread safety the interface supports. pysqream currently supports level 1, which states that threads can share the module, but not connections. - -.. attribute:: paramstyle = 'qmark' - - The placeholder marker. Set to ``qmark``, which is a question mark (``?``). diff --git a/third_party_tools/client_drivers/python/index.rst b/third_party_tools/client_drivers/python/index.rst deleted file mode 100644 index 1c69752d7..000000000 --- a/third_party_tools/client_drivers/python/index.rst +++ /dev/null @@ -1,502 +0,0 @@ -.. _pysqream: - -************************* -Python (pysqream) -************************* - -The SQream Python connector is a set of packages that allows Python programs to connect to SQream DB. - -* ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. - -* ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream`` - -The connector supports Python 3.6.5 and newer. - -The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 `_. - -.. contents:: In this topic: - :local: - -Installing the Python connector -================================== - -Prerequisites ----------------- - -1. Python -^^^^^^^^^^^^ - -The connector requires Python 3.6.5 or newer. To verify your version of Python: - -.. code-block:: console - - $ python --version - Python 3.7.3 - - -.. note:: If both Python 2.x and 3.x are installed, you can run ``python3`` and ``pip3`` instead of ``python`` and ``pip`` respectively for the rest of this guide - -.. warning:: If you're running on an older version, ``pip`` will fetch an older version of ``pysqream``, with version <3.0.0. This version is currently not supported. - -2. PIP -^^^^^^^^^^^^ -The Python connector is installed via ``pip``, the Python package manager and installer. - -We recommend upgrading to the latest version of ``pip`` before installing. To verify that you are on the latest version, run the following command: - -.. code-block:: console - - $ python -m pip install --upgrade pip - Collecting pip - Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) - |████████████████████████████████| 1.4MB 1.6MB/s - Installing collected packages: pip - Found existing installation: pip 19.1.1 - Uninstalling pip-19.1.1: - Successfully uninstalled pip-19.1.1 - Successfully installed pip-19.3.1 - -.. note:: - * On macOS, you may want to use virtualenv to install Python and the connector, to ensure compatibility with the built-in Python environment - * If you encounter an error including ``SSLError`` or ``WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.`` - please be sure to reinstall Python with SSL enabled, or use virtualenv or Anaconda. - -3. OpenSSL for Linux -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Some distributions of Python do not include OpenSSL. The Python connector relies on OpenSSL for secure connections to SQream DB. - -* To install OpenSSL on RHEL/CentOS - - .. code-block:: console - - $ sudo yum install -y libffi-devel openssl-devel - -* To install OpenSSL on Ubuntu - - .. code-block:: console - - $ sudo apt-get install libssl-dev libffi-dev -y - -4. Cython (optional) -^^^^^^^^^^^^^^^^^^^^^^^^ - -Optional but highly recommended is Cython, which improves performance of Python applications. - - .. code-block:: console - - $ pip install cython - -Install via pip ------------------ - -The Python connector is available via `PyPi `_. - -Install the connector with ``pip``: - -.. code-block:: console - - $ pip install pysqream pysqream-sqlalchemy - -``pip`` will automatically install all necessary libraries and modules. - -Upgrading an existing installation --------------------------------------- - -The Python drivers are updated periodically. -To upgrade an existing pysqream installation, use pip's ``-U`` flag. - -.. code-block:: console - - $ pip install pysqream pysqream-sqlalchemy -U - - -Validate the installation ------------------------------ - -Create a file called ``test.py``, containing the following: - -.. literalinclude:: test.py - :language: python - :caption: pysqream Validation Script - :linenos: - -Make sure to replace the parameters in the connection with the respective parameters for your SQream DB installation. - -Run the test file to verify that you can connect to SQream DB: - -.. code-block:: console - - $ python test.py - Version: v2020.1 - -If all went well, you are now ready to build an application using the SQream DB Python connector! - -If any connection error appears, verify that you have access to a running SQream DB and that the connection parameters are correct. - -SQLAlchemy examples -======================== - -SQLAlchemy is an ORM for Python. - -When you install the SQream DB dialect (``pysqream-sqlalchemy``) you can use frameworks like Pandas, TensorFlow, and Alembic to query SQream DB directly. - -A simple connection example ---------------------------------- - -.. code-block:: python - - import sqlalchemy as sa - from sqlalchemy.engine.url import URL - - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) - - engine = sa.create_engine(engine_url) - - res = engine.execute('create table test (ints int)') - res = engine.execute('insert into test values (5), (6)') - res = engine.execute('select * from test') - -Pulling a table into Pandas ---------------------------------- - -In this example, we use the URL method to create the connection string. - -.. code-block:: python - - import sqlalchemy as sa - import pandas as pd - from sqlalchemy.engine.url import URL - - - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) - - engine = sa.create_engine(engine_url) - - table_df = pd.read_sql("select * from nba", con=engine) - - -API Examples -=============== - -Explaining the connection example ---------------------------------------- - -First, import the package and create a connection - -.. code-block:: python - - # Import pysqream package - - import pysqream - - """ - Connection parameters include: - * IP/Hostname - * Port - * database name - * username - * password - * Connect through load balancer, or direct to worker (Default: false - direct to worker) - * use SSL connection (default: false) - * Optional service queue (default: 'sqream') - """ - - # Create a connection object - - con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - -Then, run a query and fetch the results - -.. code-block:: python - - cur = con.cursor() # Create a new cursor - # Prepare and execute a query - cur.execute('select show_version()') - - result = cur.fetchall() # `fetchall` gets the entire data set - - print (f"Version: {result[0][0]}") - -This should print the SQream DB version. For example ``v2020.1``. - -Finally, we will close the connection - -.. code-block:: python - - con.close() - -Using the cursor --------------------------------------------- - -The DB-API specification includes several methods for fetching results from the cursor. - -We will use the ``nba`` example. Here's a peek at the table contents: - -.. csv-table:: nba - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -Like before, we will import the library and create a :py:meth:`~Connection`, followed by :py:meth:`~Connection.execute` on a simple ``SELECT *`` query. - -.. code-block:: python - - import pysqream - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - - cur = con.cursor() # Create a new cursor - # The select statement: - statement = 'SELECT * FROM nba' - cur.execute(statement) - -After executing the statement, we have a :py:meth:`Connection` cursor object waiting. A cursor is iterable, meaning that everytime we fetch, it advances the cursor to the next row. - -Use :py:meth:`~Connection.fetchone` to get one record at a time: - -.. code-block:: python - - first_row = cur.fetchone() # Fetch one row at a time (first row) - - second_row = cur.fetchone() # Fetch one row at a time (second row) - -To get several rows at a time, use :py:meth:`~Connection.fetchmany`: - -.. code-block:: python - - # executing `fetchone` twice is equivalent to this form: - third_and_fourth_rows = cur.fetchmany(2) - -To get all rows at once, use :py:meth:`~Connection.fetchall`: - -.. code-block:: python - - # To get all rows at once, use `fetchall` - remaining_rows = cur.fetchall() - - # Close the connection when done - con.close() - -Here are the contents of the row variables we used: - -.. code-block:: pycon - - >>> print(first_row) - ('Avery Bradley', 'Boston Celtics', 0, 'PG', 25, '6-2', 180, 'Texas', 7730337) - >>> print(second_row) - ('Jae Crowder', 'Boston Celtics', 99, 'SF', 25, '6-6', 235, 'Marquette', 6796117) - >>> print(third_and_fourth_rows) - [('John Holland', 'Boston Celtics', 30, 'SG', 27, '6-5', 205, 'Boston University', None), ('R.J. Hunter', 'Boston Celtics', 28, 'SG', 22, '6-5', 185, 'Georgia State', 1148640)] - >>> print(remaining_rows) - [('Jonas Jerebko', 'Boston Celtics', 8, 'PF', 29, '6-10', 231, None, 5000000), ('Amir Johnson', 'Boston Celtics', 90, 'PF', 29, '6-9', 240, None, 12000000), ('Jordan Mickey', 'Boston Celtics', 55, 'PF', 21, '6-8', 235, 'LSU', 1170960), ('Kelly Olynyk', 'Boston Celtics', 41, 'C', 25, '7-0', 238, 'Gonzaga', 2165160), - [...] - -.. note:: Calling a fetch command after all rows have been fetched will return an empty array (``[]``). - -Reading result metadata ----------------------------- - -When executing a statement, the connection object also contains metadata about the result set (e.g.column names, types, etc). - -The metadata is stored in the :py:attr:`Connection.description` object of the cursor. - -.. code-block:: pycon - - >>> import pysqream - >>> con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - ... , username='rhendricks', password='Tr0ub4dor&3' - ... , clustered=True) - >>> cur = con.cursor() - >>> statement = 'SELECT * FROM nba' - >>> cur.execute(statement) - - >>> print(cur.description) - [('Name', 'STRING', 24, 24, None, None, True), ('Team', 'STRING', 22, 22, None, None, True), ('Number', 'NUMBER', 1, 1, None, None, True), ('Position', 'STRING', 2, 2, None, None, True), ('Age (as of 2018)', 'NUMBER', 1, 1, None, None, True), ('Height', 'STRING', 4, 4, None, None, True), ('Weight', 'NUMBER', 2, 2, None, None, True), ('College', 'STRING', 21, 21, None, None, True), ('Salary', 'NUMBER', 4, 4, None, None, True)] - -To get a list of column names, iterate over the ``description`` list: - -.. code-block:: pycon - - >>> [ i[0] for i in cur.description ] - ['Name', 'Team', 'Number', 'Position', 'Age (as of 2018)', 'Height', 'Weight', 'College', 'Salary'] - -Loading data into a table ---------------------------- - -This example loads 10,000 rows of dummy data to a SQream DB instance - -.. code-block:: python - - import pysqream - from datetime import date, datetime - from time import time - - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - - # Create a table for loading - create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' - con.execute(create) - - # After creating the table, we can load data into it with the INSERT command - - # Create dummy data which matches the table we created - data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "Marty McFly" , u"キウイは楽しい鳥です" , date(2019, 12, 17), datetime(1955, 11, 4, 1, 23, 0, 0)) - - - row_count = 10**4 - - # Get a new cursor - cur = con.cursor() - insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)' - start = time() - cur.executemany(insert, [data] * row_count) - print (f"Total insert time for {row_count} rows: {time() - start} seconds") - - # Close this cursor - cur.close() - - # Verify that the data was inserted correctly - # Get a new cursor - cur = con.cursor() - cur.execute('select count(*) from perf') - result = cur.fetchall() # `fetchall` collects the entire data set - print (f"Count of inserted rows: {result[0][0]}") - - # When done, close the cursor - cur.close() - - # Close the connection - con.close() - -Reading data from a CSV file for load into a table ----------------------------------------------------------- - -We will write a helper function to create an :ref:`insert` statement, by reading an existing table's metadata. - -.. code-block:: python - - import pysqream - import datetime - - def insert_from_csv(cur, table_name, csv_filename, field_delimiter = ',', null_markers = []): - """ - We will first ask SQream DB for some table information. - This is important for understanding the number of columns, and will help - to create a matching INSERT statement - """ - - column_info = cur.execute(f"SELECT * FROM {table_name} LIMIT 0").description - - - def parse_datetime(v): - try: - return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S.%f') - except ValueError: - try: - return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S') - except ValueError: - return datetime.datetime.strptime(row[i], '%Y-%m-%d') - - # Create enough placeholders (`?`) for the INSERT query string - qstring = ','.join(['?'] * len(column_info)) - insert_statement = f"insert into {table_name} values ({qstring})" - - # Open the CSV file - with open(csv_filename, mode='r') as csv_file: - csv_reader = csv.reader(csv_file, delimiter=field_delimiter) - - # Execute the INSERT statement with the CSV data - cur.executemany(insert_statement, [row for row in csv_reader]) - - - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - - cur = con.cursor() - insert_from_csv(cur, 'nba', 'nba.csv', field_delimiter = ',', null_markers = []) - - con.close() - - -Using SQLAlchemy ORM to create tables and fill them with data ------------------------------------------------------------------------ - -You can also use the ORM to create tables and insert data to them from Python objects. - -For example: - -.. code-block:: python - - import sqlalchemy as sa - import pandas as pd - from sqlalchemy.engine.url import URL - - - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) - - engine = sa.create_engine(engine_url) - - # Build a metadata object and bind it - - metadata = sa.MetaData() - metadata.bind = engine - - # Create a table in the local metadata - - employees = sa.Table( - 'employees' - , metadata - , sa.Column('id', sa.Integer) - , sa.Column('name', sa.VARCHAR(32)) - , sa.Column('lastname', sa.VARCHAR(32)) - , sa.Column('salary', sa.Float) - ) - - # The create_all() function uses the SQream DB engine object - # to create all the defined table objects. - - metadata.create_all(engine) - - # Now that the table exists, we can insert data into it. - - # Build the data rows - insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks', 'salary': 12000.75} - ,{'id': 3, 'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0} - ,{'id': 8, 'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40} - ] - - # Build the insert command - ins = employees.insert(insert_data) - - # Execute the command - result = engine.execute(ins) - -.. toctree:: - :maxdepth: 8 - :caption: Further information - - api-reference diff --git a/third_party_tools/client_drivers/python/nba-t10.csv b/third_party_tools/client_drivers/python/nba-t10.csv deleted file mode 100644 index fe9ced442..000000000 --- a/third_party_tools/client_drivers/python/nba-t10.csv +++ /dev/null @@ -1,10 +0,0 @@ -Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 diff --git a/third_party_tools/client_drivers/python/test.py b/third_party_tools/client_drivers/python/test.py deleted file mode 100644 index 51d0b4a92..000000000 --- a/third_party_tools/client_drivers/python/test.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python - -import pysqream - -""" -Connection parameters include: -* IP/Hostname -* Port -* database name -* username -* password -* Connect through load balancer, or direct to worker (Default: false - direct to worker) -* use SSL connection (default: false) -* Optional service queue (default: 'sqream') -""" - -# Create a connection object - -con = pysqream.connect(host='127.0.0.1', port=5000, database='master' - , username='sqream', password='sqream' - , clustered=False) - -# Create a new cursor -cur = con.cursor() - -# Prepare and execute a query -cur.execute('select show_version()') - -result = cur.fetchall() # `fetchall` gets the entire data set - -print (f"Version: {result[0][0]}") - -# This should print the SQream DB version. For example ``Version: v2020.1``. - -# Finally, close the connection - -con.close() \ No newline at end of file diff --git a/third_party_tools/client_platforms/connect.sas b/third_party_tools/client_platforms/connect.sas deleted file mode 100644 index 78c670762..000000000 --- a/third_party_tools/client_platforms/connect.sas +++ /dev/null @@ -1,27 +0,0 @@ -options sastrace='d,d,d,d' -sastraceloc=saslog -nostsuffix -msglevel=i -sql_ip_trace=(note,source) -DEBUG=DBMS_SELECT; - -options validvarname=any; - -libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" - classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" - URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" - user="rhendricks" - password="Tr0ub4dor3" - schema="public" - PRESERVE_TAB_NAMES=YES - PRESERVE_COL_NAMES=YES; - -proc sql; - title 'Customers table'; - select * - from sqlib.customers; -quit; - -data sqlib.customers; - set sqlib.customers; -run; \ No newline at end of file diff --git a/third_party_tools/client_platforms/connect2.sas b/third_party_tools/client_platforms/connect2.sas deleted file mode 100644 index 10fcdb0a2..000000000 --- a/third_party_tools/client_platforms/connect2.sas +++ /dev/null @@ -1,27 +0,0 @@ -options sastrace='d,d,d,d' -sastraceloc=saslog -nostsuffix -msglevel=i -sql_ip_trace=(note,source) -DEBUG=DBMS_SELECT; - -options validvarname=any; - -libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" - classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" - URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" - user="rhendricks" - password="Tr0ub4dor3" - schema="public" - PRESERVE_TAB_NAMES=YES - PRESERVE_COL_NAMES=YES; - -proc sql; - title 'Customers table'; - select * - from sqlib.customers; -quit; - -data sqlib.customers; - set sqlib.customers; -run; \ No newline at end of file diff --git a/third_party_tools/client_platforms/connect3.sas b/third_party_tools/client_platforms/connect3.sas deleted file mode 100644 index c1bf11dcf..000000000 --- a/third_party_tools/client_platforms/connect3.sas +++ /dev/null @@ -1,17 +0,0 @@ -options sastrace='d,d,d,d' -sastraceloc=saslog -nostsuffix -msglevel=i -sql_ip_trace=(note,source) -DEBUG=DBMS_SELECT; - -options validvarname=any; - -libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" - classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" - URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" - user="rhendricks" - password="Tr0ub4dor3" - schema="public" - PRESERVE_TAB_NAMES=YES - PRESERVE_COL_NAMES=YES; \ No newline at end of file diff --git a/third_party_tools/client_platforms/index.rst b/third_party_tools/client_platforms/index.rst deleted file mode 100644 index 30280c788..000000000 --- a/third_party_tools/client_platforms/index.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _client_platforms: - -************************************ -Client Platforms -************************************ -These topics explain how to install and connect a variety of third party tools. - -Browse the articles below, in the sidebar, or use the search to find the information you need. - -Overview -========== - -SQream DB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, tools, vizualisers, and utilities. - -The tools listed have been tested and approved for use with SQream DB. Most 3\ :sup:`rd` party tools that work through JDBC, ODBC, and Python should work. - -If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support `_ or contact your SQream account manager for more information. - -.. toctree:: - :maxdepth: 4 - :caption: In this section: - :titlesonly: - - power_bi - tibco_spotfire - sas_viya - sql_workbench - tableau - pentaho - microstrategy - informatica - r - php - xxtalend - xxdiagnosing_common_connectivity_issues - -.. image:: /_static/images/connectivity_ecosystem.png \ No newline at end of file diff --git a/third_party_tools/client_platforms/informatica.rst b/third_party_tools/client_platforms/informatica.rst deleted file mode 100644 index 6bc50b22a..000000000 --- a/third_party_tools/client_platforms/informatica.rst +++ /dev/null @@ -1,173 +0,0 @@ -.. _informatica: - -************************* -Connect to SQream Using Informatica Cloud Services -************************* - -Overview -========= -The **Connecting to SQream Using Informatica Cloud Services** page is quick start guide for connecting to SQream using Informatica cloud services. - -It describes the following: - -.. contents:: - :local: - -Establishing a Connection between SQream and Informatica ------------------ -The **Establishing a Connection between SQream and Informatica** page describes how to establish a connection between SQream and the Informatica data integration Cloud. - -**To establish a connection between SQream and the Informatica data integration Cloud:** - -1. Go to the `Informatica Cloud homepage `_. - - :: - -2. Do one of the following: - - 1. Log in using your credentials. - - :: - - 2. Log in using your SAML Identity Provider. - -3. From the **Services** window, select **Administrator** or click **Show all services** to show all services. - - - The SQream dashboard is displayed. - - - :: - - -4. In the menu on the left, click **Runtime Environments**. - - - The **Runtime Environments** panel is displayed. - - :: - -5. Click **Download Secure Agent**. - - :: - -6. When the **Download the Secure Agent** panel is displayed, do the following: - - 1. Select a platform (Windows 64 or Linux 64). - - :: - - - 2. Click **Copy** and save the token on your local hard drive. - - The token is used in combination with your user name to authorize the agent to access your account. - - -7. Click **Download**. - - The installation begins. - - :: - -8. When the **Informatica Cloud Secure Agent Setup** panel is displayed, click **Next**. - - - :: - - -9. Provide your **User Name** and **Install Token** and click **Register**. - - :: - - - -10. From the Runtime Environments panel, click **New Runtime Environment**. - - - The **New Secure Agent Group** window is displayed. - - :: - -11. On the New Secure Agent Group window, click **OK** to connect your Runtime Environment with the running agent. - - .. note:: If you do not download Secure Agent, you will not be able to connect your Runtime Environment with the running agent and continue establishing a connection between SQream and the Informatica data integration Cloud. - -Establishing a Connection In Your Environment ------------------ - -The **Establishing a Connection In Your Environment** describes the following: - -.. contents:: - :local: - -Establishing an ODBC DSN Connection In Your Environment -~~~~~~~~~~~~~ -After establishing a connection between SQream and Informatica you can establish an ODBC DSN connection in your environment. - -**To establish an ODBC connection in your environment:** - -1. Click **Add**. - - :: - -2. Click **Configure**. - - .. note:: Verify that **Use Server Picker** is selected. - -3. Click **Test**. - - :: - -4. Verify that the connection has tested successfully. - - :: - -5. Click **Save**. - - :: - -6. Click **Actions** > **Publish**. - -Establishing a JDBC Connection In Your Environment -~~~~~~~~~~~~~ -After establishing a connection between SQream and Informatica you can establish a JDBC connection in your environment. - -**To establish a JDBC connection in your environment:** - -1. Create a new DB connection by clicking **Connections** > **New Connection**. - - The **New Connection** window is displayed. - - :: - - -2. In the **JDBC_IC Connection Properties** section, in the **JDBC Connection URL** field, establish a JDBC connection by providing the correct connection string. - - For connection string examples, see `Connection Strings `_. - - :: - -3. Click **Test**. - - :: - -4. Verify that the connection has tested successfully. - - :: - -5. Click **Save**. - - :: - -6. Click **Actions** > **Publish**. - -Supported SQream Driver Versions ---------------- - -SQream supports the following SQream driver versions: - -* **JDBC** - Version 4.3.4 and above. - - :: - -* **ODBC** - Version 4.0.0 and above. diff --git a/third_party_tools/client_platforms/microstrategy.rst b/third_party_tools/client_platforms/microstrategy.rst deleted file mode 100644 index 6d2be281f..000000000 --- a/third_party_tools/client_platforms/microstrategy.rst +++ /dev/null @@ -1,185 +0,0 @@ -.. _microstrategy: - - -************************* -Connect to SQream Using MicroStrategy -************************* - -.. _ms_top: - -Overview ---------------- -This document is a Quick Start Guide that describes how to install MicroStrategy and connect a datasource to the MicroStrategy dasbhoard for analysis. - - - -The **Connecting to SQream Using MicroStrategy** page describes the following: - - -.. contents:: - :local: - - - - - - -What is MicroStrategy? -================ -MicroStrategy is a Business Intelligence software offering a wide variety of data analytics capabilities. SQream uses the MicroStrategy connector for reading and loading data into SQream. - -MicroStrategy provides the following: - -* Data discovery -* Advanced analytics -* Data visualization -* Embedded BI -* Banded reports and statements - - -For more information about Microstrategy, see `MicroStrategy `_. - - - -:ref:`Back to Overview ` - - - - - -Connecting a Data Source -======================= - -1. Activate the **MicroStrategy Desktop** app. The app displays the Dossiers panel to the right. - - :: - -2. Download the most current version of the `SQream JDBC driver `_. - - :: - -3. Click **Dossiers** and **New Dossier**. The **Untitled Dossier** panel is displayed. - - :: - -4. Click **New Data**. - - :: - -5. From the **Data Sources** panel, select **Databases** to access data from tables. The **Select Import Options** panel is displayed. - - :: - -6. Select one of the following: - - * Build a Query - * Type a Query - * Select Tables - - :: - -7. Click **Next**. - - :: - -8. In the Data Source panel, do the following: - - 1. From the **Database** dropdown menu, select **Generic**. The **Host Name**, **Port Number**, and **Database Name** fields are removed from the panel. - - :: - - 2. In the **Version** dropdown menu, verify that **Generic DBMS** is selected. - - :: - - 3. Click **Show Connection String**. - - :: - - 4. Select the **Edit connection string** checkbox. - - :: - - 5. From the **Driver** dropdown menu, select a driver for one of the following connectors: - - * **JDBC** - The SQream driver is not integrated with MicroStrategy and does not appear in the dropdown menu. However, to proceed, you must select an item, and in the next step you must specify the path to the SQream driver that you installed on your machine. - * **ODBC** - SQreamDB ODBC - - :: - - 6. In the **Connection String** text box, type the relevant connection string and path to the JDBC jar file using the following syntax: - - .. code-block:: console - - $ jdbc:Sqream:///;user=;password=sqream;[; ...] - - The following example shows the correct syntax for the JDBC connector: - - .. code-block:: console - - jdbc;MSTR_JDBC_JAR_FOLDER=C:\path\to\jdbc\folder;DRIVER=;URL={jdbc:Sqream:///;user=;password=;[; ...];} - - The following example shows the correct syntax for the ODBC connector: - - .. code-block:: console - - odbc:Driver={SqreamODBCDriver};DSN={SQreamDB ODBC};Server=;Port=;Database=;User=;Password=;Cluster=; - - For more information about the available **connection parameters** and other examples, see `Connection Parameters `_. - - 7. In the **User** and **Password** fields, fill out your user name and password. - - :: - - 8. In the **Data Source Name** field, type **SQreamDB**. - - :: - - 9. Click **Save**. The SQreamDB that you picked in the Data Source panel is displayed. - - -9. In the **Namespace** menu, select a namespace. The tables files are displayed. - - :: - -10. Drag and drop the tables into the panel on the right in your required order. - - :: - -11. **Recommended** - Click **Prepare Data** to customize your data for analysis. - - :: - -12. Click **Finish**. - - :: - -13. From the **Data Access Mode** dialog box, select one of the following: - - - * Connect Live - * Import as an In-memory Dataset - -Your populated dashboard is displayed and is ready for data discovery and analytics. - - - - - - -.. _supported_sqream_drivers: - -:ref:`Back to Overview ` - -Supported SQream Drivers -================ - -The following list shows the supported SQream drivers and versions: - -* **JDBC** - Version 4.3.3 and higher. -* **ODBC** - Version 4.0.0. - - -.. _supported_tools_and_operating_systems: - -:ref:`Back to Overview ` diff --git a/third_party_tools/client_platforms/odbc-sqream.tdc b/third_party_tools/client_platforms/odbc-sqream.tdc deleted file mode 100644 index f1bbe279d..000000000 --- a/third_party_tools/client_platforms/odbc-sqream.tdc +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/third_party_tools/client_platforms/pentaho.rst b/third_party_tools/client_platforms/pentaho.rst deleted file mode 100644 index 1cd95866f..000000000 --- a/third_party_tools/client_platforms/pentaho.rst +++ /dev/null @@ -1,249 +0,0 @@ -.. _pentaho_data_integration: - -************************* -Connect to SQream Using Pentaho Data Integration -************************* -.. _pentaho_top: - -Overview -========= -This document is a Quick Start Guide that describes how to install Pentaho, create a transformation, and define your output. - -The Connecting to SQream Using Pentaho page describes the following: - -* :ref:`Installing Pentaho ` -* :ref:`Installing and setting up the JDBC driver ` -* :ref:`Creating a transformation ` -* :ref:`Defining your output ` -* :ref:`Importing your data ` - -.. _install_pentaho: - -Installing Pentaho -~~~~~~~~~~~~~~~~~ -To install PDI, see the `Pentaho Community Edition (CE) Installation Guide `_. - -The **Pentaho Community Edition (CE) Installation Guide** describes how to do the following: - -* Downloading the PDI software. -* Installing the **JRE (Java Runtime Environment)** and **JDK (Java Development Kit)**. -* Setting up the JRE and JDK environment variables for PDI. - -:ref:`Back to Overview ` - -.. _install_set_up_jdbc_driver: - -Installing and Setting Up the JDBC Driver -~~~~~~~~~~~~~~~~~ -After installing Pentaho you must install and set up the JDBC driver. This section explains how to set up the JDBC driver using Pentaho. These instructions use Spoon, the graphical transformation and job designer associated with the PDI suite. - -You can install the driver by copying and pasting the SQream JDBC .jar file into your **/design-tools/data-integration/lib** directory. - -**NOTE:** Contact your SQream license account manager for the JDBC .jar file. - -:ref:`Back to Overview ` - -.. _create_transformation: - -Creating a Transformation -~~~~~~~~~~~~~~~~~~ -After installing Pentaho you can create a transformation. - -**To create a transformation:** - -1. Use the CLI to open the PDI client for your operating system (Windows): - - .. code-block:: console - - $ spoon.bat - -2. Open the spoon.bat file from its folder location. - -:: - -3. In the **View** tab, right-click **Transformations** and click **New**. - -A new transformation tab is created. - -4. In the **Design** tab, click **Input** to show its file contents. - -:: - -5. Drag and drop the **CSV file input** item to the new transformation tab that you created. - -:: - -6. Double-click **CSV file input**. The **CSV file input** panel is displayed. - -:: - -7. In the **Step name** field, type a name. - -:: - -8. To the right of the **Filename** field, click **Browse**. - -:: - -9. Select the file that you want to read from and click **OK**. - -:: - -10. In the CSV file input window, click **Get Fields**. - -:: - -11. In the **Sample data** window, enter the number of lines you want to sample and click **OK**. The default setting is **100**. - -The tool reads the file and suggests the field name and type. - -12. In the CSV file input window, click **Preview**. - -:: - -13. In the **Preview size** window, enter the number of rows you want to preview and click **OK**. The default setting is **1000**. - -:: - -14. Verify that the preview data is correct and click **Close**. - -:: - -15. Click **OK** in the **CSV file input** window. - -:ref:`Back to Overview ` - -.. _define_output: - -Defining Your Output ------------------ -After creating your transformation you must define your output. - -**To define your output:** - -1. In the **Design** tab, click **Output**. - - The Output folder is opened. - -2. Drag and drop **Table output** item to the Transformation window. - -:: - -3. Double-click **Table output** to open the **Table output** dialog box. - -:: - -4. From the **Table output** dialog box, type a **Step name** and click **New** to create a new connection. Your **steps** are the building blocks of a transformation, such as file input or a table output. - -The **Database Connection** window is displayed with the **General** tab selected by default. - -5. Enter or select the following information in the Database Connection window and click **Test**. - -The following table shows and describes the information that you need to fill out in the Database Connection window: - -.. list-table:: - :widths: 6 31 73 - :header-rows: 1 - - * - No. - - Element Name - - Description - * - 1 - - Connection name - - Enter a name that uniquely describes your connection, such as **sampledata**. - * - 2 - - Connection type - - Select **Generic database**. - * - 3 - - Access - - Select **Native (JDBC)**. - * - 4 - - Custom connection URL - - Insert **jdbc:Sqream:///;user=;password=;[; ...];**. The IP is a node in your SQream cluster and is the name or schema of the database you want to connect to. Verify that you have not used any leading or trailing spaces. - * - 5 - - Custom driver class name - - Insert **com.sqream.jdbc.SQDriver**. Verify that you have not used any leading or trailing spaces. - * - 6 - - Username - - Your SQreamdb username. If you leave this blank, you will be prompted to provide it when you connect. - * - 7 - - Password - - Your password. If you leave this blank, you will be prompted to provide it when you connect. - -The following message is displayed: - -.. image:: /_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png - -6. Click **OK** in the window above, in the Database Connection window, and Table Output window. - -:ref:`Back to Overview ` - -.. _import_data: - -Importing Data ------------------ -After defining your output you can begin importing your data. - -For more information about backing up users, permissions, or schedules, see `Backup and Restore Pentaho Repositories `_ - -**To import data:** - -1. Double-click the **Table output** connection that you just created. - -:: - -2. To the right of the **Target schema** field, click **Browse** and select a schema name. - -:: - -3. Click **OK**. The selected schema name is displayed in the **Target schema** field. - -:: - -4. Create a new hop connection between the **CSV file input** and **Table output** steps: - - 1. On the CSV file input step item, click the **new hop connection** icon. - - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png - - 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. - - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png - - 3. Release the mouse button. The following options are displayed. - - 4. Select **Main output of step**. - - .. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png - -:: - -5. Double-click **Table output** to open the **Table output** dialog box. - -:: - -6. In the **Target table** field, define a target table name. - -:: - -7. Click **SQL** to open the **Simple SQL editor.** - -:: - -8. In the **Simple SQL editor**, click **Execute**. - - The system processes and displays the results of the SQL statements. - -9. Close all open dialog boxes. - -:: - -10. Click the play button to execute the transformation. - - .. image:: /_static/images/third_party_connectors/pentaho/execute_transformation.png - - The **Run Options** dialog box is displayed. - -11. Click **Run**. The **Execution Results** are displayed. - -:ref:`Back to Overview ` diff --git a/third_party_tools/client_platforms/php.rst b/third_party_tools/client_platforms/php.rst deleted file mode 100644 index 599d6a578..000000000 --- a/third_party_tools/client_platforms/php.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. _php: - -***************************** -Connect to SQream Using PHP -***************************** - -You can use PHP to interact with a SQream DB cluster. - -This tutorial is a guide that will show you how to connect a PHP application to SQream DB. - -.. contents:: In this topic: - :local: - -Prerequisites -=============== - -#. Install the :ref:`SQream DB ODBC driver for Linux` and create a DSN. - -#. - Install the `uODBC `_ extension for your PHP installation. - To configure PHP to enable uODBC, configure it with ``./configure --with-pdo-odbc=unixODBC,/usr/local`` when compiling php or install ``php-odbc`` and ``php-pdo`` along with php (version 7.1 minimum for best results) using your distribution package manager. - -Testing the connection -=========================== - -#. - Create a test connection file. Be sure to use the correct parameters for your SQream DB installation. - - Download this :download:`PHP example connection file ` . - - .. literalinclude:: test.php - :language: php - :emphasize-lines: 4 - :linenos: - - .. tip:: - An example of a valid DSN line is: - - .. code:: php - - $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; - - For more information about supported DSN parameters, see :ref:`dsn_params`. - -#. Run the PHP file either directly with PHP (``php test.php``) or through a browser. - diff --git a/third_party_tools/client_platforms/power_bi.rst b/third_party_tools/client_platforms/power_bi.rst deleted file mode 100644 index 3b9f662bd..000000000 --- a/third_party_tools/client_platforms/power_bi.rst +++ /dev/null @@ -1,143 +0,0 @@ -.. _power_bi: - -************************* -Connect to SQream Using Power BI Desktop -************************* - -Overview -========= -**Power BI Desktop** lets you connect to SQream and use underlying data as with other data sources in Power BI Desktop. - -SQream integrates with Power BI Desktop to do the following: - -* Extract and transform your datasets into usable visual models in approximately one minute. - - :: - -* Use **DAX** functions **(Data Analysis Expressions)** to analyze your datasets. - - :: - -* Refresh datasets as needed or by using scheduled jobs. - -SQream uses Power BI for extracting data sets using the following methods: - -* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide `_. - - :: - -* **Import** - Lets you extract datasets from remote databases. - -The **Connect to SQream Using Power BI** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Prerequisites -------------------- -To connect to SQream, the following must be installed: - -* **ODBC data source administrator** - 32 or 64, depending on your operating system. For Windows users, the ODBC data source administrator is embedded within the operating system. - -* **SQream driver** - The SQream application required for interacting with the ODBC according to the configuration specified in the ODBC administrator tool. - -Installing Power BI Desktop -------------------- -**To install Power BI Desktop:** - -1. Download `Power BI Desktop 64x `_. - - :: - -2. Download and configure your ODBC driver. - - For more information about configuring your ODBC driver, see `ODBC `_. - -3. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. - - :: - -4. In the **Power BI Desktop** folder, create a folder called **Custom Connectors**. - - -5. From the Client Drivers page, download the **PowerQuery.mez** file. - - :: - -5. Save the PowerQuery.mez file in the **Custom Connectors** folder you created in Step 3. - - :: - -6. Open the Power BI application. - - :: - -7. Navigate to **File** > **Options and Settings** > **Option** > **Security** > **Data Extensions**, and select **(Not Recommended) Allow any extension to load without validation or warning**. - - :: - -8. Restart the Power BI Desktop application. - - :: - -9. From the **Get Data** menu, select **SQream**. - - :: - -10. Click **Connect** and provide the information shown in the following table: - - .. list-table:: - :widths: 6 31 - :header-rows: 1 - - * - Element Name - - Description - * - Server - - Provide the network address to your database server. You can use a hostname or an IP address. - * - Port - - Provide the port that the database is responding to at the network address. - * - Database - - Provide the name of your database or the schema on your database server. - * - User - - Provide a SQreamdb username. - * - Passwords - - Provide a password for your user. - -11. Under **Data Connectivity mode**, select **DirectQuery mode**. - - :: - -12. Click **Connect**. - - :: - -13. Provide your user name and password and click **Connect**. - -Best Practices for Power BI ---------------- -SQream recommends using Power BI in the following ways for acquiring the best performance metrics: - -* Creating bar, pie, line, or plot charts when illustrating one or more columns. - - :: - -* Displaying trends and statuses using visual models. - - :: - -* Creating a unified view using **PowerQuery** to connect different data sources into a single dashboard. - -Supported SQream Driver Versions ---------------- -SQream supports the following SQream driver versions: - -* The **PowerQuery Connector** is an additional layer on top of the ODBC. - - :: - -* SQream Driver Installation (ODBC v4.1.1) - Contact your administrator for the link to download ODBC v4.1.1. - -Related Information -------------------- -For more information, see the `Glossary `_. \ No newline at end of file diff --git a/third_party_tools/client_platforms/r.rst b/third_party_tools/client_platforms/r.rst deleted file mode 100644 index 6abe27031..000000000 --- a/third_party_tools/client_platforms/r.rst +++ /dev/null @@ -1,151 +0,0 @@ -.. _r: - -***************************** -Connect to SQream Using R -***************************** - -You can use R to interact with a SQream DB cluster. - -This tutorial is a guide that will show you how to connect R to SQream DB. - -.. contents:: In this topic: - :local: - -JDBC -========= - - -#. Get the :ref:`SQream DB JDBC driver`. - -#. - In R, install RJDBC - - .. code-block:: rconsole - - > install.packages("RJDBC") - Installing package into 'C:/Users/r/...' - (as 'lib' is unspecified) - - package 'RJDBC' successfully unpacked and MD5 sums checked - -#. - Import the RJDBC library - - .. code-block:: rconsole - - > library(RJDBC) - -#. - Set the classpath and initialize the JDBC driver which was previously installed. For example, on Windows: - - .. code-block:: rconsole - - > cp = c("C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") - > .jinit(classpath=cp) - > drv <- JDBC("com.sqream.jdbc.SQDriver","C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") -#. - Open a connection with a :ref:`JDBC connection string` and run your first statement - - .. code-block:: rconsole - - > con <- dbConnect(drv,"jdbc:Sqream://127.0.0.1:3108/master;user=rhendricks;password=Tr0ub4dor&3;cluster=true") - - > dbGetQuery(con,"select top 5 * from t") - xint xtinyint xsmallint xbigint - 1 1 82 5067 1 - 2 2 14 1756 2 - 3 3 91 22356 3 - 4 4 84 17232 4 - 5 5 13 14315 5 - -#. - Close the connection - - .. code-block:: rconsole - - > close(con) - -A full example ------------------ - -.. code-block:: rconsole - - > library(RJDBC) - > cp = c("C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") - > .jinit(classpath=cp) - > drv <- JDBC("com.sqream.jdbc.SQDriver","C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") - > con <- dbConnect(drv,"jdbc:Sqream://127.0.0.1:3108/master;user=rhendricks;password=Tr0ub4dor&3;cluster=true") - > dbGetQuery(con,"select top 5 * from t") - xint xtinyint xsmallint xbigint - 1 1 82 5067 1 - 2 2 14 1756 2 - 3 3 91 22356 3 - 4 4 84 17232 4 - 5 5 13 14315 5 - > close(con) - -ODBC -========= - -#. Install the :ref:`SQream DB ODBC driver` for your operating system, and create a DSN. - -#. - In R, install RODBC - - .. code-block:: rconsole - - > install.packages("RODBC") - Installing package into 'C:/Users/r/...' - (as 'lib' is unspecified) - - package 'RODBC' successfully unpacked and MD5 sums checked - -#. - Import the RODBC library - - .. code-block:: rconsole - - > library(RODBC) - -#. - Open a connection handle to an existing DSN (``my_cool_dsn`` in this example) - - .. code-block:: rconsole - - > ch <- odbcConnect("my_cool_dsn",believeNRows=F) - -#. - Run your first statement - - .. code-block:: rconsole - - > sqlQuery(ch,"select top 5 * from t") - xint xtinyint xsmallint xbigint - 1 1 82 5067 1 - 2 2 14 1756 2 - 3 3 91 22356 3 - 4 4 84 17232 4 - 5 5 13 14315 5 - -#. - Close the connection - - .. code-block:: rconsole - - > close(ch) - -A full example ------------------ - -.. code-block:: rconsole - - > library(RODBC) - > ch <- odbcConnect("my_cool_dsn",believeNRows=F) - > sqlQuery(ch,"select top 5 * from t") - xint xtinyint xsmallint xbigint - 1 1 82 5067 1 - 2 2 14 1756 2 - 3 3 91 22356 3 - 4 4 84 17232 4 - 5 5 13 14315 5 - > close(ch) diff --git a/third_party_tools/client_platforms/sas_viya.rst b/third_party_tools/client_platforms/sas_viya.rst deleted file mode 100644 index fc0806296..000000000 --- a/third_party_tools/client_platforms/sas_viya.rst +++ /dev/null @@ -1,185 +0,0 @@ -.. _connect_to_sas_viya: - -************************* -Connect to SQream Using SAS Viya -************************* - -Overview -========== -SAS Viya is a cloud-enabled analytics engine used for producing useful insights. The **Connect to SQream Using SAS Viya** page describes how to connect to SAS Viya, and describes the following: - -.. contents:: - :local: - :depth: 1 - -Installing SAS Viya -------------------- -The **Installing SAS Viya** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Downloading SAS Viya -~~~~~~~~~~~~~~~~~~ -Integrating with SQream has been tested with SAS Viya v.03.05 and newer. - -To download SAS Viya, see `SAS Viya `_. - -Installing the JDBC Driver -~~~~~~~~~~~~~~~~~~ -The SQream JDBC driver is required for establishing a connection between SAS Viya and SQream. - -**To install the JDBC driver:** - -#. Download the `JDBC driver `_. - - :: - -#. Unzip the JDBC driver into a location on the SAS Viya server. - - SQream recommends creating the directory ``/opt/sqream`` on the SAS Viya server. - -Configuring SAS Viya -------------------- -After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQream Studio. - -**To configure the JDBC driver from the SAS Studio:** - -#. Sign in to the SAS Studio. - - :: - -#. From the **New** menu, click **SAS Program**. - - :: - -#. Configure the SQream JDBC connector by adding the following rows: - - .. literalinclude:: connect3.sas - :language: php - -For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String `_. - -Operating SAS Viya --------------------- -The **Operating SAS Viya** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Using SAS Viya Visual Analytics -~~~~~~~~~~~~~~~~~~ -This section describes how to use SAS Viya Visual Analytics. - -**To use SAS Viya Visual Analytics:** - -#. Log in to `SAS Viya Visual Analytics `_ using your credentials: - - :: - -2. Click **New Report**. - - :: - -3. Click **Data**. - - :: - -4. Click **Data Sources**. - - :: - -5. Click the **Connect** icon. - - :: - -6. From the **Type** menu, select **Database**. - - :: - -7. Provide the required information and select **Persist this connection beyond the current session**. - - :: - -8. Click **Advanced** and provide the required information. - - :: - -9. Add the following additional parameters by clicking **Add Parameters**: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - Name - - Value - * - class - - com.sqream.jdbc.SQDriver - * - classPath - - ** - * - url - - \jdbc:Sqream://**:**/**;cluster=true - * - username - - - * - password - - - -10. Click **Test Connection**. - - :: - -11. If the connection is successful, click **Save**. - -If your connection is not successful, see :ref:`troubleshooting_sas_viya` below. - -.. _troubleshooting_sas_viya: - -Troubleshooting SAS Viya -------------------------- -The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: - -.. contents:: - :local: - :depth: 1 - -Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ -When using SAS Viya, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. - - :: - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. - -Creating a Separate Service for SAS Viya -~~~~~~~~~~~~~~~~~~ -SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. - -Locating the SQream JDBC Driver -~~~~~~~~~~~~~~~~~~ -In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: - -.. code-block:: text - - java.lang.ClassNotFoundException: com.sqream.jdbc.SQDriver - -**To locate the SQream JDBC driver:** - -1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. - - :: - -2. Verify that the classpath in your SAS program is correct, and that SAS Viya can access the file that it references. - - :: - -3. Restart SAS Viya. - -For more troubleshooting assistance, see the `SQream Support Portal `_. - -Supporting TEXT -~~~~~~~~~~~~~~~~~~ -In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. diff --git a/third_party_tools/client_platforms/sql_workbench.rst b/third_party_tools/client_platforms/sql_workbench.rst deleted file mode 100644 index d46d45ae6..000000000 --- a/third_party_tools/client_platforms/sql_workbench.rst +++ /dev/null @@ -1,135 +0,0 @@ -.. _connect_to_sql_workbench: - -***************************** -Connect to SQream Using SQL Workbench -***************************** - -You can use SQL Workbench to interact with a SQream DB cluster. SQL Workbench/J is a free SQL query tool, and is designed to run on any JRE-enabled environment. - -This tutorial is a guide that will show you how to connect SQL Workbench to SQream DB. - -.. contents:: In this topic: - :local: - -Installing SQL Workbench with the SQream DB installer (Windows only) -===================================================================== - -SQream DB's driver installer for Windows can install the Java prerequisites and SQL Workbench for you. - -#. Get the JDBC driver installer available for download from the `SQream Drivers page `_. The Windows installer takes care of the Java prerequisites and subsequent configuration. - -#. Install the driver by following the on-screen instructions in the easy-to-follow installer. - By default, the installer does not install SQL Workbench. Make sure to select the item! - - .. image:: /_static/images/jdbc_windows_installer_screen.png - -.. note:: The installer will install SQL Workbench in ``C:\Program Files\SQream Technologies\SQLWorkbench`` by default. You can change this path during the installation. - -#. Once finished, SQL Workbench is installed and contains the necessary configuration for connecting to SQream DB clusters. - -#. Start SQL Workbench from the Windows start menu. Be sure to select **SQL Workbench (64)** if you're on 64-bit Windows. - - .. image:: /_static/images/sql_workbench_launch.png - -You are now ready to create a profile for your cluster. Continue to :ref:`Creating a new connection profile `. - -Installing SQL Workbench manually (Linux, MacOS) -=================================================== - -Install Java Runtime ------------------------- - -Both SQL Workbench and the SQream DB JDBC driver require Java 1.8 or newer. You can install either Oracle Java or OpenJDK. - -**Oracle Java** - -Download and install Java 8 from Oracle for your platform - https://www.java.com/en/download/manual.jsp - -**OpenJDK** - -For Linux and BSD, see https://openjdk.java.net/install/ - -For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk - -Get the SQream DB JDBC driver -------------------------------- - -SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page `_. - -Download and extract the JAR file from the zip archive. - -Install SQL Workbench ------------------------ - -#. Download the latest stable release from https://www.sql-workbench.eu/downloads.html . The **Generic package for all systems** is recommended. - -#. Extract the downloaded ZIP archive into a directory of your choice. - -#. Start SQL workbench. If you are using 64 bit windows, run ``SQLWorkbench64.exe`` instead of ``SQLWOrkbench.exe``. - -Setting up the SQream DB JDBC driver profile ---------------------------------------------- - -#. Define a connection profile - :menuselection:`&File --> &Connect window (Alt+C)` - - .. image:: /_static/images/sql_workbench_connect_window1.png - -#. Open the drivers management window - :menuselection:`&Manage Drivers` - - .. image:: /_static/images/sql_workbench_manage_drivers.png - - - -#. Create the SQream DB driver profile - - .. image:: /_static/images/sql_workbench_create_driver.png - - #. Click on the Add new driver button ("New" icon) - - #. Name the driver as you see fit. We recommend calling it SQream DB , where is the version you have installed. - - #. - Add the JDBC drivers from the location where you extracted the SQream DB JDBC JAR. - - If you used the SQream installer, the file will be in ``C:\Program Files\SQream Technologies\JDBC Driver\`` - - #. Click the magnifying glass button to detect the classname automatically. Other details are purely optional - - #. Click OK to save and return to "new connection screen" - - -.. _new_connection_profile: - -Create a new connection profile for your cluster -===================================================== - - .. image:: /_static/images/sql_workbench_connection_profile.png - -#. Create new connection by clicking the New icon (top left) - -#. Give your connection a descriptive name - -#. Select the SQream Driver that was created in the previous screen - -#. Type in your connection string. To find out more about your connection string (URL), see the :ref:`Connection string documentation `. - -#. Text the connection details - -#. Click OK to save the connection profile and connect to SQream DB - -Suggested optional configuration -================================== - -If you installed SQL Workbench manually, you can set a customization to help SQL Workbench show information correctly in the DB Explorer panel. - -#. Locate your workbench.settings file - On Windows, typically: ``C:\Users\\.sqlworkbench\workbench.settings`` - On Linux, ``$HOME/.sqlworkbench`` - -#. Add the following line at the end of the file: - - .. code-block:: text - - workbench.db.sqreamdb.schema.retrieve.change.catalog=true - -#. Save the file and restart SQL Workbench diff --git a/third_party_tools/client_platforms/tableau.rst b/third_party_tools/client_platforms/tableau.rst deleted file mode 100644 index 666b2f198..000000000 --- a/third_party_tools/client_platforms/tableau.rst +++ /dev/null @@ -1,453 +0,0 @@ -.. _connect_to_tableau: - -************************* -Connecting to SQream Using Tableau -************************* - -Overview -===================== -SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. - -The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. - -For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. - -The Connecting to SQream Using Tableau page describes the following: - -.. contents:: - :local: - -Installing the JDBC Driver and Tableau Connector Plugin -------------------- -This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. - -**To connect to SQream using Tableau:** - -#. Install the Tableau Desktop application. - - For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. - - :: - -#. Do one of the following: - - * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. - * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. - -.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. - -.. _tableau_windows_installer: - -Installing the JDBC Driver Using the Windows Installer -~~~~~~~~~~~~~~~~~~ -If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. - -**To install Tableau using the Windows installer**: - -#. Close Tableau Desktop. - - :: - -#. Download the most current version of the `SQream JDBC driver `_. - - :: - -#. Do the following: - - #. Start the installer. - #. Verify that the **Tableau Desktop connector** item is selected. - #. Follow the installation steps. - - :: - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. - -.. _tableau_jdbc_installer: - -Installing the JDBC Driver Manually -~~~~~~~~~~~~~ -If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. - -**To install the JDBC driver manually:** - -1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. - - :: - -#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - - * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* - * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - -.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. - -Note the following when installing the JDBC driver: - -* You must have read permissions on the .jar file. -* Tableau requires a JDBC 4.0 or later driver. -* Tableau requires a Type 4 JDBC driver. -* The latest 64-bit version of Java 8 is installed. - -3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - - * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* - * **Tableau Desktop on Windows:** *~/My Tableau Repository/Connectors* - - :: - -4. *Optional* - If you are using the Tableau Server, do the following: - - 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. - - This directory needs to exist on all Tableau servers. - - :: - - 2. Copy the SQreamDB.taco file into the new directory. - - :: - - 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: - - .. code-block:: console - - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors - - If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: - - .. code-block:: console - - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys - - 4. To apply the pending configuration changes, run the following command: - - .. code-block:: console - - $ tsm pending-changes apply - - .. warning:: This restarts the server. - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. - -.. _tableau_connect_to_sqream: - - -Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier --------------- - - -This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: - -.. contents:: - :local: - -.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. - -Automatically Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: - -.. image:: /_static/images/odbc_windows_installer_tableau.png - -SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. - -For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. - -If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. - -.. _manually_reconfigure_odbc_driver: - -Manually Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. - -**To manually reconfigure the ODBC driver after initial installation:** - -1. Do one of the following: - - 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. - - :: - - 2. Copy the text below into a text editor: - - .. literalinclude:: odbc-sqream.tdc - :language: xml - :caption: SQream ODBC TDC File - :emphasize-lines: 2 - -#. Check which version of Tableau you are using. - - :: - -#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. - - For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. - - :: - -#. Do one of the following: - - * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. - - :: - - * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. - -Configuring the ODBC Connection -~~~~~~~~~~~~ -The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. - -**To configure the ODBC connection:** - -1. Create an ODBC DSN. - - :: - -#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. - - :: - -#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. - - During installation, the installer created a sample user DSN named **SQreamDB**. - - :: - -#. *Optional* - Do one or both of the following: - - * Modify the DSN name. - - :: - - * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. - -.. image:: /_static/images/odbc_windows_dsns.png - - -5. Click **Finish**. - - :: - -6. Enter your connection parameters. - - The following table describes the connection parameters: - - .. list-table:: - :widths: 15 38 38 - :header-rows: 1 - - * - Item - - Description - - Example - * - Data Source Name - - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. - - - * - Description - - The description of your DSN. This field is optional. - - - * - User - - The username of a role to use for establishing the connection. - - ``rhendricks`` - * - Password - - The password of the selected role. - - ``Tr0ub4dor`` - * - Database - - The database name to connect to. For example, ``master`` - - ``master`` - * - Service - - The :ref:`service queue` to use. - - For example, ``etl``. For the default service ``sqream``, leave blank. - * - Server - - The hostname of the SQream worker. - - ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - The TCP port of the SQream worker. - - ``5000`` or ``3108`` - * - User Server Picker - - Uses the load balancer when establishing a connection. Use only if exists, and check port. - - - * - SSL - - Uses SSL when establishing a connection. - - - * - Logging Options - - Lets you modify your logging options when tracking the ODBC connection for connection issues. - - - -.. tip:: Test the connection by clicking **Test** before saving your DSN. - -7. Save the DSN by clicking **OK.** - -Connecting Tableau to SQream -~~~~~~~~~~~~ -**To connect Tableau to SQream:** - -1. Start Tableau Desktop. - - :: - -#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. - - The **Other Databases (ODBC)** window is displayed. - - :: - -#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. - - Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. - -#. Provide your username and password and click **OK**. - -.. _tableau_connect_to_sqream_db: - - -Connecting to SQream ---------------------- -After installing the JDBC driver you can connect to SQream. - -**To connect to SQream:** - -#. Start Tableau Desktop. - - :: - -#. In the **Connect** menu, in the **To a Server** sub-menu, click **More...**. - - More connection options are displayed. - - :: - -#. Select **SQream DB by SQream Technologies**. - - The **New Connection** dialog box is displayed. - - :: - -#. In the New Connection dialog box, fill in the fields and click **Sign In**. - - The following table describes the fields: - - .. list-table:: - :widths: 15 38 38 - :header-rows: 1 - - * - Item - - Description - - Example - * - Server - - Defines the server of the SQream worker. - - ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - Defines the TCP port of the SQream worker. - - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL. - * - Database - - Defines the database to establish a connection with. - - ``master`` - * - Cluster - - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection. - - - * - Username - - Specifies the username of a role to use when connecting. - - ``rhendricks`` - * - Password - - Specifies the password of the selected role. - - ``Tr0ub4dor&3`` - * - Require SSL (recommended) - - Sets SSL as a requirement for establishing this connection. - - - -The connection is established and the data source page is displayed. - -.. tip:: - Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. - -.. _set_up_sqream_tables_as_data_sources: - -Setting Up SQream Tables as Data Sources ----------------- -After connecting to SQream you must set up the SQream tables as data sources. - -**To set up SQream tables as data sources:** - -1. From the **Table** menu, select the desired database and schema. - - SQream's default schema is **public**. - - :: - -#. Drag the desired tables into the main area (labeled **Drag tables here**). - - This area is also used for specifying joins and data source filters. - - :: - -#. Open a new sheet to analyze data. - -.. tip:: - For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. - -Tableau Best Practices and Troubleshooting ---------------- -This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: - -.. contents:: - :local: - -Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ -When using Tableau, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. - - :: - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. - -Using Tableau's Table Query Syntax -~~~~~~~~~~~~~~~~~~~ -Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. - -Creating a Separate Service for Tableau -~~~~~~~~~~~~~~~~~~~ -SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. - -Troubleshooting Workbook Performance Before Deploying to the Tableau Server -~~~~~~~~~~~~~~~~~~~ -Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. - -Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. - -Troubleshooting Error Codes -~~~~~~~~~~~~~~~~~~~ -Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: - -.. code-block:: console - - Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect - -**To troubleshoot error codes:** - -If Tableau cannot locate the SQream JDBC driver, do the following: - - 1. Verify that the JDBC driver is located in the correct directory: - - * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* - * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - - 2. Find the file path for the JDBC driver and add it to the Java classpath: - - * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` - - :: - - * **For Windows** - add an environment variable for the classpath: - - .. image:: /_static/images/third_party_connectors/tableau/envrionment_variable_for_classpath.png - -If you experience issues after restarting Tableau, see the `SQream support portal `_. diff --git a/third_party_tools/client_platforms/talend.rst b/third_party_tools/client_platforms/talend.rst deleted file mode 100644 index 6e34a7168..000000000 --- a/third_party_tools/client_platforms/talend.rst +++ /dev/null @@ -1,177 +0,0 @@ -.. _talend: - -************************* -Connecting to SQream Using Talend -************************* -.. _top: - -Overview -================= - -This page describes how to use Talend to interact with a SQream DB cluster. The Talend connector is used for reading data from a SQream DB cluster and loading data into SQream DB. - -In addition, this page provides a viability report on Talend's comptability with SQream DB for stakeholders. - -It includes the following: - -* :ref:`A Quick Start guide ` -* :ref:`Information about supported SQream drivers ` -* :ref:`Supported data sources ` and :ref:`tool and operating system versions ` -* :ref:`A description of known issues ` -* :ref:`Related links ` - -About Talend -================= -Talend is an open-source data integration platform. It provides various software and services for Big Data integration and management, enterprise application integration, data quality and cloud storage. - -For more information about Talend, see `Talend `_. - -.. _quickstart_guide: - -Quick Start Guide -======================= - -Creating a New Metadata JDBC DB Connection -------------- -**To create a new metadata JDBC DB connection:** - -1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. - -:: - -2. Select **Create connection**. - -3. In the **Name** field, type a name. - -The name cannot contain spaces. - -4. In the **Purpose** field, type a purpose and click **Next**. You cannot go to the next step until you define both a Name and a Purpose. - -:: - -5. In the **DB Type** field, select **JDBC**. - -:: - -6. In the **JDBC URL** field, type the relevant connection string. - - For connection string examples, see `Connection Strings `_. - -7. In the **Drivers** field, click the **Add** button. - - The **"newLine** entry is added. - -8. One the **"newLine** entry, click the ellipsis. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_8.png - -The **Module** window is displayed. - -9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. - -:: - -10. Click the ellipsis. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.5.png - -Your hard drive is displayed. - -11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.4.0.jar**)and click **Open**. - -:: - -12. Click **Detect the module install status**. - -:: - -13. Click **OK**. - -The JDBC that you selected is displayed in the **Driver** field. - -14. Click **Select class name**. - -:: - -15. Click **Test connection**. - -If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: - -After creating a new metadata JDBC DB connection, you can do the following: - - * Use your new metadata connection. - * Drag it to the **job** screen. - * Build Talend components. - -For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. - -:ref:`Back to top ` - -.. _supported_sqream_drivers: - -Supported SQream Drivers -================ - -The following list shows the supported SQream drivers and versions: - -* **JDBC** - Version 4.3.3 and higher. -* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. - -:ref:`Back to top ` - -.. _supported_data_sources: - -Supported Data Sources -============================ -Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. - -* **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. - -* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. - -:ref:`Back to top ` - -.. _supported_tools_os_sys_versions: - -Supported Tool and Operating System Versions -====================== -Talend was tested using the following: - -* Talend version 7.4.1M6 -* Windows 10 -* SQream version 2021.1 -* JDBC version - -:ref:`Back to top ` - -.. _known_issues: - -Known Issues -=========================== -The the list below describes the following known issues as of 6/1/2021: - -* Schemas not displayed for tables with identical names. - -:ref:`Back to top ` - -.. _related_links: - -Related Links -=============== -The following is a list of links relevant to the Talend connector: - -* `Talend Home page `_ -* `Talend Community page `_ -* `Talend BugTracker `_ - -Download Links -================== -The following is a list of download links relevant to the Talend connector: - -* `Talend Open Studio for Big Data `_ -* `Latest version of SQream JDBC `_ - -:ref:`Back to top ` - -.. contents:: In this topic: - :local: \ No newline at end of file diff --git a/third_party_tools/client_platforms/test.php b/third_party_tools/client_platforms/test.php deleted file mode 100644 index fef04e699..000000000 --- a/third_party_tools/client_platforms/test.php +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/third_party_tools/client_platforms/tibco_spotfire.rst b/third_party_tools/client_platforms/tibco_spotfire.rst deleted file mode 100644 index b0a707c51..000000000 --- a/third_party_tools/client_platforms/tibco_spotfire.rst +++ /dev/null @@ -1,387 +0,0 @@ -.. _tibco_spotfire: - - -************************* -Connecting to SQream Using TIBCO Spotfire -************************* -Overview -========= -The **TIBCO Spotfire** software is an analytics solution that enables visualizing and exploring data through dashboards and advanced analytics. - -This document is a Quick Start Guide that describes the following: - -.. contents:: - :local: - :depth: 1 - -Establishing a Connection between TIBCO Spotfire and SQream ------------------ -TIBCO Spotfire supports the following versions: - -* **JDBC driver** - Version 4.5.3 -* **ODBC driver** - Version 4.1.1 - -SQream supports TIBCO Spotfire version 7.12.0. - -The **Establishing a JDBC Connection between TIBCO Spotfire and SQream** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Creating a JDBC Connection -~~~~~~~~~~~ -For TIBCO Spotfire to recognize SQream, you must add the correct JDBC jar file to Spotfire's loaded binary folder. The following is an example of a path to the Spotfire loaded binaries folder: ``C:\tibco\tss\7.12.0\tomcat\bin``. - -For the complete TIBCO Spotfire documentation, see `TIBCO Spotfire® JDBC Data Access Connectivity Details `_. - -Creating an ODBC Connection -~~~~~~~~~~~ -**To create an ODBC connection** - -1. Install and configure ODBC on Windows. - - For more information, see :ref:`Install and Configure ODBC on Windows`. - -#. Launch the TIBCO Spotfire application. - - :: - -#. From the **File** menu click **Add Data Tables**. - - The **Add Database Tables** window is displayed. - -#. Click **Add** and select **Database**. - - The **Open Database** window is displayed. - -#. In the **Data source type** area, select **ODBC SQream** (Odbc Data Provider) and click **Configure**. - - The **Configure Data Source and Connection** window is displayed. - -#. Select **System or user data source** and from the drop-down menu select the DSN of your data source (SQreamDB). - - :: - -#. Provide your database username and password and click **OK**. - - :: - -#. In the **Open Database** window, click **OK**. - - The **Specify Tables and Columns** window is displayed. - -#. In the **Specify Tables and Columns** window, select the checkboxes corresponding to the tables and columns that you want to include in your SQL statement. - - :: - -#. In the **Data source name** field, set your data source name and click **OK**. - - Your data source is displayed in the **Data tables** area. - -#. In the **Add Data Tables** dialog, click **OK** to load the data from your ODBC data source into Spotfire. - -.. note:: Verify that you have checked the SQL statement. - -Creating the SQream Data Source Template -~~~~~~~~~~~ -After creating a connection, you can create your SQream data source template. - -**To create your SQream data source template:** - -1. Log in to the TIBCO Spotfire Server Configuration Tool. - - :: - -#. From the **Configuration** tab, in the **Configuration Start** menu, click **Data Source Templates**. - - The **Data Source Templates** list is displayed. - -#. From the Data Source Templates list do one of the following: - - * Override an existing template: - - 1. In the template text field, select an existing template. - - :: - - 2. Copy and paste your data source template text. - - :: - - * Create a new template: - - 1. Click **New**. - - The **Add Data Source Template** window is displayed. - - .. _creating_sqream_data_source_template: - - 2. In the **Name** field, define your template name. - - :: - - 3. In the **Data Source Template** text field, copy and paste your data source template text. - - The following is an example of a data source template: - - .. code-block:: console - - - SQream - com.sqream.jdbc.SQDriver - jdbc:Sqream://<host>:<port>/database;user=sqream;password=sqream;cluster=true - true - true - false - TABLE,EXTERNAL_TABLE - - - Bool - Integer - - - VARCHAR(2048) - String - - - INT - Integer - - - BIGINT - LongInteger - - - Real - Real - - - Decimal - Float - - - Numeric - Float - - - Date - DATE - - - DateTime - DateTime - - - - - -4. Click **Save configuration**. - - :: - -5. Close and restart your Spotfire server. - -Creating a Data Source -~~~~~~~~~~~ -After creating the SQream data source template, you can create a data source. - -**To create a data source:** - -1. Launch the TIBCO Spotfire application. - - :: - -#. From the **Tools** menu, select **Information Designer**. - - The **Information Designer** window is displayed. - - :: - -#. From the **New** menu, click **Data Source**. - - The **Data Source** tab is displayed. - - :: - -#. Provide the following information: - - * **Name** - define a unique name. - - :: - - * **Type** - use the same type template name you used while configuring your template. See **Step 3** in :ref:`Creating the SQream Data Source Template`. - - :: - - * **Connection URL** - use the standard JDBC connection string, ``:/database``. - - :: - - * **No. of connections** - define a number between **1** and **100**. SQream recommends setting your number of connections to **100**. - - :: - - * **Username and Password** - define your SQream username and password. - -Creating an Information Link -~~~~~~~~~~~ -After creating a data source, you can create an information link. - -**To create an information link**: - -1. From the **Tools** menu, select **Information Designer**. - - The **Information Designer** window is displayed. - - :: - -#. From the **New** menu, click **Information Link**. - - The **Information link** tab is displayed. - -#. From the **Elements** tab, select a column type and click **Add**. - - The column type is added to the **Elements** region as a filter. - - Note the following: - - * You can select procedures from the Elements region. - - :: - - * You can remove an element by selecting an element and clicking **Remove**. - - .. tip:: If the Elements menu is not displayed, you can display it by clicking the **Elements** tab. You can simultaneously select multiple elements by pressing **Ctrl** and making additional selections, and select a range of elements by holding **Shift** and clicking two elements. - -#. If the elements you select originate from more than one data source table, specify a **Join path**. - -5. *Optional* - In the **Description** region, type the description of the information link. - - :: - -#. *Optional* - To filter your data, expand the **Filters** section and do the following: - - 1. From the **Information Link** region, select the element you added in Step 3 above. - - :: - - 2. Click **Add**. - - The **Add Column** window is displayed. - - 3. From the drop-down list, select a column to add a hard filter to and click **OK**. - - The selected column is added to the Filters list. - - 4. Repeat steps 2 and 3 to add filters to additional columns. - - :: - - 5. For each column, from the **Filter Type** drop-down list, select **range** or **values**. - - .. note:: Filtering by range means entering the upper and lower limits of the desired range. Filtering by values means entering the exact values that you want to include in the returned data, separated by semicolon. - - 6. In the **Values** field type the desired values separated with semicolons, or set the upper and lower limits in the **Min Value** and **Max Value** fields. Alternatively, you can type ``?param_name`` in the Values field to use a parameter as the filter for the selected column, where ``param_name`` is the name used to identify the parameter. - - .. note:: Because limits are inclusive, setting the lower limit to **1000** includes the value **1000** in the data table. - - .. note:: When setting upper and lower limits on **String** type columns, ``A`` precedes ``AA``, and a lone letter precedes words beginning with that latter. For example, ``S** precedes **Smith**, indicating that the name ``Smith`` will not be present when you select names from ``D`` to ``S``. The order of characters is standard ASCII. - - For more information on adding filters, see `Adding Hard Filters `_. - -7. *Optional* - To add runtime filtering prompts, expand the **Prompts** section and do the following: - - 1. Click **Add**. - - The **Add Column** window is displayed. - - #. From the **Select column** list, select a column to add a prompt to and click **OK**. - - The selected column is added to the Prompts list. - - #. Repeat **Step 1** to add prompts to additional columns. - - :: - - #. Do the following for each column: - - * Make a selection from the **Prompt Type** drop-down list. - * Select or clear **Mandatory**. - * *Optional* - Set your **Max Selections**. - - For more information on adding prompts, see `Adding Prompts `_. - -8. *Optional* - Expand the **Conditioning** section and specify one of the following conditions: - - * None - * Distinct - * Pivot - - Note that you can edit the Pivot conditioning by selecting **Pivot** and clicking **Edit**. - -9. *Optional* - Expand the **Parameters** section and define your parameters. - - :: - -10. *Optional* - Expand the **Properties** section and define your properties. - - :: - -11. *Optional* - Expand the **Caching** section and enable or disable whether your information link can be cached. - - :: - -12. Click **Save**. - - The **Save As** window is displayed. - -13. In the tree, select where you want to save the information link. - - :: - -14. In the **Name** field, type a name and description for the information link. - - :: - - -15. Click **Save**. - - The new information link is added to the library and can be accessed by other users. - -.. tip:: You can test the information link directly by clicking **Open Data**. You can also view and edit the SQL belonging to the information link by clicking **SQL**. - -For more information on the Information Link attributes, see `Information Link Tab `_. - -Troubleshooting -------------- -The **Troubleshooting** section describes the following scenarios: - -.. contents:: - :local: - :depth: 1 - -The JDBC Driver does not Support Boolean, Decimal, or Numeric Types -~~~~~~~~~~~ -When attempting to load data, the the Boolean, Decimal, or Numeric column types are not supported and generate the following error: - -.. code-block:: console - - Failed to execute query: Unsupported JDBC data type in query result: Bool (HRESULT: 80131500) - -The error above is resolved by casting the columns as follows: - -* ``Bool`` columns to ``INT``. -* ``Decimal`` and ``Numeric`` columns to ``REAL``. - -For more information, see the following: - -* **Resolving this error** - `Details on Change Data Types `_. - -* **Supported data types** - :ref:`Data Types`. - -Information Services do not Support Live Queries -~~~~~~~~~~~ -TIBCO Spotfire data connectors support live queries, but no APIs currently exist for creating custom data connectors. This is resolved by creating a customized SQream adapter using TIBCO's **Data Virtualization (TDV)** or the **Spotfire Advanced Services (ADS)**. These can be used from the built-in TDV connector to enable live queries. - -This resolution applies to JDBC and ODBC drivers. diff --git a/third_party_tools/index.rst b/third_party_tools/index.rst index 1052f9f27..ee581e337 100644 --- a/third_party_tools/index.rst +++ b/third_party_tools/index.rst @@ -12,7 +12,6 @@ This section provides information about the following third party tools: :glob: :titlesonly: - client_platforms/index client_drivers/index If you need a tool that SQream does not support, contact SQream Support or your SQream account manager for more information. \ No newline at end of file diff --git a/troubleshooting/index.rst b/troubleshooting/index.rst index efbcdd412..985008e09 100644 --- a/troubleshooting/index.rst +++ b/troubleshooting/index.rst @@ -15,11 +15,6 @@ The **Troubleshooting** page describes solutions to the following issues: examining_logs identifying_configuration_issues lock_related_issues - sas_viya_related_issues - tableau_related_issues - solving_code_126_odbc_errors log_related_issues - node_js_related_issues core_dumping_related_issues - sqream_sql_installation_related_issues information_for_support \ No newline at end of file diff --git a/troubleshooting/node_js_related_issues.rst b/troubleshooting/node_js_related_issues.rst deleted file mode 100644 index b3b95b2ed..000000000 --- a/troubleshooting/node_js_related_issues.rst +++ /dev/null @@ -1,54 +0,0 @@ -.. _node_js_related_issues: - -*********************** -Node.js Related Issues -*********************** -The **Node.js Related Issues** page describes how to resolve the following common issues: - -.. toctree:: - :maxdepth: 2 - :glob: - :titlesonly: - -Preventing Heap Out of Memory Errors --------------------------------------------- - -Some workloads may cause Node.JS to fail with the error: - -.. code-block:: none - - FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory - -To prevent this error, modify the heap size configuration by setting the ``--max-old-space-size`` run flag. - -For example, set the space size to 2GB: - -.. code-block:: console - - $ node --max-old-space-size=2048 my-application.js - -Providing Support for BIGINT Data Type ------------------------- - -The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. - -The error that appears is: -.. code-block:: none - - TypeError: Do not know how to serialize a BigInt - -This is because JSON specification do not support BIGINT values, even when supported by Javascript engines. - -To resolve this issue, objects with BIGINT values should be converted to string before serializing, and converted back after deserializing. - -For example: - -.. code-block:: javascript - - const rows = [{test: 1n}] - const json = JSON.stringify(rows, , (key, value) => - typeof value === 'bigint' - ? value.toString() - : value // return everything else unchanged - )); - console.log(json); // [{"test": "1"}] \ No newline at end of file diff --git a/troubleshooting/sas_viya_related_issues.rst b/troubleshooting/sas_viya_related_issues.rst deleted file mode 100644 index 6661dec95..000000000 --- a/troubleshooting/sas_viya_related_issues.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _sas_viya_related_issues: - -*********************** -SAS Viya Related Issues -*********************** - -This section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: - -.. contents:: - :local: - -Inserting Only Required Data ------- -When using Tableau, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. - - :: - - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. - - -Creating a Separate Service for SAS Viya ------- -SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. - -Locating the SQream JDBC Driver ------- -In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: - -.. code-block:: text - - java.lang.ClassNotFoundException: com.sqream.jdbc.SQDriver - -**To locate the SQream JDBC driver:** - -1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. - - :: - - -2. Verify that the classpath in your SAS program is correct, and that SAS Viya can access the file that it references. - - :: - - -3. Restart SAS Viya. - -For more troubleshooting assistance, see the `SQream Support Portal `_. - - -Supporting TEXT ------- -In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. diff --git a/troubleshooting/solving_code_126_odbc_errors.rst b/troubleshooting/solving_code_126_odbc_errors.rst deleted file mode 100644 index 2e652b113..000000000 --- a/troubleshooting/solving_code_126_odbc_errors.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _solving_code_126_odbc_errors: - -*********************** -Solving "Code 126" ODBC Errors -*********************** -After installing the ODBC driver, you may experience the following error: - -.. code-block:: none - - The setup routines for the SQreamDriver64 ODBC driver could not be loaded due to system error - code 126: The specified module could not be found. - (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) - -This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. diff --git a/troubleshooting/sqream_sql_installation_related_issues.rst b/troubleshooting/sqream_sql_installation_related_issues.rst deleted file mode 100644 index 8225a2f18..000000000 --- a/troubleshooting/sqream_sql_installation_related_issues.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. _sqream_sql_installation_related_issues: - -*********************** -SQream SQL Installation Related Issues -*********************** - -The **SQream SQL Installation Related Issues** page describes how to resolve SQream SQL installation related issues. - -Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. - -Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. - -* Ubuntu: - - #. Install ``libtinfo``: - - ``$ sudo apt-get install -y libtinfo`` - #. Depending on your Ubuntu version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/lib/x86_64-linux-gnu/libtinfo.so.6.2``: - - ``$ sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6.2 /lib/x86_64-linux-gnu/libtinfo.so.5`` - -* CentOS / RHEL: - - #. Install ``ncurses``: - - ``$ sudo yum install -y ncurses-libs`` - #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: - - ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` \ No newline at end of file diff --git a/troubleshooting/tableau_related_issues.rst b/troubleshooting/tableau_related_issues.rst deleted file mode 100644 index 99b4a04dd..000000000 --- a/troubleshooting/tableau_related_issues.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _tableau_related_issues: - -*********************** -Tableau Related Issues -*********************** -This section describes the following best practices and troubleshooting procedures when connecting to Tableau: - -.. contents:: - :local: - -Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ -When using Tableau, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. - - :: - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. - -Using Tableau's Table Query Syntax -~~~~~~~~~~~~~~~~~~~ -Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. - -Creating a Separate Service for Tableau -~~~~~~~~~~~~~~~~~~~ -SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. - -Error Saving Large Quantities of Data as Files -~~~~~~~~~~~~~~~~~~~ -An **FAB9A2C5** error can when saving large quantities of data as files. If you receive this error when writing a connection string, add the ``fetchSize`` parameter to ``1``, as shown below: - -.. code-block:: text - - jdbc:Sqream:///;user=;password=sqream;[; fetchSize=1...] - -For more information on troubleshooting error **FAB9A2C5**, see the `Tableau Knowledge Base `_. - -Troubleshooting Workbook Performance Before Deploying to the Tableau Server -~~~~~~~~~~~~~~~~~~~ -Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. - -Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. - -Troubleshooting Error Codes -~~~~~~~~~~~~~~~~~~~ -Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: - -.. code-block:: console - - Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect - -**To troubleshoot error codes:** - -If Tableau cannot locate the SQream JDBC driver, do the following: - - 1. Verify that the JDBC driver is located in the correct directory: - - * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* - * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - - 2. Find the file path for the JDBC driver and add it to the Java classpath: - - * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` - - :: - - * **For Windows** - add an environment variable for the classpath: - - - -If you experience issues after restarting Tableau, see the `SQream support portal `_. From 16da90b13dbdcf6e9eaeeacdbd1ba4aa9e290435 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 29 Mar 2022 17:05:38 +0300 Subject: [PATCH 0032/1892] Update sqream_studio_installation.rst --- installation_guides/sqream_studio_installation.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 8d6c16546..8646a35ad 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -9,11 +9,7 @@ The **Installing SQream Studio** page incudes the following installation guides: :maxdepth: 1 :glob: - installing_studio_on_stand_alone_server installing_prometheus_exporters installing_prometheus_using_binary_packages installing_dashboard_data_collector - - - - + installing_studio_on_stand_alone_server \ No newline at end of file From 4e1393f438ac26520f98726880f4c54bf28dcbf7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 29 Mar 2022 18:29:02 +0300 Subject: [PATCH 0033/1892] Replaced VARCHAR with TEXT Replaced *most* instances of VARCHAR with TEXT. I didn't replace all of them because I had some open questions for Shachar (about 20). I am going to merge this now into branch 2020-1 to test if it worked, and will merge it again after updating it in light of Shachar's comments. I will then merge it on the remaining branches. --- data_ingestion/csv.rst | 10 +++---- data_ingestion/inserting_data.rst | 2 +- data_ingestion/orc.rst | 16 ++++++------ data_ingestion/parquet.rst | 14 +++++----- data_type_guides/sql_data_types_string.rst | 2 +- feature_guides/compression.rst | 10 +++---- ...flexible_data_clustering_data_examples.rst | 4 +-- .../performing_basic_sqream_operations.rst | 1 + getting_started/querying_data.rst | 10 +++---- operational_guides/external_tables.rst | 10 +++---- operational_guides/logging.rst | 4 +-- .../optimization_best_practices.rst | 26 ++----------------- operational_guides/s3.rst | 10 +++---- reference/cli/sqream_sql.rst | 4 +-- .../sql_functions/aggregate_functions/avg.rst | 10 +++---- .../aggregate_functions/corr.rst | 10 +++---- .../aggregate_functions/count.rst | 10 +++---- .../aggregate_functions/covar_pop.rst | 10 +++---- .../aggregate_functions/covar_samp.rst | 10 +++---- .../sql_functions/aggregate_functions/max.rst | 10 +++---- .../sql_functions/aggregate_functions/min.rst | 10 +++---- .../aggregate_functions/stddev_pop.rst | 10 +++---- .../aggregate_functions/stddev_samp.rst | 10 +++---- .../sql_functions/aggregate_functions/sum.rst | 10 +++---- .../aggregate_functions/var_pop.rst | 10 +++---- .../aggregate_functions/var_samp.rst | 10 +++---- .../date_and_time/dateadd.rst | 2 +- .../date_and_time/datediff.rst | 2 +- .../date_and_time/datepart.rst | 2 +- .../scalar_functions/date_and_time/trunc.rst | 2 +- .../scalar_functions/numeric/crc64.rst | 5 ++-- .../scalar_functions/string/concat.rst | 17 ++++++------ .../scalar_functions/string/len.rst | 2 +- .../scalar_functions/string/like.rst | 10 +++---- .../scalar_functions/string/regexp_count.rst | 10 +++---- .../scalar_functions/string/regexp_instr.rst | 10 +++---- .../scalar_functions/string/regexp_substr.rst | 10 +++---- .../scalar_functions/string/rlike.rst | 10 +++---- .../scalar_functions/string/substring.rst | 10 +++---- .../window_functions/first_value.rst | 2 +- .../sql_functions/window_functions/lag.rst | 10 +++---- .../sql_functions/window_functions/lead.rst | 10 +++---- .../window_functions/nth_value.rst | 4 +-- .../sql_functions/window_functions/rank.rst | 10 +++---- .../window_functions/row_number.rst | 10 +++---- .../ddl_commands/create_external_table.rst | 6 ++--- .../ddl_commands/create_foreign_table.rst | 6 ++--- .../sql_statements/dml_commands/select.rst | 10 +++---- .../utility_commands/execute_saved_query.rst | 15 +++++------ .../utility_commands/get_ddl.rst | 4 +-- .../utility_commands/save_query.rst | 13 +++++----- reference/sql/sql_syntax/literals.rst | 1 - reference/sql/sql_syntax/subqueries.rst | 10 +++---- reference/sql/sql_syntax/window_functions.rst | 10 +++---- troubleshooting/log_related_issues.rst | 4 +-- 55 files changed, 217 insertions(+), 243 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index f44c3c9e9..47c6d94a1 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -83,14 +83,14 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 660cd61bd..86bd08103 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -98,7 +98,7 @@ Unsupported Data Types SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. -These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``VARCHAR``. +These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``TEXT``. Handing Extended Errors ---------------------------- diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index d199e958e..de10c5ce4 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -186,14 +186,14 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA CREATE FOREIGN TABLE ext_nba ( - Name VARCHAR(40), - Team VARCHAR(40), + Name TEXT(40), + Team TEXT(40), Number BIGINT, - Position VARCHAR(2), + Position TEXT(2), Age BIGINT, - Height VARCHAR(4), + Height TEXT(4), Weight BIGINT, - College VARCHAR(40), + College TEXT(40), Salary FLOAT ) WRAPPER orc_fdw @@ -288,7 +288,7 @@ Loading a table from a directory of ORC files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email VARCHAR(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( @@ -303,7 +303,7 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email VARCHAR(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', @@ -312,4 +312,4 @@ Loading a table from a bucket of files on S3 ) ; - CREATE TABLE users AS SELECT * FROM ext_users; + CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 800c3122a..4579deb82 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -167,14 +167,14 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T CREATE FOREIGN TABLE ext_nba ( - Name VARCHAR(40), - Team VARCHAR(40), + Name TEXT(40), + Team TEXT(40), Number BIGINT, - Position VARCHAR(2), + Position TEXT(2), Age BIGINT, - Height VARCHAR(4), + Height TEXT(4), Weight BIGINT, - College VARCHAR(40), + College TEXT(40), Salary FLOAT ) WRAPPER parquet_fdw @@ -269,7 +269,7 @@ Loading a table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER parquet_fdw OPTIONS ( @@ -284,7 +284,7 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER parquet_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index beb970b8d..0d977b6d2 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -3,7 +3,7 @@ ************************* String ************************* -``TEXT`` and ``VARCHAR`` are types designed for storing text or strings of characters. +``TEXT`` is designed for storing text or strings of characters. SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 710641036..96c051ff4 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -108,7 +108,7 @@ The following two are equivalent: CREATE TABLE t ( x INT, - y VARCHAR(50) + y TEXT(50) ); In this version, the default compression is specified explicitly: @@ -117,7 +117,7 @@ In this version, the default compression is specified explicitly: CREATE TABLE t ( x INT CHECK('CS "default"'), - y VARCHAR(50) CHECK('CS "default"') + y TEXT(50) CHECK('CS "default"') ); Forcing no compression (flat) @@ -130,7 +130,7 @@ in order to reduce CPU or GPU resource utilization at the expense of increased I CREATE TABLE t ( x INT NOT NULL CHECK('CS "flat"'), -- This column won't be compressed - y VARCHAR(50) -- This column will still be compressed automatically + y TEXT(50) -- This column will still be compressed automatically ); @@ -146,8 +146,8 @@ For example: CREATE TABLE t ( id BIGINT NOT NULL CHECK('CS "sequence"'), - y VARCHAR(110) CHECK('CS "lz4"'), -- General purpose text compression - z VARCHAR(80) CHECK('CS "dict"'), -- Low cardinality column + y TEXT(110) CHECK('CS "lz4"'), -- General purpose text compression + z TEXT(80) CHECK('CS "dict"'), -- Low cardinality column ); diff --git a/feature_guides/flexible_data_clustering_data_examples.rst b/feature_guides/flexible_data_clustering_data_examples.rst index 0c720ff04..bf08a111a 100644 --- a/feature_guides/flexible_data_clustering_data_examples.rst +++ b/feature_guides/flexible_data_clustering_data_examples.rst @@ -16,7 +16,7 @@ The following is an example of syntax for creating a clustered table on a table .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name text(30) NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country text(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY country; \ No newline at end of file diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst index 81ea9b05f..1b0f60ba3 100644 --- a/getting_started/performing_basic_sqream_operations.rst +++ b/getting_started/performing_basic_sqream_operations.rst @@ -12,6 +12,7 @@ After installing SQream you can perform the operations described on this page: running_the_sqream_sql_client creating_your_first_table creating_a_database + querying_data listing_tables inserting_rows running_queries diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst index 36bf9e78b..7b6b46aed 100644 --- a/getting_started/querying_data.rst +++ b/getting_started/querying_data.rst @@ -11,14 +11,14 @@ To begin familiarizing yourself with querying data, you can create the following CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/operational_guides/external_tables.rst b/operational_guides/external_tables.rst index 005dc961f..6ee2f67a0 100644 --- a/operational_guides/external_tables.rst +++ b/operational_guides/external_tables.rst @@ -52,14 +52,14 @@ Based on the source file structure, we we :ref:`create an external table create table animals(id int not null, name varchar(30) not null, is_angry bool not null); + farm=> create table animals(id int not null, name text(30) not null, is_angry bool not null); executed time: 0.011940s @@ -303,7 +303,7 @@ Assuming a file containing SQL statements (separated by semicolons): $ cat some_queries.sql CREATE TABLE calm_farm_animals - ( id INT IDENTITY(0, 1), name VARCHAR(30) + ( id INT IDENTITY(0, 1), name TEXT(30) ); INSERT INTO calm_farm_animals (name) diff --git a/reference/sql/sql_functions/aggregate_functions/avg.rst b/reference/sql/sql_functions/aggregate_functions/avg.rst index be0294d46..4768061c8 100644 --- a/reference/sql/sql_functions/aggregate_functions/avg.rst +++ b/reference/sql/sql_functions/aggregate_functions/avg.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/corr.rst b/reference/sql/sql_functions/aggregate_functions/corr.rst index 212ab89d2..5963c835f 100644 --- a/reference/sql/sql_functions/aggregate_functions/corr.rst +++ b/reference/sql/sql_functions/aggregate_functions/corr.rst @@ -51,14 +51,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index 803e529c0..133d658f4 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -67,14 +67,14 @@ The examples in this section are based on a table named ``nba``, structured as f CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst index c0d7cd35d..24300b5d7 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_pop.rst @@ -55,14 +55,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst index 29d7b7493..2c8451023 100644 --- a/reference/sql/sql_functions/aggregate_functions/covar_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/covar_samp.rst @@ -56,14 +56,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/max.rst b/reference/sql/sql_functions/aggregate_functions/max.rst index 529e2230d..994a3aaca 100644 --- a/reference/sql/sql_functions/aggregate_functions/max.rst +++ b/reference/sql/sql_functions/aggregate_functions/max.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/min.rst b/reference/sql/sql_functions/aggregate_functions/min.rst index d488d87fc..dd4d39177 100644 --- a/reference/sql/sql_functions/aggregate_functions/min.rst +++ b/reference/sql/sql_functions/aggregate_functions/min.rst @@ -53,14 +53,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst index 5a8a7e677..8687c0e76 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst index 0328e2241..81c7a1f51 100644 --- a/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/stddev_samp.rst @@ -62,14 +62,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/sum.rst b/reference/sql/sql_functions/aggregate_functions/sum.rst index e8f648894..51d7f6d97 100644 --- a/reference/sql/sql_functions/aggregate_functions/sum.rst +++ b/reference/sql/sql_functions/aggregate_functions/sum.rst @@ -65,14 +65,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_pop.rst b/reference/sql/sql_functions/aggregate_functions/var_pop.rst index 4ddf45a1e..de078a3ae 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_pop.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_pop.rst @@ -58,14 +58,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/aggregate_functions/var_samp.rst b/reference/sql/sql_functions/aggregate_functions/var_samp.rst index 6f0c91e63..cc9721225 100644 --- a/reference/sql/sql_functions/aggregate_functions/var_samp.rst +++ b/reference/sql/sql_functions/aggregate_functions/var_samp.rst @@ -63,14 +63,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst index cff5268e6..240b0bf2e 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst @@ -106,7 +106,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index 5c91a88d9..1af8827de 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -100,7 +100,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst index 8a43a1472..a779663b5 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst @@ -109,7 +109,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index d9d791cc3..1e888cfe5 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -104,7 +104,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst index 7dbd6ddf1..105dae47c 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst @@ -25,7 +25,7 @@ Arguments * - Parameter - Description * - ``expr`` - - Text expression (``VARCHAR``, ``TEXT``) + - Text expression (``TEXT``) Returns ============ @@ -54,5 +54,4 @@ Calculate a CRC-64 hash of a string . as t(x); crc64 -------------------- - -9085161068710498500 - + -9085161068710498500 \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index 0409216cd..c612a9bdd 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); @@ -76,7 +76,7 @@ Convert values to string types before concatenation .. code-block:: psql - nba=> SELECT ("Age" :: VARCHAR(2)) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: TEXT(2)) || "Name" FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ---------------- 40Tim Duncan @@ -116,12 +116,11 @@ Add a space and concatenate it first to bypass the space trimming issue .. code-block:: psql - nba=> SELECT ("Age" :: VARCHAR(2) || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; + nba=> SELECT ("Age" :: TEXT(2) || (' ' || "Name")) FROM nba ORDER BY 1 DESC LIMIT 5; ?column? ----------------- 40 Tim Duncan 40 Kevin Garnett 40 Andre Miller 39 Vince Carter - 39 Pablo Prigioni - + 39 Pablo Prigioni \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/len.rst b/reference/sql/sql_functions/scalar_functions/string/len.rst index d3cba24b2..fdd671423 100644 --- a/reference/sql/sql_functions/scalar_functions/string/len.rst +++ b/reference/sql/sql_functions/scalar_functions/string/len.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ($$'Twas brillig, and the slithy toves$$), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/like.rst b/reference/sql/sql_functions/scalar_functions/string/like.rst index 4640ba9be..ce5ca4942 100644 --- a/reference/sql/sql_functions/scalar_functions/string/like.rst +++ b/reference/sql/sql_functions/scalar_functions/string/like.rst @@ -83,14 +83,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst index 5f3bd75a0..26191eccc 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst @@ -99,14 +99,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst index f401fdfff..d72f0af4f 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst @@ -104,14 +104,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index 1730d6ebf..36611424e 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -104,14 +104,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/rlike.rst b/reference/sql/sql_functions/scalar_functions/string/rlike.rst index 324a6e525..3c61cb959 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rlike.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rlike.rst @@ -99,14 +99,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index b07d951fb..6e6359167 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -54,14 +54,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_functions/window_functions/first_value.rst b/reference/sql/sql_functions/window_functions/first_value.rst index 07708872d..25294040c 100644 --- a/reference/sql/sql_functions/window_functions/first_value.rst +++ b/reference/sql/sql_functions/window_functions/first_value.rst @@ -21,4 +21,4 @@ None Returns --------- -Returns the value located in the selected column of the first row of a segment. +Returns the value located in the selected column of the first row of a segment. \ No newline at end of file diff --git a/reference/sql/sql_functions/window_functions/lag.rst b/reference/sql/sql_functions/window_functions/lag.rst index e93be2821..96ea55bed 100644 --- a/reference/sql/sql_functions/window_functions/lag.rst +++ b/reference/sql/sql_functions/window_functions/lag.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/lead.rst b/reference/sql/sql_functions/window_functions/lead.rst index bc311689f..f1c52e1ec 100644 --- a/reference/sql/sql_functions/window_functions/lead.rst +++ b/reference/sql/sql_functions/window_functions/lead.rst @@ -59,14 +59,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/nth_value.rst b/reference/sql/sql_functions/window_functions/nth_value.rst index a2c1dd9a6..75e97a939 100644 --- a/reference/sql/sql_functions/window_functions/nth_value.rst +++ b/reference/sql/sql_functions/window_functions/nth_value.rst @@ -22,8 +22,8 @@ The following example shows the syntax for a table named ``superstore`` used for CREATE TABLE superstore ( - "Section" varchar(40), - "Product_Name" varchar(40), + "Section" text(40), + "Product_Name" text(40), "Sales_In_K" int, ); diff --git a/reference/sql/sql_functions/window_functions/rank.rst b/reference/sql/sql_functions/window_functions/rank.rst index 28856bd04..7699fd399 100644 --- a/reference/sql/sql_functions/window_functions/rank.rst +++ b/reference/sql/sql_functions/window_functions/rank.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_functions/window_functions/row_number.rst b/reference/sql/sql_functions/window_functions/row_number.rst index ea5786aef..cfcc14b7b 100644 --- a/reference/sql/sql_functions/window_functions/row_number.rst +++ b/reference/sql/sql_functions/window_functions/row_number.rst @@ -48,14 +48,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_statements/ddl_commands/create_external_table.rst b/reference/sql/sql_statements/ddl_commands/create_external_table.rst index fc05ca71e..4e2a3d952 100644 --- a/reference/sql/sql_statements/ddl_commands/create_external_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_external_table.rst @@ -113,7 +113,7 @@ A simple table from Tab-delimited file (TSV) .. code-block:: postgres CREATE OR REPLACE EXTERNAL TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) USING FORMAT csv WITH PATH '/home/rhendricks/cool_animals.csv' FIELD DELIMITER '\t'; @@ -125,7 +125,7 @@ A table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) USING FORMAT Parquet WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet'; @@ -135,7 +135,7 @@ A table from a bucket of files on S3 .. code-block:: postgres CREATE EXTERNAL TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) USING FORMAT Parquet WITH PATH 's3://pp-secret-bucket/users/*.parquet' AWS_ID 'our_aws_id' diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index d50e13380..ecc39f08b 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -113,7 +113,7 @@ A simple table from Tab-delimited file (TSV) .. code-block:: postgres CREATE OR REPLACE FOREIGN TABLE cool_animals - (id INT NOT NULL, name VARCHAR(30) NOT NULL, weight FLOAT NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) WRAPPER csv_fdw OPTIONS ( LOCATION = '/home/rhendricks/cool_animals.csv', @@ -128,7 +128,7 @@ A table from a directory of Parquet files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) WRAPPER parquet_fdw OPTIONS ( @@ -141,7 +141,7 @@ A table from a bucket of ORC files on S3 .. code-block:: postgres CREATE FOREIGN TABLE users - (id INT NOT NULL, name VARCHAR(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index f47ffaec1..03bd20d70 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -163,14 +163,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index 6fe41fa08..9232a5162 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -66,14 +66,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); @@ -109,7 +109,7 @@ Use parameters to replace them later at execution time. .. tip:: Use dollar quoting (`$$`) to avoid escaping strings. - .. code-block:: psql +.. code-block:: psql t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); executed @@ -119,5 +119,4 @@ Use parameters to replace them later at execution time. Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 - + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_ddl.rst b/reference/sql/sql_statements/utility_commands/get_ddl.rst index f2566e99a..bc3b9ef54 100644 --- a/reference/sql/sql_statements/utility_commands/get_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_ddl.rst @@ -55,7 +55,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -64,7 +64,7 @@ The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_ farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text(30) not null, "weight" double null, "is_agressive" bool default false not null ) ; diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index be34c33ed..f71f6e025 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -70,14 +70,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); @@ -123,5 +123,4 @@ Use parameters to replace them later at execution time. Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 - + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 \ No newline at end of file diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 906684590..bc5376dd1 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -239,7 +239,6 @@ The following is a syntax reference for typed literals: | REAL | DATE | DATETIME - | VARCHAR ( digits ) | TEXT ( digits ) Examples diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 4cd995977..7f788ff46 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -28,14 +28,14 @@ The following is an example of table named ``nba`` with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index cb87e085e..39d072d33 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -221,14 +221,14 @@ For these examples, assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - "Name" varchar(40), - "Team" varchar(40), + "Name" text(40), + "Team" text(40), "Number" tinyint, - "Position" varchar(2), + "Position" text(2), "Age" tinyint, - "Height" varchar(4), + "Height" text(4), "Weight" real, - "College" varchar(40), + "College" text(40), "Salary" float ); diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst index a260f59d5..12623c943 100644 --- a/troubleshooting/log_related_issues.rst +++ b/troubleshooting/log_related_issues.rst @@ -18,7 +18,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas CREATE FOREIGN TABLE logs ( - start_marker VARCHAR(4), + start_marker TEXT(4), row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -32,7 +32,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas service_name TEXT, message_type_id INT, message TEXT, - end_message VARCHAR(5) + end_message TEXT(5) ) WRAPPER csv_fdw OPTIONS From 4996747e7e8e5ee5486b109bf89905281546867b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Apr 2022 15:16:23 +0300 Subject: [PATCH 0034/1892] Replaced VARCHAR with TEXT... ... according to Shachar's comments in the Slack threads. --- data_ingestion/inserting_data.rst | 81 +++++----- data_ingestion/orc.rst | 56 +++---- data_ingestion/parquet.rst | 37 +++-- data_type_guides/sql_data_types_date.rst | 2 +- .../sql_data_types_floating_point.rst | 3 +- data_type_guides/sql_data_types_integer.rst | 2 +- data_type_guides/sql_data_types_string.rst | 30 +--- .../monitoring_query_performance.rst | 4 +- .../conditionals/is_ascii.rst | 15 +- .../scalar_functions/conversion/to_hex.rst | 4 +- .../scalar_functions/numeric/crc64.rst | 19 +-- .../scalar_functions/string/octet_length.rst | 10 +- .../scalar_functions/string/replace.rst | 10 +- .../scalar_functions/string/rtrim.rst | 2 +- .../window_functions/first_value.rst | 2 +- .../window_functions/last_value.rst | 4 +- reference/sql/sql_statements/index.rst | 87 ++++------- reference/sql/sql_syntax/literals.rst | 2 +- reference/sql_feature_support.rst | 141 +++++++++--------- 19 files changed, 209 insertions(+), 302 deletions(-) diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 86bd08103..42ac36ceb 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -53,8 +53,6 @@ SQream therefore recommends: * Applications such as :ref:`Tableau` and others have been tested, and work -* Data types were not over-provisioned (e.g. don't use VARCHAR(2000) to store a short string) - File Soure Location when Loading -------------------------------- @@ -78,20 +76,20 @@ SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, bu - ORC - Streaming data * - :ref:`copy_from` - - ✓ - - ✗ - - ✗ - - ✗ + - Supported + - Not supported + - Not supported + - Not supported * - :ref:`external_tables` - - ✓ - - ✓ - - ✓ - - ✗ + - Supported + - Supported + - Supported + - Not supported * - :ref:`insert` - - ✗ - - ✗ - - ✗ - - ✓ (Python, JDBC, Node.JS) + - Not supported + - Not supported + - Not supported + - Supported (Python, JDBC, Node.JS) Unsupported Data Types ----------------------------- @@ -262,9 +260,8 @@ Type Support and Behavior Notes * The types should match to some extent within the same "class" (see table below). .. list-table:: - :widths: auto + :widths: 5 5 70 70 70 70 5 5 5 5 5 :header-rows: 1 - :stub-columns: 1 * - SQream DB type → @@ -276,15 +273,15 @@ Type Support and Behavior Notes - ``BIGINT`` - ``REAL`` - ``DOUBLE`` - - Text [#f0]_ + - ``Text`` [#f0]_ - ``DATE`` - ``DATETIME`` * - ``boolean`` - - ✓ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ + - Supported + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ - - - @@ -292,10 +289,10 @@ Type Support and Behavior Notes - * - ``tinyint`` - ○ [#f6]_ - - ✓ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported + - Supported - - - @@ -304,9 +301,9 @@ Type Support and Behavior Notes * - ``smallint`` - ○ [#f6]_ - ○ [#f7]_ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported - - - @@ -316,8 +313,8 @@ Type Support and Behavior Notes - ○ [#f6]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ - - ✓ + - Supported + - Supported - - - @@ -328,7 +325,7 @@ Type Support and Behavior Notes - ○ [#f7]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ + - Supported - - - @@ -340,8 +337,8 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported - - - @@ -351,12 +348,12 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported - - - - * - ``string`` / ``char`` / ``varchar`` + * - ``string`` / ``char`` / ``text`` - - - @@ -364,7 +361,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - * - ``date`` @@ -376,8 +373,8 @@ Type Support and Behavior Notes - - - - - ✓ - - ✓ + - Supported + - Supported * - ``timestamp``, ``timestamp`` with timezone - - @@ -388,7 +385,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported * If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. @@ -459,7 +456,7 @@ Further Reading and Migration Guides .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT`` .. [#f2] With UTF8 annotation diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index de10c5ce4..61e9237f9 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -13,9 +13,9 @@ This guide covers inserting data from ORC files into SQream DB using :ref:`FOREI Prepare the source ORC files, with the following requirements: .. list-table:: - :widths: auto + :widths: 5 5 70 70 70 70 5 5 5 5 5 :header-rows: 1 - :stub-columns: 1 + * - SQream DB type → @@ -27,15 +27,15 @@ Prepare the source ORC files, with the following requirements: - ``BIGINT`` - ``REAL`` - ``DOUBLE`` - - Text [#f0]_ + - ``TEXT`` [#f0]_ - ``DATE`` - ``DATETIME`` * - ``boolean`` - - ✓ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ - - ✓ [#f5]_ + - Supported + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ + - Supported [#f5]_ - - - @@ -43,10 +43,10 @@ Prepare the source ORC files, with the following requirements: - * - ``tinyint`` - ○ [#f6]_ - - ✓ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported + - Supported - - - @@ -55,9 +55,9 @@ Prepare the source ORC files, with the following requirements: * - ``smallint`` - ○ [#f6]_ - ○ [#f7]_ - - ✓ - - ✓ - - ✓ + - Supported + - Supported + - Supported - - - @@ -67,8 +67,8 @@ Prepare the source ORC files, with the following requirements: - ○ [#f6]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ - - ✓ + - Supported + - Supported - - - @@ -79,7 +79,7 @@ Prepare the source ORC files, with the following requirements: - ○ [#f7]_ - ○ [#f7]_ - ○ [#f7]_ - - ✓ + - Supported - - - @@ -91,8 +91,8 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported - - - @@ -102,12 +102,12 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported - - - - * - ``string`` / ``char`` / ``varchar`` + * - ``string`` / ``char`` / ``text`` - - - @@ -115,7 +115,7 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ + - Supported - - * - ``date`` @@ -127,8 +127,8 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ - - ✓ + - Supported + - Supported * - ``timestamp``, ``timestamp`` with timezone - - @@ -139,13 +139,13 @@ Prepare the source ORC files, with the following requirements: - - - - - ✓ + - Supported * If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. This can be worked around. See more information in the examples. .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT`` .. [#f5] Boolean values are cast to 0, 1 diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 4579deb82..c5971e064 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -15,9 +15,8 @@ This guide covers inserting data from Parquet files into SQream DB using :ref:`F Prepare the source Parquet files, with the following requirements: .. list-table:: - :widths: auto + :widths: 40 5 20 20 20 20 5 5 5 5 10 :header-rows: 1 - :stub-columns: 1 * - SQream DB type → @@ -29,11 +28,11 @@ Prepare the source Parquet files, with the following requirements: - ``BIGINT`` - ``REAL`` - ``DOUBLE`` - - Text [#f0]_ + - ``TEXT`` [#f0]_ - ``DATE`` - ``DATETIME`` * - ``BOOLEAN`` - - ✓ + - Supported - - - @@ -46,7 +45,7 @@ Prepare the source Parquet files, with the following requirements: * - ``INT16`` - - - - ✓ + - Supported - - - @@ -58,7 +57,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -70,7 +69,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -82,7 +81,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -94,7 +93,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - - @@ -106,7 +105,7 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ + - Supported - - * - ``INT96`` [#f3]_ @@ -119,13 +118,13 @@ Prepare the source Parquet files, with the following requirements: - - - - - ✓ [#f4]_ + - Supported [#f4]_ -* If a Parquet file has an unsupported type like ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. This can be worked around. See more information in the examples. +* If a Parquet file has an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not Supported, but the column may be ommited. This can be worked around. See more information in the examples. .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` +.. [#f0] Text values include ``TEXT`` .. [#f2] With UTF8 annotation @@ -187,7 +186,7 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T Types in SQream DB must match Parquet types exactly. - If the column type isn't supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. + If the column type isn't Supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. 4. Verify table contents @@ -223,21 +222,21 @@ To load the data into SQream DB, use the :ref:`create_table_as` statement: CREATE TABLE nba AS SELECT * FROM ext_nba; -Working around unsupported column types +Working around unSupported column types --------------------------------------------- -Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. +Suppose you only want to load some of the columns - for example, if one of the columns isn't Supported. -By ommitting unsupported columns from queries that access the ``EXTERNAL TABLE``, they will never be called, and will not cause a "type mismatch" error. +By ommitting unSupported columns from queries that access the ``EXTERNAL TABLE``, they will never be called, and will not cause a "type mismatch" error. -For this example, assume that the ``Position`` column isn't supported because of its type. +For this example, assume that the ``Position`` column isn't Supported because of its type. .. code-block:: postgres CREATE TABLE nba AS SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; - -- We ommitted the unsupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. + -- We ommitted the unSupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. Modifying data during the copy process diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index da83f80cc..88236c113 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -108,5 +108,5 @@ The following table shows the possible ``DATE`` and ``DATETIME`` value conversio * - Type - Details - * - ``VARCHAR(n)`` + * - ``TEXT`` - ``'1997-01-01'`` → ``'1997-01-01'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_floating_point.rst b/data_type_guides/sql_data_types_floating_point.rst index 18227140c..3edc8362d 100644 --- a/data_type_guides/sql_data_types_floating_point.rst +++ b/data_type_guides/sql_data_types_floating_point.rst @@ -74,7 +74,6 @@ The following table shows the possible Floating Point value conversions: - ``1.0`` → ``true``, ``0.0`` → ``false`` * - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT`` - ``2.0`` → ``2``, ``3.14159265358979`` → ``3``, ``2.718281828459`` → ``2``, ``0.5`` → ``0``, ``1.5`` → ``1`` - * - ``VARCHAR(n)`` (n > 6 recommended) - - ``1`` → ``'1.0000'``, ``3.14159265358979`` → ``'3.1416'`` + .. note:: As shown in the above examples, casting ``real`` to ``int`` rounds down. \ No newline at end of file diff --git a/data_type_guides/sql_data_types_integer.rst b/data_type_guides/sql_data_types_integer.rst index 9d4210731..cd27f6956 100644 --- a/data_type_guides/sql_data_types_integer.rst +++ b/data_type_guides/sql_data_types_integer.rst @@ -79,5 +79,5 @@ The following table shows the possible Integer value conversions: - Details * - ``REAL``, ``DOUBLE`` - ``1`` → ``1.0``, ``-32`` → ``-32.0`` - * - ``VARCHAR(n)`` (All numberic values must fit in the string length) + * - ``TEXT`` (All numberic values must fit in the string length) - ``1`` → ``'1'``, ``2451`` → ``'2451'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index 0d977b6d2..4b1a1b406 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -5,30 +5,7 @@ String ************************* ``TEXT`` is designed for storing text or strings of characters. -SQream separates ASCII (``VARCHAR``) and UTF-8 representations (``TEXT``). - -.. note:: The data type ``NVARCHAR`` has been deprecated by ``TEXT`` as of version 2020.1. - -String Types -^^^^^^^^^^^^^^^^^^^^^^ -The following table describes the String types: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Name - - Details - - Data Size (Not Null, Uncompressed) - - Example - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` - - Varaiable length string - UTF-8 unicode. ``NVARCHAR`` is synonymous with ``TEXT``. - - Up to ``4*n`` bytes - - ``'キウイは楽しい鳥です'`` - * - ``VARCHAR (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` +SQream UTF-8 representations (``TEXT``). Length ^^^^^^^^^ @@ -37,8 +14,7 @@ When using ``TEXT``, specifying a size is optional. If not specified, the text f The following apply to setting the String type length: * If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. -* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: VARCHAR(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. -* ``VARCHAR`` strings are padded with spaces. +* When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: TEXT(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. Syntax ^^^^^^^^ @@ -47,7 +23,7 @@ String types can be written with standard SQL string literals, which are enclose Size ^^^^^^ -``VARCHAR(n)`` can occupy up to *n* bytes, whereas ``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. +``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. String Examples ^^^^^^^^^^ diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index a542f61e6..a38ddc6d0 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -200,7 +200,7 @@ Commonly Seen Nodes - Description * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``VARCHAR`` types + - Decompression operation, common for longer ``TEXT`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU @@ -621,7 +621,7 @@ Common Solutions for Improving Filtering * Use :ref:`clustering keys and naturally ordered data` in your filters. * Avoid full table scans when possible -4. Joins with ``varchar`` Keys +4. Joins with ``text`` Keys ----------------------------------- Joins on long text keys, such as ``varchar(100)`` do not perform as well as numeric data types or very short text keys. diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst index bb9e3b2f9..495e46e76 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst @@ -45,20 +45,19 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE dictionary (id INT NOT NULL, fw TEXT(30), en VARCHAR(30)); - - INSERT INTO dictionary VALUES (1, '行こう', 'Let''s go'), (2, '乾杯', 'Cheers'), (3, 'L''chaim', 'Cheers'); + CREATE TABLE dictionary (id INT NOT NULL, text TEXT); + INSERT INTO dictionary VALUES (1, '行こう'), (2, '乾杯'), (3, 'L''chaim'); + SELECT id, text, IS_ASCII(text) FROM dictionary; IS NULL ----------- .. code-block:: psql - m=> SELECT id, en, fw, IS_ASCII(fw) FROM dictionary; - id | en | fw | is_ascii + id | text | is_ascii ---+----------+----------+--------- - 1 | Let's go | 行こう | false - 2 | Cheers | 乾杯 | false - 3 | Cheers | L'chaim | true + 1 | 行こう | false + 2 | 乾杯 | false + 3 | L'chaim | true diff --git a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst index f3cf6fb82..d33643f22 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst @@ -11,7 +11,7 @@ Syntax .. code-block:: postgres - TO_HEX( expr ) --> VARCHAR + TO_HEX( expr ) --> TEXT Arguments ============ @@ -28,7 +28,7 @@ Arguments Returns ============ -* Representation of the hexadecimal number of type ``VARCHAR``. +* Representation of the hexadecimal number of type ``TEXT``. Examples diff --git a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst index 105dae47c..8d067485d 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst @@ -12,8 +12,6 @@ Syntax .. code-block:: postgres CRC64( expr ) --> BIGINT - - CRC64_JOIN( expr ) --> BIGINT Arguments ============ @@ -32,14 +30,7 @@ Returns Returns a CRC-64 hash of the text input, of type ``BIGINT``. -Notes -======= - -* If the input value is NULL, the result is NULL. - -* The ``CRC64_JOIN`` can be used with ``VARCHAR`` only. It can not be used with ``TEXT``. - -* The ``CRC64_JOIN`` variant ignores leading whitespace when used as a ``JOIN`` key. +.. note:: If the input value is NULL, the result is NULL. Examples =========== @@ -49,9 +40,5 @@ Calculate a CRC-64 hash of a string .. code-block:: psql - numbers=> SELECT CRC64(x) FROM - . (VALUES ('This is a relatively long text string, that can be converted to a shorter hash' :: varchar(80))) - . as t(x); - crc64 - -------------------- - -9085161068710498500 \ No newline at end of file + SELECT CRC64(x) FROM (VALUES ('This is a relatively long text string, that can be converted to a shorter hash' :: text)) as t(x); + -8397827068206190216 \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index 8bb1e3daf..0836b4685 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -6,14 +6,10 @@ OCTET_LENGTH Calculates the number of bytes in a string. -.. note:: +.. note:: + + * To get the length in bytes, see :ref:`octet_length`. - * This function is supported on ``TEXT`` strings only. - - * To get the length in characters, see :ref:`char_length`. - - * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. - Syntax ========== The following is the correct syntax for the ``OCTET_LENGTH`` function: diff --git a/reference/sql/sql_functions/scalar_functions/string/replace.rst b/reference/sql/sql_functions/scalar_functions/string/replace.rst index 5552be269..d2fab561a 100644 --- a/reference/sql/sql_functions/scalar_functions/string/replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/replace.rst @@ -6,9 +6,6 @@ REPLACE Replaces all occurrences of a specified string value with another string value. -.. warning:: With ``VARCHAR``, a substring can only be replaced with another substring of equal **byte length**. See :ref:`octet_length`. - - Syntax ========== @@ -37,12 +34,7 @@ Returns Returns the same type as the argument supplied. -Notes -======= - -* In ``VARCHAR`` strings, the ``source_expr`` and ``replacement_expr`` must be the same **byte length**. See :ref:`octet_length`. - -* If the value is NULL, the result is NULL. +.. note:: If the value is NULL, the result is NULL. Examples =========== diff --git a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst index 2bd5bbc38..61fdc877d 100644 --- a/reference/sql/sql_functions/scalar_functions/string/rtrim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/rtrim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``VARCHAR`` does not affect the result. +* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. Using ``RTRIM`` on ``TEXT`` does not affect the result. * This function is equivalent to the ANSI form ``TRIM( TRAILING FROM expr )`` diff --git a/reference/sql/sql_functions/window_functions/first_value.rst b/reference/sql/sql_functions/window_functions/first_value.rst index 25294040c..78896746a 100644 --- a/reference/sql/sql_functions/window_functions/first_value.rst +++ b/reference/sql/sql_functions/window_functions/first_value.rst @@ -5,7 +5,7 @@ FIRST_VALUE ************************** The **FIRST_VALUE** function returns the value located in the selected column of the first row of a segment. If the table is not segmented, the FIRST_VALUE function returns the value from the first row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the first employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. Syntax ------- diff --git a/reference/sql/sql_functions/window_functions/last_value.rst b/reference/sql/sql_functions/window_functions/last_value.rst index 3cadaa9d1..ae1276e79 100644 --- a/reference/sql/sql_functions/window_functions/last_value.rst +++ b/reference/sql/sql_functions/window_functions/last_value.rst @@ -5,7 +5,7 @@ LAST_VALUE ************************** The **LAST_VALUE** function returns the value located in the selected column of the last row of a segment. If the table is not segmented, the LAST_VALUE function returns the value from the last row of the whole table. -This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``varchar`` type, the function returns a ``varchar`` type name column. +This function returns the same type of variable that you input for your requested value. For example, requesting the value for the last employee in a list using an ``int`` type output returns an ``int`` type ID column. If you use a ``text`` type, the function returns a ``text`` type name column. Syntax ------- @@ -21,4 +21,4 @@ None Returns --------- -Returns the value located in the selected column of the last row of a segment. +Returns the value located in the selected column of the last row of a segment. \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index e14041385..ae0139607 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -11,8 +11,6 @@ SQream DB supports commands from ANSI SQL. Data Definition Commands (DDL) ================================ - update - .. list-table:: DDL Commands :widths: auto :header-rows: 1 @@ -20,45 +18,47 @@ Data Definition Commands (DDL) * - Command - Usage - * - :ref:`ADD COLUMN` + * - :ref:`add_column` - Add a new column to a table - * - :ref:`UPDATE` - - Modify the value of certain columns in existing rows without creating a table - * - :ref:`ALTER DEFAULT SCHEMA` + * - :ref:`alter_default_schema` - Change the default schema for a role - * - :ref:`ALTER TABLE` + * - :ref:`alter_table` - Change the schema of a table - * - :ref:`CREATE DATABASE` + * - :ref:`cluster_by` + - Change clustering keys in a table + * - :ref:`create_database` - Create a new database - * - :ref:`CREATE EXTERNAL TABLE` + * - :ref:`create_external_table` - Create a new external table in the database (deprecated) - * - :ref:`CREATE FOREIGN TABLE` + * - :ref:`create_foreign_table` - Create a new foreign table in the database - * - :ref:`CREATE FUNCTION ` + * - :ref:`create_function` - Create a new user defined function in the database - * - :ref:`CREATE SCHEMA` + * - :ref:`create_schema` - Create a new schema in the database - * - :ref:`CREATE TABLE` + * - :ref:`create_table` - Create a new table in the database - * - :ref:`CREATE TABLE AS` + * - :ref:`create_table_as` - Create a new table in the database using results from a select query - * - :ref:`CREATE VIEW` + * - :ref:`create_view` - Create a new view in the database - * - :ref:`DROP COLUMN` + * - :ref:`drop_clustering_key` + - Drops all clustering keys in a table + * - :ref:`drop_column` - Drop a column from a table - * - :ref:`DROP DATABASE` + * - :ref:`drop_database` - Drop a database and all of its objects - * - :ref:`DROP FUNCTION` + * - :ref:`drop_function` - Drop a function - * - :ref:`DROP SCHEMA` + * - :ref:`drop_schema` - Drop a schema - * - :ref:`DROP TABLE` + * - :ref:`drop_table` - Drop a table and its contents from a database - * - :ref:`DROP VIEW` + * - :ref:`drop_view` - Drop a view - * - :ref:`RENAME COLUMN` + * - :ref:`rename_column` - Rename a column - * - :ref:`RENAME TABLE` + * - :ref:`rename_table` - Rename a table Data Manipulation Commands (DML) @@ -86,6 +86,8 @@ Data Manipulation Commands (DML) - Select rows and column from a table * - :ref:`TRUNCATE` - Delete all rows from a table + * - :ref:`UPDATE` + - Modify the value of certain columns in existing rows without creating a table * - :ref:`VALUES` - Return rows containing literal values @@ -111,29 +113,6 @@ Utility Commands * - :ref:`SELECT DUMP_DATABASE_DDL` - View the ``CREATE TABLE`` statement for an current database -Saved Queries -=================== - -.. list-table:: Saved Queries - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`SELECT DROP_SAVED_QUERY` - - Drop a saved query - * - :ref:`SELECT EXECUTE_SAVED_QUERY` - - Executes a saved query - * - :ref:`SELECT LIST_SAVED_QUERIES` - - Returns a list of saved queries - * - :ref:`SELECT RECOMPILE_SAVED_QUERY` - - Recompiles a query that has been invalidated by a schema change - * - :ref:`SELECT SAVE_QUERY` - - Compiles and saves a query for re-use and sharing - * - :ref:`SELECT SHOW_SAVED_QUERY` - - Shows query text for a saved query - -For more information, see :ref:`saved_queries` Monitoring @@ -202,18 +181,4 @@ Access Control Commands * - :ref:`revoke` - Revoke permissions from a role * - :ref:`rename_role` - - Rename a role - - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :hidden: - :glob: - - ddl_commands/* - dml_commands/* - utility_commands/* - monitoring_commands/* - wlm_commands/* - access_control_commands/* \ No newline at end of file + - Rename a role \ No newline at end of file diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index bc5376dd1..d1ec35dbe 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -86,7 +86,7 @@ Examples '1997-01-01' -- This is a string -The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``VARCHAR``. +The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``TEXT``. .. code-block:: postgres diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index ba4ca39e4..4443d631a 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -14,7 +14,7 @@ To understand which ANSI SQL and other SQL features SQream DB supports, use the Data Types and Values ========================= -Read more about :ref:`supported data types`. +Read more about :ref:`Yes data types`. .. list-table:: Data Types and Values :widths: auto @@ -24,46 +24,43 @@ Read more about :ref:`supported data types`. - Supported - Further information * - ``BOOL`` - - ✓ + - Yes - Boolean values * - ``TINTINT`` - - ✓ + - Yes - Unsigned 1 byte integer (0 - 255) * - ``SMALLINT`` - - ✓ + - Yes - 2 byte integer (-32,768 - 32,767) * - ``INT`` - - ✓ + - Yes - 4 byte integer (-2,147,483,648 - 2,147,483,647) * - ``BIGINT`` - - ✓ + - Yes - 8 byte integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) * - ``REAL`` - - ✓ + - Yes - 4 byte floating point * - ``DOUBLE``, ``FLOAT`` - - ✓ + - Yes - 8 byte floating point * - ``DECIMAL``, ``NUMERIC`` - - ✓ + - Yes - Fixed-point numbers. - * - ``VARCHAR`` - - ✓ - - Variable length string - ASCII only * - ``TEXT`` - - ✓ + - Yes - Variable length string - UTF-8 encoded * - ``DATE`` - - ✓ + - Yes - Date * - ``DATETIME``, ``TIMESTAMP`` - - ✓ + - Yes - Date and time * - ``NULL`` - - ✓ + - Yes - ``NULL`` values * - ``TIME`` - - ✗ + - No - Can be stored as a text string or as part of a ``DATETIME`` @@ -77,14 +74,14 @@ Contraints * - Item - Supported - Further information - * - Not null - - ✓ + * - ``Not null`` + - Yes - ``NOT NULL`` - * - Default values - - ✓ + * - ``Default values`` + - Yes - ``DEFAULT`` * - ``AUTO INCREMENT`` - - ✓ Different name + - Yes (different name) - ``IDENTITY`` @@ -118,43 +115,43 @@ Schema Changes - Supported - Further information * - ``ALTER TABLE`` - - ✓ + - Yes - :ref:`alter_table` - Add column, alter column, drop column, rename column, rename table, modify clustering keys * - Rename database - - ✗ + - No - * - Rename table - - ✓ + - Yes - :ref:`rename_table` * - Rename column - - ✓ + - Yes - :ref:`rename_column` * - Add column - - ✓ + - Yes - :ref:`add_column` * - Remove column - - ✓ + - Yes - :ref:`drop_column` * - Alter column data type - - ✗ + - No - * - Add / modify clustering keys - - ✓ + - Yes - :ref:`cluster_by` * - Drop clustering keys - - ✓ + - Yes - :ref:`drop_clustering_key` * - Add / Remove constraints - - ✗ + - No - * - Rename schema - - ✗ + - No - * - Drop schema - - ✓ + - Yes - :ref:`drop_schema` * - Alter default schema per user - - ✓ + - Yes - :ref:`alter_default_schema` @@ -169,28 +166,28 @@ Statements - Supported - Further information * - SELECT - - ✓ + - Yes - :ref:`select` * - CREATE TABLE - - ✓ + - Yes - :ref:`create_table` * - CREATE FOREIGN / EXTERNAL TABLE - - ✓ + - Yes - :ref:`create_foreign_table` * - DELETE - - ✓ + - Yes - :ref:`delete_guide` * - INSERT - - ✓ + - Yes - :ref:`insert`, :ref:`copy_from` * - TRUNCATE - - ✓ + - Yes - :ref:`truncate` * - UPDATE - - ✗ + - No - * - VALUES - - ✓ + - Yes - :ref:`values` Clauses @@ -204,19 +201,19 @@ Clauses - Supported - Further information * - ``LIMIT`` / ``TOP`` - - ✓ + - Yes - * - ``LIMIT`` with ``OFFSET`` - - ✗ + - No - * - ``WHERE`` - - ✓ + - Yes - * - ``HAVING`` - - ✓ + - Yes - * - ``OVER`` - - ✓ + - Yes - Table Expressions @@ -230,19 +227,19 @@ Table Expressions - Supported - Further information * - Tables, Views - - ✓ + - Yes - * - Aliases, ``AS`` - - ✓ + - Yes - * - ``JOIN`` - ``INNER``, ``LEFT [ OUTER ]``, ``RIGHT [ OUTER ]``, ``CROSS`` - - ✓ + - Yes - * - Table expression subqueries - - ✓ + - Yes - * - Scalar subqueries - - ✗ + - No - @@ -259,34 +256,34 @@ Read more about :ref:`scalar_expressions`. - Supported - Further information * - Common functions - - ✓ + - Yes - ``CURRENT_TIMESTAMP``, ``SUBSTRING``, ``TRIM``, ``EXTRACT``, etc. * - Comparison operators - - ✓ + - Yes - ``<``, ``<=``, ``>``, ``>=``, ``=``, ``<>, !=``, ``IS``, ``IS NOT`` * - Boolean operators - - ✓ + - Yes - ``AND``, ``NOT``, ``OR`` * - Conditional expressions - - ✓ + - Yes - ``CASE .. WHEN`` * - Conditional functions - - ✓ + - Yes - ``COALESCE`` * - Pattern matching - - ✓ + - Yes - ``LIKE``, ``RLIKE``, ``ISPREFIXOF``, ``CHARINDEX``, ``PATINDEX`` * - REGEX POSIX pattern matching - - ✓ + - Yes - ``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, * - ``EXISTS`` - - ✗ + - No - * - ``IN``, ``NOT IN`` - Partial - Literal values only * - Bitwise arithmetic - - ✓ + - Yes - ``&``, ``|``, ``XOR``, ``~``, ``>>``, ``<<`` @@ -304,16 +301,16 @@ Read more about :ref:`access_control` in SQream DB. - Supported - Further information * - Roles as users and groups - - ✓ + - Yes - * - Object default permissions - - ✓ + - Yes - * - Column / Row based permissions - - ✗ + - No - * - Object ownership - - ✗ + - No - @@ -329,20 +326,20 @@ Extra Functionality - Supported - Further information * - Information schema - - ✓ + - Yes - :ref:`catalog_reference` * - Views - - ✓ + - Yes - :ref:`create_view` * - Window functions - - ✓ + - Yes - :ref:`window_functions` * - CTEs - - ✓ + - Yes - :ref:`common_table_expressions` * - Saved queries, Saved queries with parameters - - ✓ + - Yes - :ref:`saved_queries` * - Sequences - - ✓ + - Yes - :ref:`identity` From b6b9249dddf1365520566271e6e727a15d6750d2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Apr 2022 17:16:14 +0300 Subject: [PATCH 0035/1892] Continued Updating... ... Not done... --- operational_guides/monitoring_query_performance.rst | 2 +- .../sql_functions/scalar_functions/string/char_length.rst | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index a38ddc6d0..07897f585 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -623,7 +623,7 @@ Common Solutions for Improving Filtering 4. Joins with ``text`` Keys ----------------------------------- -Joins on long text keys, such as ``varchar(100)`` do not perform as well as numeric data types or very short text keys. +Joins on long text keys do not perform as well as numeric data types or very short text keys. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index f89c397ab..47d517975 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -7,13 +7,9 @@ CHAR_LENGTH Calculates the number of characters in a string. .. note:: - - * This function is supported on ``TEXT`` only. - + * To get the length in bytes, see :ref:`octet_length`. - * For ``VARCHAR`` strings, the octet length is the number of characters. Use :ref:`len` instead. - Syntax ========== From 15b18684b41d04a14dcc1851f6647f48c9d9b29f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 5 Apr 2022 13:52:01 +0300 Subject: [PATCH 0036/1892] Replaced VARCHAR with TEXT --- data_ingestion/avro.rst | 344 ++++++++++++++++++ data_ingestion/orc.rst | 4 +- .../converting_and_casting_types.rst | 2 +- data_type_guides/sql_data_types_string.rst | 2 +- data_type_guides/supported_data_types.rst | 6 +- ...ata_clustering_data_clustering_methods.rst | 6 +- getting_started/creating_your_first_table.rst | 6 +- .../monitoring_query_performance.rst | 36 +- .../seeing_system_objects_as_ddl.rst | 4 +- .../scalar_functions/conditionals/is_null.rst | 2 +- .../date_and_time/eomonth.rst | 2 +- .../date_and_time/extract.rst | 2 +- .../scalar_functions/string/charindex.rst | 4 +- .../scalar_functions/string/isprefixof.rst | 2 +- .../scalar_functions/string/lower.rst | 2 +- .../scalar_functions/string/patindex.rst | 2 +- .../scalar_functions/string/trim.rst | 2 +- .../scalar_functions/string/upper.rst | 2 +- .../ddl_commands/create_function.rst | 2 +- .../ddl_commands/create_table.rst | 12 +- .../monitoring_commands/show_node_info.rst | 2 +- .../utility_commands/drop_saved_query.rst | 55 --- .../utility_commands/dump_database_ddl.rst | 2 +- .../utility_commands/execute_saved_query.rst | 122 ------- .../utility_commands/list_saved_queries.rst | 77 ---- .../recompile_saved_query.rst | 88 ----- .../utility_commands/save_query.rst | 2 +- .../utility_commands/show_saved_query.rst | 61 ---- ...ts_and_running_queries_from_the_editor.rst | 2 +- 29 files changed, 398 insertions(+), 457 deletions(-) create mode 100644 data_ingestion/avro.rst delete mode 100644 reference/sql/sql_statements/utility_commands/drop_saved_query.rst delete mode 100644 reference/sql/sql_statements/utility_commands/execute_saved_query.rst delete mode 100644 reference/sql/sql_statements/utility_commands/list_saved_queries.rst delete mode 100644 reference/sql/sql_statements/utility_commands/recompile_saved_query.rst delete mode 100644 reference/sql/sql_statements/utility_commands/show_saved_query.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst new file mode 100644 index 000000000..f74d8875d --- /dev/null +++ b/data_ingestion/avro.rst @@ -0,0 +1,344 @@ +.. _avro: + +************************** +Inserting Data from Avro +************************** +The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=========== +**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility and nesting as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. + +Avro Data Types +=========== + +Avro includes the following data types: + +.. contents:: + :local: + :depth: 1 + +Primitive Data Types +-------------- +The following table shows the supported **Primitive** data types: + ++-------------+------------------------------------------------------+ +| Avro Type | SQream Type | +| +-----------+---------------+-----------+--------------+ +| | Number | Date/Datetime | String | Boolean | ++=============+===========+===============+===========+==============+ +| ``null`` | Supported | Supported | Supported | Supported | ++-------------+-----------+---------------+-----------+--------------+ +| ``boolean`` | | | Supported | Supported | ++-------------+-----------+---------------+-----------+--------------+ +| ``int`` | Supported | | Supported | | ++-------------+-----------+---------------+-----------+--------------+ +| ``long`` | Supported | | Supported | | ++-------------+-----------+---------------+-----------+--------------+ +| ``float`` | Supported | | Supported | | ++-------------+-----------+---------------+-----------+--------------+ +| ``double`` | Supported | | Supported | | ++-------------+-----------+---------------+-----------+--------------+ +| ``bytes`` | | | | | ++-------------+-----------+---------------+-----------+--------------+ +| ``string`` | | Supported | Supported | | ++-------------+-----------+---------------+-----------+--------------+ + + + + + + +Complex Data Types +-------------- +The following table shows the supported **Complex** data types: + ++------------+---------------------------------------------------+ +| | SQream Type | +| +-----------+---------------+-----------+-----------+ +|Avro Type | Number | Date/Datetime | String | Boolean | ++============+===========+===============+===========+===========+ +| ``record`` | | | | | ++------------+-----------+---------------+-----------+-----------+ +| ``enum`` | | | Supported | | ++------------+-----------+---------------+-----------+-----------+ +| ``array`` | | | | | ++------------+-----------+---------------+-----------+-----------+ +| ``map`` | | | | | ++------------+-----------+---------------+-----------+-----------+ +| ``union`` | Supported | Supported | Supported | Supported | ++------------+-----------+---------------+-----------+-----------+ +| ``fixed`` | | | | | ++------------+-----------+---------------+-----------+-----------+ + + +Logical Data Types +-------------- +The following table shows the supported **Logical** data types: + ++----------------------------+-------------------------------------------------+ +| Avro Type | SQream Type | +| +-----------+---------------+-----------+---------+ +| | Number | Date/Datetime | String | Boolean | ++============================+===========+===============+===========+=========+ +| ``decimal`` | Supported | | Supported | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``uuid`` | | | Supported | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``date`` | | Supported | Supported | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``time-millis`` | | | | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``time-micros`` | | | | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``timestamp-millis`` | | Supported | Supported | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``timestamp-micros`` | | Supported | Supported | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``local-timestamp-millis`` | | | | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``local-timestamp-micros`` | | | | | ++----------------------------+-----------+---------------+-----------+---------+ +| ``duration`` | | | | | ++----------------------------+-----------+---------------+-----------+---------+ + + +Mapping Objects to Rows +=============== +When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. + +Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. + +Ingesting Avro Files +==================== +This section describes how to ingest Avro files into SQream and covers the following: + + +.. contents:: + :local: + :depth: 1 + + +Preparing Your Avro Source File +---------- +Prepare your Avro source files according to the following requirements: + +* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). + + :: + +* Files are encoded with UTF-8 or ASCII. + + :: + +* Field delimiter is an ASCII character or characters. + + :: + +* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). + + :: + +* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. + + :: + +* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: + + * The record delimiter or field delimiter. + + :: + + * A double quote character. + + :: + + * A newline. + +SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. + +``NULL`` values can be marked in the following ways in Avro files: + + * An explicit null marker. For example, ``col1,\N,col3``. + + :: + + * An empty field delimited by the field delimiter. For example, ``col1,,col3``. + + .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. + +For more information about standard CSV files, see `RFC 4180 standard CSVs `_. + +Making Avro Files Accessible to Workers +--------------------- +To give workers access to files every node must have the same view of the storage being used. + +The following apply for Avro files to be accessible to workers: + +* For files hosted on NFS, ensure that the mount is accessible from all servers. + +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Basing Your Table Structure on Inserted Tables +--------------------- +Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.parquet`` table shown below: + +.. csv-table:: nba.parquet + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.parquet' + ); + +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. + +Verifying Your Table Output +--------------------- +Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. + +The following is an example of the output based on the **nba.parquet** table: + +.. code-block:: psql + + t=> SELECT * FROM ext_nba LIMIT 10; + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. + +Loading Data into SQream +--------------------- + +Syntax +~~~~~~~~~~~~~~~~~~~~~ +The following is the correct syntax for loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE
AS + SELECT * FROM ; + +The following is an example of loading data into SQream: + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT * FROM ext_nba; + +For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. + +Examples +~~~~~~~~~~~~~~~~~~~~~ + +This section includes the following examples of loading data into SQream: + +.. contents:: + :local: + :depth: 1 + +Omitting Unsupported Column Types +********************** +When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. + +In the example below, the ``Position`` column is not supported due its type. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + + +Modifying Data Before Loading +********************** +One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. + +For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement + +In the example below, the ``Position`` column is set to the default ``NULL``. + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary + FROM ext_nba + ORDER BY weight; + + +Loading a Table from a Directory of Avro Files on HDFS +********************** +The following is an example of loading a table from a directory of Avro files on HDFS: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; + +For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. + +Loading a Table from a Directory of Avro Files on S3 +********************** +The following is an example of loading a table from a directory of Avro files on S3: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_users + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index 61e9237f9..cfcf6c38b 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -288,7 +288,7 @@ Loading a table from a directory of ORC files on HDFS .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( @@ -303,7 +303,7 @@ Loading a table from a bucket of files on S3 .. code-block:: postgres CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email VARCHAR(50) NOT NULL) + (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) WRAPPER orc_fdw OPTIONS ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index ee5e273da..e4de6eeb7 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT(30))``. :: diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index 4b1a1b406..df4261d8f 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -9,7 +9,7 @@ SQream UTF-8 representations (``TEXT``). Length ^^^^^^^^^ -When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``VARCHAR(n)`` or ``TEXT(n)``, where ``n`` is the permitted number of characters. +When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``TEXT(n)``, where ``n`` is the permitted number of characters. The following apply to setting the String type length: diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 2743b054b..afc735ad1 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -51,17 +51,17 @@ The following table shows the supported data types. - 8 bytes - ``0.000003`` - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT [(n)]``, ``NVARCHAR (n)`` + * - ``TEXT [(n)]`` - Variable length string - UTF-8 unicode - Up to ``4*n`` bytes - ``'キウイは楽しい鳥です'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NVARCHAR`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR`` * - ``NUMERIC`` - 38 digits - 16 bytes - ``0.123245678901234567890123456789012345678`` - ``DECIMAL`` - * - ``VARCHAR (n)`` + * - ``TEXT (n)`` - Variable length string - ASCII only - ``n`` bytes - ``'Kiwis have tiny wings, but cannot fly.'`` diff --git a/feature_guides/flexible_data_clustering_data_clustering_methods.rst b/feature_guides/flexible_data_clustering_data_clustering_methods.rst index 347be830a..6949547ba 100644 --- a/feature_guides/flexible_data_clustering_data_clustering_methods.rst +++ b/feature_guides/flexible_data_clustering_data_clustering_methods.rst @@ -63,7 +63,7 @@ Best Practices for Time-Based Management ~~~~~~~~~~ Data inserted in bulks is automatically timestamped with the insertion date and time. Therefore, inserting data through small and frequent bulks has the effect of naturally ordering data according to timestamp. Frequent bulks generally refers to short time frames, such as at 15-minute, hourly, or daily intervals. As you insert new data, SQream chunks and appends it into your existing tables according to its timestamp. -The ``DATE`` and ``DATETIME`` types were created to improve performance, minimze storage size, and maintain data integrity. SQream recommends using them instead of ``VARCHAR``. +The ``DATE`` and ``DATETIME`` types were created to improve performance, minimze storage size, and maintain data integrity. SQream recommends using them instead of ``TEXT``. Using Clustering Keys ============ @@ -76,9 +76,9 @@ A clustering key is a subset of table columns or expressions and is defined usin .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name TEXT(30) NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country TEXT(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY country; diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index c070b43ed..2837907f8 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -21,7 +21,7 @@ The ``CREATE TABLE`` syntax is used to create your first table. This table inclu CREATE TABLE cool_animals ( id INT NOT NULL, - name VARCHAR(20), + name TEXT(20), weight INT ); @@ -37,7 +37,7 @@ You can drop an existing table and create a new one by adding the ``OR REPLACE`` CREATE OR REPLACE TABLE cool_animals ( id INT NOT NULL, - name VARCHAR(20), + name TEXT(20), weight INT ); @@ -54,7 +54,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t test=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(20), + "name" text(20), "weight" int ); diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 07897f585..057512968 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -47,7 +47,7 @@ First, create a foreign table for the logs .. code-block:: postgres CREATE FOREIGN TABLE logs ( - start_marker VARCHAR(4), + start_marker TEXT(4), row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -61,7 +61,7 @@ First, create a foreign table for the logs service_name TEXT, message_type_id INT, message TEXT, - end_message VARCHAR(5) + end_message TEXT(5) ) WRAPPER cdv_fdw OPTIONS @@ -636,20 +636,20 @@ For example, consider these two table structures: amt FLOAT NOT NULL, i INT NOT NULL, ts DATETIME NOT NULL, - country_code VARCHAR(3) NOT NULL, - flag VARCHAR(10) NOT NULL, - fk VARCHAR(50) NOT NULL + country_code TEXT(3) NOT NULL, + flag TEXT(10) NOT NULL, + fk TEXT(50) NOT NULL ); CREATE TABLE t_b ( - id VARCHAR(50) NOT NULL + id TEXT(50) NOT NULL prob FLOAT NOT NULL, j INT NOT NULL, ); #. Run a query. - In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``VARCHAR(50)``. + In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``TEXT(50)``. .. code-block:: postgres @@ -688,7 +688,7 @@ For example, consider these two table structures: Improving Query Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* In general, try to avoid ``VARCHAR`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. +* In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. * Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text input and returns a ``BIGINT`` hash. @@ -726,10 +726,10 @@ Improving Query Performance * You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. -5. Sorting on big ``VARCHAR`` fields +5. Sorting on big ``TEXT`` fields --------------------------------------- In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. -When running a ``GROUP BY`` on large ``VARCHAR`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. +When running a ``GROUP BY`` on large ``TEXT`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -749,9 +749,9 @@ For example: i INT NOT NULL, amt DOUBLE NOT NULL, ts DATETIME NOT NULL, - country_code VARCHAR(100) NOT NULL, - flag VARCHAR(10) NOT NULL, - string_fk VARCHAR(50) NOT NULL + country_code TEXT(100) NOT NULL, + flag TEXT(10) NOT NULL, + string_fk TEXT(50) NOT NULL ); We will run a query, and inspect it's execution details: @@ -800,16 +800,16 @@ For example: max --- 3 - With a maximum string length of just 3 characters, our ``VARCHAR(100)`` is way oversized. + With a maximum string length of just 3 characters, our ``TEXT(100)`` is way oversized. #. - We can recreate the table with a more restrictive ``VARCHAR(3)``, and can examine the difference in performance: + We can recreate the table with a more restrictive ``TEXT(3)``, and can examine the difference in performance: .. code-block:: psql t=> CREATE TABLE t_efficient . AS SELECT i, . amt, . ts, - . country_code::VARCHAR(3) AS country_code, + . country_code::TEXT(3) AS country_code, . flag . FROM t_inefficient; executed @@ -832,8 +832,8 @@ For example: Improving Sort Performance on Text Keys ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When using VARCHAR, ensure that the maximum length defined in the table structure is as small as necessary. -For example, if you're storing phone numbers, don't define the field as ``VARCHAR(255)``, as that affects sort performance. +When using TEXT, ensure that the maximum length defined in the table structure is as small as necessary. +For example, if you're storing phone numbers, don't define the field as ``TEXT(255)``, as that affects sort performance. You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))``), and potentially modify the table structure. diff --git a/operational_guides/seeing_system_objects_as_ddl.rst b/operational_guides/seeing_system_objects_as_ddl.rst index 4f9f596dd..2aacb49e8 100644 --- a/operational_guides/seeing_system_objects_as_ddl.rst +++ b/operational_guides/seeing_system_objects_as_ddl.rst @@ -22,7 +22,7 @@ Getting the DDL for a table farm=> SELECT GET_DDL('cool_animals'); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text(30) not null, "weight" double null, "is_agressive" bool default false not null ) ; @@ -142,7 +142,7 @@ Exporting database DDL to a client farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text(30) not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst index c99f4e7d1..94f8605f7 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_null.rst @@ -40,7 +40,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE t (id INT NOT NULL, name VARCHAR(30), weight INT); + CREATE TABLE t (id INT NOT NULL, name TEXT(30), weight INT); INSERT INTO t VALUES (1, 'Kangaroo', 120), (2, 'Koala', 20), (3, 'Wombat', 60) ,(4, 'Kappa', NULL),(5, 'Echidna', 8),(6, 'Chupacabra', NULL) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst index 92e3f7940..50bcf7410 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst @@ -48,7 +48,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst index 2fd79ca86..f0ca54a58 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst @@ -86,7 +86,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index fa9c89027..3ad4ca1f3 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -49,7 +49,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') @@ -73,4 +73,4 @@ Using ``CHARINDEX`` "Beware the Jabberwock, my son! | 9 The jaws that bite, the claws that catch! | 27 Beware the Jubjub bird, and shun | 8 - The frumious Bandersnatch!" | 0 + The frumious Bandersnatch!" | 0 \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst index 4a978b1ff..3da356969 100644 --- a/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst +++ b/reference/sql/sql_functions/scalar_functions/string/isprefixof.rst @@ -50,7 +50,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') diff --git a/reference/sql/sql_functions/scalar_functions/string/lower.rst b/reference/sql/sql_functions/scalar_functions/string/lower.rst index 69dfd4f1a..4318015dc 100644 --- a/reference/sql/sql_functions/scalar_functions/string/lower.rst +++ b/reference/sql/sql_functions/scalar_functions/string/lower.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_functions/scalar_functions/string/patindex.rst b/reference/sql/sql_functions/scalar_functions/string/patindex.rst index 063fe6d5c..b1ffcda9b 100644 --- a/reference/sql/sql_functions/scalar_functions/string/patindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/patindex.rst @@ -69,7 +69,7 @@ Notes * If the value is NULL, the result is NULL. -* PATINDEX works on ``VARCHAR`` text types only. +* PATINDEX works on ``TEXT`` text types only. * PATINDEX does not work on all literal values - only on column values. diff --git a/reference/sql/sql_functions/scalar_functions/string/trim.rst b/reference/sql/sql_functions/scalar_functions/string/trim.rst index d6e90c2f8..d249c8952 100644 --- a/reference/sql/sql_functions/scalar_functions/string/trim.rst +++ b/reference/sql/sql_functions/scalar_functions/string/trim.rst @@ -35,7 +35,7 @@ Returns the same type as the argument supplied. Notes ======= -* When using ``VARCHAR`` values, SQream DB automatically trims the trailing whitespace. +* When using ``TEXT`` values, SQream DB automatically trims the trailing whitespace. * This function is equivalent to the ANSI form ``TRIM( BOTH FROM expr )`` diff --git a/reference/sql/sql_functions/scalar_functions/string/upper.rst b/reference/sql/sql_functions/scalar_functions/string/upper.rst index 219bc854e..1f9cc1b96 100644 --- a/reference/sql/sql_functions/scalar_functions/string/upper.rst +++ b/reference/sql/sql_functions/scalar_functions/string/upper.rst @@ -45,7 +45,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE jabberwocky(line VARCHAR(50)); + CREATE TABLE jabberwocky(line TEXT(50)); INSERT INTO jabberwocky VALUES ('''Twas brillig, and the slithy toves'), (' Did gyre and gimble in the wabe:') diff --git a/reference/sql/sql_statements/ddl_commands/create_function.rst b/reference/sql/sql_statements/ddl_commands/create_function.rst index 339543a0a..a693fc897 100644 --- a/reference/sql/sql_statements/ddl_commands/create_function.rst +++ b/reference/sql/sql_statements/ddl_commands/create_function.rst @@ -52,7 +52,7 @@ Parameters * - ``argument_list`` - A comma separated list of column definitions. A column definition includes a name identifier and a datatype. * - ``return_type`` - - The SQL datatype of the return value, such as ``INT``, ``VARCHAR``, etc. + - The SQL datatype of the return value, such as ``INT``, ``TEXT``, etc. * - ``function_body`` - Python code, dollar-quoted (``$$``). diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index b660e442c..2689c6aca 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -141,7 +141,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -155,7 +155,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -171,8 +171,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name VARCHAR(30) NOT NULL, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + name TEXT(30) NOT NULL, + country TEXT(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -203,9 +203,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name TEXT(30) NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country TEXT(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. diff --git a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst b/reference/sql/sql_statements/monitoring_commands/show_node_info.rst index 345d16440..9c1e1ec11 100644 --- a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst +++ b/reference/sql/sql_statements/monitoring_commands/show_node_info.rst @@ -108,7 +108,7 @@ This is a full list of node types: - Compress data with both CPU and GPU schemes * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``VARCHAR`` types + - Decompression operation, common for longer ``TEXT`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst deleted file mode 100644 index f7faef6c5..000000000 --- a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst +++ /dev/null @@ -1,55 +0,0 @@ -.. _drop_saved_query: - -******************** -DROP_SAVED_QUERY -******************** - -``DROP_SAVED_QUERY`` drops a :ref:`previously saved query`. - -Read more in the :ref:`saved_queries` guide. - -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. - -Permissions -============= - -Dropping a saved query requires no special permissions. - -Syntax -========== - -.. code-block:: postgres - - drop_saved_query_statement ::= - SELECT DROP_SAVED_QUERY(saved_query_name) - ; - - saved_query_name ::= string_literal - -Returns -========== - -If saved query is dropped successfully, returns nothing. - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``saved_query_name`` - - The name of the query to drop - -Examples -=========== - -Dropping a previously saved query ---------------------------------------- - -.. code-block:: psql - - t=> SELECT DROP_SAVED_QUERY('select_all'); - executed diff --git a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst index bf246b803..fc9ca1282 100644 --- a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst @@ -51,7 +51,7 @@ Getting the DDL for a database farm=> SELECT DUMP_DATABASE_DDL(); create table "public"."cool_animals" ( "id" int not null, - "name" varchar(30) not null, + "name" text(30) not null, "weight" double null, "is_agressive" bool default false not null ) diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst deleted file mode 100644 index 9232a5162..000000000 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ /dev/null @@ -1,122 +0,0 @@ -.. _execute_saved_query: - -******************** -EXECUTE_SAVED_QUERY -******************** - -``EXECUTE_SAVED_QUERY`` executes a :ref:`previously saved query`. - -Read more in the :ref:`saved_queries` guide. - -See also: ref:`save_query`, :ref:`drop_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. - -Permissions -============= - -Executing a saved query requires ``SELECT`` permissions to access the tables referenced in the query. - -Syntax -========== - -.. code-block:: postgres - - execute_saved_query_statement ::= - SELECT EXECUTE_SAVED_QUERY(saved_query_name, [ , argument [ , ... ] ] ) - ; - - saved_query_name ::= string_literal - - argument ::= string_literal | number_literal - -Returns -========== - -Query execution results, based on the query saved. - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``saved_query_name`` - - The name of the query to execute - * - ``argument`` - - A comma separated list of argument literal values - - -Notes -========= - -* Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. - -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) - -* Query parameters' types are inferred at compile time. - -Examples -=========== - -Assume a table named ``nba``, with the following structure: - -.. code-block:: postgres - - CREATE TABLE nba - ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float - ); - - -Here's a peek at the table contents (:download:`Download nba.csv `): - -.. csv-table:: nba.csv - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - - -Saving and executing a simple query ---------------------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_all'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - [...] - -Saving and executing parametrized query ------------------------------------------- - -Use parameters to replace them later at execution time. - -.. tip:: Use dollar quoting (`$$`) to avoid escaping strings. - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- - Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 - James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 - Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst deleted file mode 100644 index bb1781840..000000000 --- a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _list_saved_queries: - -******************** -LIST_SAVED_QUERIES -******************** - -``LIST_SAVED_QUERIES`` lists the available :ref:`previously saved queries`. - -This is an alternative way to using the ``savedqueries`` catalog view. - -Read more in the :ref:`saved_queries` guide. - -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`show_saved_query`. - -Permissions -============= - -Listing the saved queries requires no special permissions. - -Syntax -========== - -.. code-block:: postgres - - list_saved_queries_statement ::= - SELECT LIST_SAVED_QUERIES() - ; - -Returns -========== - -List of saved query names, one per row. - -Parameters -============ - -None - -Notes -========= - -This statement returns an empty result set if no saved queries exist in the current database. - -Examples -=========== - -Listing previously saved queries ---------------------------------------- - -.. code-block:: psql - - t=> SELECT LIST_SAVED_QUERIES(); - saved_query - ------------------------- - select_all - select_by_weight - select_by_weight_and_team - - t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); - saved_query - ----------------------------------------------- - SELECT * FROM nba WHERE Weight > ? AND Team = ? - - -Listing saved queries with the catalog ---------------------------------------------- - -Using the :ref:`catalog` is also possible: - -.. code-block:: psql - - t=> SELECT * FROM sqream_catalog.savedqueries; - name | num_parameters - --------------------------+--------------- - select_all | 0 - select_by_weight | 1 - select_by_weight_and_team | 2 diff --git a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst deleted file mode 100644 index d6b63e30e..000000000 --- a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst +++ /dev/null @@ -1,88 +0,0 @@ -.. _recompile_saved_query: - -************************** -RECOMPILE_SAVED_QUERY -************************** - -``RECOMPILE_SAVED_QUERY`` recompiles a saved query that has been invalidated due to a schema change. - -Permissions -============= - -Recompiling a saved query requires no special permissions. - -Syntax -========== - -.. code-block:: postgres - - recompile_saved_query_statement ::= - SELECT RECOMPILE_SAVED_QUERY(saved_query_name) - ; - - saved_query_name ::= string_literal - -Returns -========== - -If saved query is recompiled successfully, returns nothing. - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``saved_query_name`` - - The name of the query to recompile - -Examples -=========== - -Recreating a query that has been invalidated -------------------------------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- - Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 - James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 - Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 - - -To invalidate the original saved query, we will change the schema without affecting our original query text: - -.. code-block:: psql - - t=> ALTER TABLE nba RENAME COLUMN age to "Age (as of 2015)"; - executed - -However, because the query was compiled previously, this change invalidates the query and causes it to fail: - -.. code-block:: psql - - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Error: column not found {Age@null} - column not found {Age@null} - -Recompiling the query will fix this issue - -.. code-block:: psql - - t=> SELECT RECOMPILE_SAVED_QUERY('select_by_weight_and_team'); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Name | Team | Number | Position | Age (as of 2015) | Height | Weight | College | Salary - ------------------+-----------------+--------+----------+------------------+--------+--------+-------------+-------- - Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 - James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 - Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index f71f6e025..c65cd48ba 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -56,7 +56,7 @@ Notes * Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) +* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) * Query parameters' types are inferred at compile time. diff --git a/reference/sql/sql_statements/utility_commands/show_saved_query.rst b/reference/sql/sql_statements/utility_commands/show_saved_query.rst deleted file mode 100644 index 15ac4c1bd..000000000 --- a/reference/sql/sql_statements/utility_commands/show_saved_query.rst +++ /dev/null @@ -1,61 +0,0 @@ -.. _show_saved_query: - -******************** -SHOW_SAVED_QUERY -******************** - -``SHOW_SAVED_QUERY`` shows the query text for a :ref:`previously saved query`. - -Read more in the :ref:`saved_queries` guide. - -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`list_saved_queries`. - -Permissions -============= - -Showing a saved query requires no special permissions. - -Syntax -========== - -.. code-block:: postgres - - show_saved_query_statement ::= - SELECT SHOW_SAVED_QUERY(saved_query_name) - ; - - saved_query_name ::= string_literal - -Returns -========== - -A single row result containing the saved query string. - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``saved_query_name`` - - The name of the query to show - - -Examples -=========== - -Showing a previously saved query ---------------------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); - saved_query - ----------------------------------------------- - SELECT * FROM nba WHERE Weight > ? AND Team = ? - diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 55369d761..72cbff97b 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -223,7 +223,7 @@ The following table describes the DDL Optimizer screen: * - Column area - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. * - Run Optimizer - Starts the optimization process. From 0f8a1b34deb2b9ba4150d81307b08cefd3d94b43 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 10 Apr 2022 13:26:15 +0300 Subject: [PATCH 0037/1892] Updated according to TPD-120 Updated according to https://sqream.atlassian.net/browse/TPD-120 (confirmed with Efrat). --- .../sql_syntax/keywords_and_identifiers.rst | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index e5d1a6fcf..bc2cb1de6 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -13,13 +13,13 @@ Regular identifiers must follow these rules: * Must be case-insensitive. SQream converts all identifiers to lowercase unless quoted. * Does not equal any keywords, such as ``SELECT``, ``OR``, or ``AND``, etc. -To bypass the rules above you can surround an identifier with double quotes (``"``). +To bypass the rules above you can surround an identifier with double quotes (``"``) or square brackets (``[]``). Quoted identifiers must follow these rules: -* Must be surrounded with double quotes (``"``). +* Must be surrounded with double quotes (``"``) or square brackets (``[]``). * May contain any ASCII character except ``@``, ``$`` or ``"``. -* Must be case-sensitive and referenced with double quotes. +* Must be case-sensitive and referenced with double quotes or square brackets (``[]``). Identifiers are different than **keywords**, which are predefined words reserved with specific meanings in a statement. Some examples of keywords are ``SELECT``, ``CREATE``, and ``WHERE``. Note that keywords **cannot** be used as identifiers. @@ -28,43 +28,45 @@ The following table shows a full list of the reserved keywords: +-------------------------------------------------------------------------------------------------+ | **Keywords** | +-------------------+---------------------+--------------------+------------------+---------------+ +| **A - C** | **C - G** | **H - N** | **N - S** | **S - W** | ++-------------------+---------------------+--------------------+------------------+---------------+ | ``ALL`` | ``CURRENT_CATALOG`` | ``HASH`` | ``NOT`` | ``SIMILAR`` | +-------------------+---------------------+--------------------+------------------+---------------+ | ``ANALYSE`` | ``CURRENT_ROLE`` | ``HAVING`` | ``NOTNULL`` | ``SOME`` | +-------------------+---------------------+--------------------+------------------+---------------+ | ``ANALYZE`` | ``CURRENT_TIME`` | ``ILIKE`` | ``NULL`` | ``SYMMETRIC`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``AND`` | ``CURRENT_USER`` | ``IN`` | ``OFFSET`` | ``SYMMETRIC`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ANY`` | ``DEFAULT`` | ``INITIALLY`` | ``ON`` | ``TABLE`` | +| ``AND`` | ``CURRENT_USER`` | ``IN`` | ``OFFSET`` | ``TABLE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``ARRAY`` | ``DEFERRABLE`` | ``INNER`` | ``ONLY`` | ``THEN`` | +| ``ANY`` | ``DEFAULT`` | ``INITIALLY`` | ``ON`` | ``THEN`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``AS`` | ``DESC`` | ``INTERSECT`` | ``OPTION`` | ``TO`` | +| ``ARRAY`` | ``DEFERRABLE`` | ``INNER`` | ``ONLY`` | ``TO`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRAILING`` | +| ``AS`` | ``DESC`` | ``INTERSECT`` | ``OPTION`` | ``TRAILING`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``TRUE`` | +| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRUE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNION`` | +| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``UNION`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``BOTH`` | ``END`` | ``JOIN`` | ``OVER`` | ``UNIQUE`` | +| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNIQUE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CASE`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USER`` | +| ``BOTH`` | ``END`` | ``JOIN`` | ``OVER`` | ``USER`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CAST`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``USING`` | +| ``CASE`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USING`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CHECK`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VARIADIC`` | +| ``CAST`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``VARIADIC`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLLATE`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``VERBOSE`` | +| ``CHECK`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VERBOSE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLUMN`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHEN`` | +| ``COLLATE`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``WHEN`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONCURRENTLY`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WHERE`` | +| ``COLUMN`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHERE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONSTRAINT`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WINDOW`` | +| ``CONCURRENTLY`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WINDOW`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CREATE`` | ``GRANT`` | ``MERGE`` | ``SELECT`` | ``WITH`` | -+-------------------+---------------------+--------------------+------------------+ | -| ``CROSS`` | ``GROUP`` | ``NATURAL`` | ``SESSION_USER`` | | +| ``CONSTRAINT`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WITH`` | ++-------------------+---------------------+--------------------+------------------+ | +| ``CREATE`` | ``GRANT`` | ``MERGE`` | ``SELECT`` | | ++-------------------+---------------------+--------------------+------------------+ | +| ``CROSS`` | ``GROUP`` | ``NATURAL`` | ``SESSION_USER`` | | +-------------------+---------------------+--------------------+------------------+---------------+ From 5c703a7a07a97efc6a0b3e5edb07c70511ee986c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Apr 2022 17:11:10 +0300 Subject: [PATCH 0038/1892] Published Key Evaluation to Private Branch --- feature_guides/index.rst | 6 +- feature_guides/key_evaluation.rst | 13 ++++ .../key_evaluation_operational_modes.rst | 70 +++++++++++++++++++ feature_guides/key_evaluation_overview.rst | 16 +++++ 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 feature_guides/key_evaluation.rst create mode 100644 feature_guides/key_evaluation_operational_modes.rst create mode 100644 feature_guides/key_evaluation_overview.rst diff --git a/feature_guides/index.rst b/feature_guides/index.rst index ee10e3ea4..2ba36198d 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -5,18 +5,18 @@ Feature Guides *********************** The **Feature Guides** section describes background processes that SQream uses to manage several areas of operation, such as data ingestion, load balancing, and access control. -This section describes the following features: +This section describes the following features: .. toctree:: :maxdepth: 1 - :titlesonly: + :titlesonly: delete_guide + key_evaluation data_encryption compression flexible_data_clustering python_functions - viewing_system_objects_as_ddl workload_manager transactions concurrency_and_locks diff --git a/feature_guides/key_evaluation.rst b/feature_guides/key_evaluation.rst new file mode 100644 index 000000000..e016e68c7 --- /dev/null +++ b/feature_guides/key_evaluation.rst @@ -0,0 +1,13 @@ +.. _key_evaluation: + +************************** +Key Evaluation +************************** +The **Key Evaluation** section describes the following: + +.. toctree:: + :maxdepth: 4 + :titlesonly: + + key_evaluation_overview + key_evaluation_operational_modes \ No newline at end of file diff --git a/feature_guides/key_evaluation_operational_modes.rst b/feature_guides/key_evaluation_operational_modes.rst new file mode 100644 index 000000000..feb4fd9c1 --- /dev/null +++ b/feature_guides/key_evaluation_operational_modes.rst @@ -0,0 +1,70 @@ +.. _key_evaluation_operational_modes: + +************************** +Operational Modes +************************** +Key Evaluation can be used to do one of the following: + +**Comment** - *Do users initiate one of these modes, or do they occur in the background on their own? The answer to this question determines whether key evaluation belongs in Feature Guides or Operational Guides.* + +.. contents:: + :local: + :depth: 1 + +View All Problematic Chunk Keys +---------- +You can use the **View** mode to find all problematic keys in the database for all databases and/or tables. + +The following shows the View command options: + +.. code-block:: + + $ select  keys_evaluate ('view'); + +.. code-block:: + + $ select  keys_evaluate ('view', 'master'); + +.. code-block:: + + $ select  keys_evaluate ('view', 'master', 'public.tbl'); + +Find and Clean Problematic Keys from Storage +---------- +You can use the **Clean Storage** mode to find all problematic keys located in the Storage for all databases. + +The following shows the Clean Storage command: + +.. code-block:: + + $ select  keys_evaluate ('clean_storage'); + +.. note:: This mode backs up the levelDB to the **backup** folder in the cluster before finding and cleaning problematic keys from your storage. + +Find and Clean Problematic Keys from a Database +---------- +You can use the **Clean Database** mode to find and clean all problematic keys located for a specific database and/or table. + +The following shows the Clean Database command options: + +.. code-block:: + + $ select keys_evaluate ('clean_database','master'); + +.. code-block:: + + $ select keys_evaluate ('clean_database','master', 'public.tbl'); + +.. note:: This mode backs up the levelDB to the **backup** folder in the cluster before finding and cleaning problematic keys from your database. + +Clean Specifically Defined Chunk Keys +---------- +**Comment** - *Currently not supported. Remove until further notice?* + +You can use the **Clean Chunk Key** mode to clean a specific problematic chunk key. **Comment** - *Note: data_diag vs keys_evaluate.* + +The following shows the Clean Chunk Key command options: + +.. code-block:: + + $ select data_diag (12, ''); \ No newline at end of file diff --git a/feature_guides/key_evaluation_overview.rst b/feature_guides/key_evaluation_overview.rst new file mode 100644 index 000000000..50e3f3eab --- /dev/null +++ b/feature_guides/key_evaluation_overview.rst @@ -0,0 +1,16 @@ +.. _key_evaluation_overview: + +************************** +Overview +************************** +The **Key Evaluation** feature resolves conflicts caused by ingesting and deleting data at the same time. Although this rarely occurs, it causes the leveldb to restore keys pointing to deleted data. In turn, this causes SQream metadata to search for deleted files. + +An indication that this conflict has occurred is SQream's inability to retrieve deleted data pointers, generating the type of error shown below: + +.. code-block:: console + + $ Internal Runtime Error *** Error opening [errno 2 No such file or directory] file name /mnt/disk1/sqream_cluster/databases/******/tables/289/17/17-391270 + +In addition, key evaluation prevents the database from creating phantom keys, which are duplicate chunk keys generated when data is ingested. Under normal circumstances ingesting data creates incrementing chunk keys. + +**Comment** - *Please confirm the reason I provided based on my understanding of the source doc.* \ No newline at end of file From e71871a44a4048c4a7e79be3a8866cba328c524d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Apr 2022 17:33:39 +0300 Subject: [PATCH 0039/1892] Corrected syntax --- feature_guides/key_evaluation_overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/key_evaluation_overview.rst b/feature_guides/key_evaluation_overview.rst index 50e3f3eab..3d3aabf8a 100644 --- a/feature_guides/key_evaluation_overview.rst +++ b/feature_guides/key_evaluation_overview.rst @@ -9,7 +9,7 @@ An indication that this conflict has occurred is SQream's inability to retrieve .. code-block:: console - $ Internal Runtime Error *** Error opening [errno 2 No such file or directory] file name /mnt/disk1/sqream_cluster/databases/******/tables/289/17/17-391270 + Internal Runtime Error *** Error opening [errno 2 No such file or directory] file name /mnt/disk1/sqream_cluster/databases/******/tables/289/17/17-391270 In addition, key evaluation prevents the database from creating phantom keys, which are duplicate chunk keys generated when data is ingested. Under normal circumstances ingesting data creates incrementing chunk keys. From d349955969ba341c2a2a6699e2f4916362245f59 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 12 Apr 2022 11:05:55 +0300 Subject: [PATCH 0040/1892] Updated Taco File Link --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index 102827f22..d52b41e95 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -24,7 +24,7 @@ The following are applicable to all operating systems: * **Tableau**: - * `Tableau connector `_ - SQream (.taco) + * `https://sq-ftp-public.s3.amazonaws.com/SQreamTaco.rar>`_ - SQream (.taco) * `Tableau manual installation `_ From 8645e71f82ad5833ab256eaa84bed7a4cfa63014 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Apr 2022 11:30:41 +0300 Subject: [PATCH 0041/1892] Added Installing NGINX Proxy Over Secure Connection Private branch - I added this file to this branch to show it to Dor before publishing it on live branches. --- ...ing_nginx_proxy_over_secure_connection.rst | 427 ++++++++++++++++++ .../sqream_studio_installation.rst | 3 +- 2 files changed, 429 insertions(+), 1 deletion(-) create mode 100644 installation_guides/installing_nginx_proxy_over_secure_connection.rst diff --git a/installation_guides/installing_nginx_proxy_over_secure_connection.rst b/installation_guides/installing_nginx_proxy_over_secure_connection.rst new file mode 100644 index 000000000..4596f109e --- /dev/null +++ b/installation_guides/installing_nginx_proxy_over_secure_connection.rst @@ -0,0 +1,427 @@ +.. _installing_nginx_proxy_over_secure_connection: + +************************* +Installing an NGINX Proxy Over a Secure Connection +************************* +Configuring your NGINX server to use a strong encryption for client connections provides you with secure servers requests, preventing outside parties from gaining access to your traffic. + +The **Installing an NGINX Proxy Over a Secure Connection** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +============== +The Node.js platform that SQream uses with our Studio user interface is susceptible to web exposure. This page describes how to implement HTTPS access on your proxy server to establish a secure connection. + +**TLS (Transport Layer Security)**, and its predecessor **SSL (Secure Sockets Layer)**, are standard web protocols used for wrapping normal traffic in a protected, encrypted wrapper. This technology prevents the interception of server-client traffic. It also uses a certificate system for helping users verify the identity of sites they visit. The **Installing an NGINX Proxy Over a Secure Connection** guide describes how to set up a self-signed SSL certificate for use with an NGINX web server on a CentOS 7 server. + +.. note:: A self-signed certificate encrypts communication between your server and any clients. However, because it is not signed by trusted certificate authorities included with web browsers, you cannot use the certificate to automatically validate the identity of your server. + +A self-signed certificate may be appropriate if your domain name is not associated with your server, and in cases where your encrypted web interface is not user-facing. If you do have a domain name, using a CA-signed certificate is generally preferrable. + +For more information on setting up a free trusted certificate, see `How To Secure Nginx with Let's Encrypt on CentOS 7 `_. + +Prerequisites +============== +The following prerequisites are required for installing an NGINX proxy over a secure connection: + +* Super user privileges + + :: + +* A domain name to create a certificate for + +Installing NGINX and Adjusting the Firewall +============== +After verifying that you have the above preriquisites, you must verify that the NGINX web server has been installed on your machine. + +Though NGINX is not available in the default CentOS repositories, it is available from the **EPEL (Extra Packages for Enterprise Linux)** repository. + +**To install NGINX and adjust the firewall:** + +1. Enable the EPEL repository to enable server access to the NGINX package: + + .. code-block:: console + + $ sudo yum install epel-release + +2. Install NGINX: + + .. code-block:: console + + $ sudo yum install nginx + +3. Start the NGINX service: + + .. code-block:: console + + $ sudo systemctl start nginx + +4. Verify that the service is running: + + .. code-block:: console + + $ systemctl status nginx + + The following is an example of the correct output: + + .. code-block:: console + + Output● nginx.service - The nginx HTTP and reverse proxy server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) + Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago + + . . . + + Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. + +5. Enable NGINX to start when your server boots up: + + .. code-block:: console + + $ sudo systemctl enable nginx + +6. Verify that access to **ports 80 and 443** are not blocked by a firewall. + + :: + +7. Do one of the following: + + * If you are not using a firewall, skip to :ref:`Creating Your SSL Certificate`. + + :: + + * If you have a running firewall, open ports 80 and 443: + + .. code-block:: console + + $ sudo firewall-cmd --add-service=http + $ sudo firewall-cmd --add-service=https + $ sudo firewall-cmd --runtime-to-permanent + +8. If have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: + + .. code-block:: console + + $ sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT + $ sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT + +**Comment** - *Is Step 8 above optional?* + + .. note:: The commands in Step 8 above are highly dependent on your current rule set. + +9. Verify that you can access the default NGINX page from a web browser. + +.. _creating_your_ssl_certificate: + +Creating Your SSL Certificate +============== +After installing NGINX and adjusting your firewall, you must create your SSL certificate. + +TLS/SSL **Comment** - *Why mention "TLS" if we are only speaking about SSL?)* combines public certificates with private keys. The SSL key, kept private on your server, is used to encrypt content sent to clients, while the SSL certificate is publicly shared with anyone requesting content. In addition, the SSL certificate can be used to decrypt the content signed by the associated SSL key. Your public certificate is located in the **/etc/ssl/certs** directory on your server. + +This section describes how to create your **/etc/ssl/private directory**, used for storing your private key file. Because the privacy of this key is essential for security, the permissions must be locked down **(Comment** - *Disabled?*) to prevent unauthorized access: + +**To create your SSL certificate:** + +1. Set the following permissions to **private**: + + .. code-block:: console + + $ sudo mkdir /etc/ssl/private + $ sudo chmod 700 /etc/ssl/private + +2. Create a self-signed key and certificate pair with OpenSSL in a single command: + + .. code-block:: console + + $ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt + + The following list describes the elements in the command above: + + * **openssl** - The basic command line tool used for creating and managing OpenSSL certificates, keys, and other files. + + :: + + * **req** - A subcommand for using the X.509 **Certificate Signing Request (CSR)** management. A public key infrastructure standard, SSL and TLS adhere X.509 key and certificate management regulations. + + :: + + * **-x509** - Used for modifying the previous subcommand by overriding the default functionality of generating a certificate signing request with making a self-signed certificate. + + :: + + * **-nodes** - Sets **OpenSSL** to skip the option of securing our certificate with a passphrase, letting NGINX read the file without user intervention when the server is activated. If you don't use **-nodes** you must enter your passphrase after every restart. + + :: + + * **-days 365** - Sets the certificate's validation duration to one year. + + :: + + * **-newkey rsa:2048** - Simultaneously generates a new certificate and new key. Because the key required to sign the certificate was not created in the previous step **(Comment** - *Step 1?*), it must be created along with the certificate. The **rsa:2048** generates an RSA 2048 bits long. + + :: + + * **-keyout** - Determines the location of the generated private key file. + + :: + + * **-out** - Determines the location of the certificate. + + After creating a self-signed key and certificate pair with OpenSSL, a series of prompts about your server is presented (**Comment** - *By SSL?*) to correctly embed the information you provided in the certificate. + +**Comment** - *Dor, please confirm that the sentence above is correct.* + +3. Provide the information requested by the prompts. + + The most important piece of information is the **Common Name**, which is either the server **FQDN** or **your** name. You must enter the domain name associated with your server or your server’s public IP address. + + The following is an example of a filled out set of prompts: + + .. code-block:: console + + OutputCountry Name (2 letter code) [AU]:US + State or Province Name (full name) [Some-State]:New York + Locality Name (eg, city) []:New York City + Organization Name (eg, company) [Internet Widgits Pty Ltd]:Bouncy Castles, Inc. + Organizational Unit Name (eg, section) []:Ministry of Water Slides + Common Name (e.g. server FQDN or YOUR name) []:server_IP_address + Email Address []:admin@your_domain.com + + Both files you create are stored in their own subdirectories of the **/etc/ssl** directory. + + While (**Comment** - *"Although" instead of "while"?*) SQream uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. + + **Comment** - *Please explain what you meant by "negotiating".* + +4. Create a strong Diffie-Hellman group: + + .. code-block:: console + + $ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 + + Creating a Diffie-Hellman group takes a few minutes, which is stored as the **dhparam.pem** file in the **/etc/ssl/certs** directory. This file can use in the configuration. + + **Comment** - *Please explain what you meant by that it can be used in the configuration.* + +Configuring NGINX to use SSL +============== +After creating your SSL certificate, you must configure NGINX to use SSL. + +The default CentOS NGINX configuration is fairly unstructured, (**Comment** - *What is the intent of "unstructured"?) with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. (**Comment** - *What did you mean by "additional configuration"? How does this work?*) + +SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a server block. This block serves content using the certificate files we generated. In addition, the default server block can be optionally configured to redirect HTTP requests to HTTPS. + +.. note:: The example on this page uses the IP address **127.0.0.1**, which you should replace with your machine's IP address. + +**To configure NGINX to use SSL:** + +1. Create and open a file called **ssl.conf** in the **/etc/nginx/conf.d** directory: + + .. code-block:: console + + $ sudo vi /etc/nginx/conf.d/ssl.conf + +2. Inside, (**Comment** - *In the directory?*) open a server block: + + 1. Listen to **port 443**, which is the TLS/SSL default port. + + :: + + 2. Set the ``server_name`` to the server’s domain name or IP address you used as the Common Name when generating your certificate. + + :: + + 3. Use the ``ssl_certificate``, ``ssl_certificate_key``, and ``ssl_dhparam`` directives to set the location of the SSL files you generated, as shown in the **/etc/nginx/conf.d/ssl.conf** file below: + + **Comment** - *Please confirm Step 3 above.* + + .. code-block:: console + + upstream ui { + server 127.0.0.1:8080; + } + server { + listen 443 http2 ssl; + listen [::]:443 http2 ssl; + + server_name nginx.sq.l; + + ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt; + ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key; + ssl_dhparam /etc/ssl/certs/dhparam.pem; + + root /usr/share/nginx/html; + + # location / { + # } + + location / { + proxy_pass http://ui; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header Host $host; + add_header Front-End-Https on; + add_header X-Cache-Status $upstream_cache_status; + proxy_cache off; + proxy_cache_revalidate off; + proxy_cache_min_uses 1; + proxy_cache_valid 200 302 1h; + proxy_cache_valid 404 3s; + proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; + proxy_no_cache $cookie_nocache $arg_nocache $arg_comment $http_pragma $http_authorization; + proxy_redirect default; + proxy_max_temp_file_size 0; + proxy_connect_timeout 90; + proxy_send_timeout 90; + proxy_read_timeout 90; + proxy_buffer_size 4k; + proxy_buffering on; + proxy_buffers 4 32k; + proxy_busy_buffers_size 64k; + proxy_temp_file_write_size 64k; + proxy_intercept_errors on; + + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + error_page 404 /404.html; + location = /404.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } + +4. Open and modify the **nginx.conf** file located in the **/etc/nginx/conf.d** directory as follows: + + .. code-block:: console + + $ sudo vi /etc/nginx/conf.d/nginx.conf + +**Comment** - *Why is this here (below)?* + +**/etc/nginx/nginx.conf** + + .. code-block:: console + + server { + listen 80; + listen [::]:80; + server_name _; + root /usr/share/nginx/html; + + # Load configuration files for the default server block. + include /etc/nginx/default.d/*.conf; + + error_page 404 /404.html; + location = /404.html { + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + } + } + +Redirecting Studio Access from HTTP to HTTPS +================== +After configuring NGINX to use SSL, you must redirect Studio access from HTTP to HTTPS. + +According to your current configuration, NGINX responds with encrypted content for requests on port 443, but with **unencrypted** content for requests on **port 80**. This means that our site offers encryption, but does not enforce its usage. This may be fine for some use cases, but it is usually better to require encryption. This is especially important when confidential data like passwords may be transferred between the browser and the server. + +Thankfully, the default Nginx configuration file allows us to easily add directives to the default port 80 server block by adding files in the /etc/nginx/default.d directory. + +**Comment** - *We need to discuss the paragraphs above together.* + +**To create a redirect from HTTP to HTTPS:** + +1. Create a new file called **ssl-redirect.conf** and open it for editing: + + .. code-block:: console + + $ sudo vi /etc/nginx/default.d/ssl-redirect.conf + +2. Copy and paste this line: + + .. code-block:: console + + $ /etc/nginx/default.d/ssl-redirect.conf + + $ return 301 https://$host$request_uri:8080/; + + **Comment** - *Confirm the above.* + +Enabling the Changes in NGINX +============== +**Comment** - *I suggest using "Activating" instead of "Enabling".* + +After redirecting from HTTP to HTTPs, you must restart NGINX to activate your new configuration. + +**To activate your NGINX configuration:** + +1. Verify that your files contain no syntax errors: + + .. code-block:: console + + $ sudo nginx -t + + The following output is generated if your files contain no syntax errors: + + .. code-block:: console + + nginx: the configuration file /etc/nginx/nginx.conf syntax is ok + nginx: configuration file /etc/nginx/nginx.conf test is successful + +2. Restart NGINX to activate your configuration: + + **Comment** - *We need to tell them what to do if they do have syntax errors, i.e., to correct their syntax errors. If it is not obvious how to do this, we should tell them how.* + + .. code-block:: console + + $ sudo systemctl restart nginx + +Verifying that NGINX is Running +============== +After activating your NGINX configuration, you must verify that NGINX is running correctly. + +**To verify that NGINX is running correctly:** + +1. Check that the service is up and running: + + .. code-block:: console + + $ systemctl status nginx + + The following is an example of the correct output: + + .. code-block:: console + + Output● nginx.service - The nginx HTTP and reverse proxy server + Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) + Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago + + . . . + + Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. + +2. Run the following command: + + .. code-block:: console + + $ sudo netstat -nltp |grep nginx + + The following is an example of the correct output: + + .. code-block:: console + + [sqream@dorb-pc etc]$ sudo netstat -nltp |grep nginx + tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 15486/nginx: master + tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 15486/nginx: master + tcp6 0 0 :::80 :::* LISTEN 15486/nginx: master + tcp6 0 0 :::443 :::* LISTEN 15486/nginx: master \ No newline at end of file diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 8646a35ad..53c89772d 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -12,4 +12,5 @@ The **Installing SQream Studio** page incudes the following installation guides: installing_prometheus_exporters installing_prometheus_using_binary_packages installing_dashboard_data_collector - installing_studio_on_stand_alone_server \ No newline at end of file + installing_studio_on_stand_alone_server + installing_nginx_proxy_over_secure_connection \ No newline at end of file From c0fb6c5939d61cd93e75f704f3fc6f28d5e761cf Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Apr 2022 17:43:05 +0300 Subject: [PATCH 0042/1892] Published Removed all remaining comments and published. --- ...ing_nginx_proxy_over_secure_connection.rst | 48 +++++-------------- 1 file changed, 12 insertions(+), 36 deletions(-) diff --git a/installation_guides/installing_nginx_proxy_over_secure_connection.rst b/installation_guides/installing_nginx_proxy_over_secure_connection.rst index 4596f109e..5aef5eaff 100644 --- a/installation_guides/installing_nginx_proxy_over_secure_connection.rst +++ b/installation_guides/installing_nginx_proxy_over_secure_connection.rst @@ -101,15 +101,13 @@ Though NGINX is not available in the default CentOS repositories, it is availabl $ sudo firewall-cmd --add-service=https $ sudo firewall-cmd --runtime-to-permanent -8. If have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: +8. If you have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: .. code-block:: console $ sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT $ sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT -**Comment** - *Is Step 8 above optional?* - .. note:: The commands in Step 8 above are highly dependent on your current rule set. 9. Verify that you can access the default NGINX page from a web browser. @@ -120,9 +118,9 @@ Creating Your SSL Certificate ============== After installing NGINX and adjusting your firewall, you must create your SSL certificate. -TLS/SSL **Comment** - *Why mention "TLS" if we are only speaking about SSL?)* combines public certificates with private keys. The SSL key, kept private on your server, is used to encrypt content sent to clients, while the SSL certificate is publicly shared with anyone requesting content. In addition, the SSL certificate can be used to decrypt the content signed by the associated SSL key. Your public certificate is located in the **/etc/ssl/certs** directory on your server. +TLS/SSL combines public certificates with private keys. The SSL key, kept private on your server, is used to encrypt content sent to clients, while the SSL certificate is publicly shared with anyone requesting content. In addition, the SSL certificate can be used to decrypt the content signed by the associated SSL key. Your public certificate is located in the **/etc/ssl/certs** directory on your server. -This section describes how to create your **/etc/ssl/private directory**, used for storing your private key file. Because the privacy of this key is essential for security, the permissions must be locked down **(Comment** - *Disabled?*) to prevent unauthorized access: +This section describes how to create your **/etc/ssl/private directory**, used for storing your private key file. Because the privacy of this key is essential for security, the permissions must be locked down to prevent unauthorized access: **To create your SSL certificate:** @@ -133,7 +131,7 @@ This section describes how to create your **/etc/ssl/private directory**, used f $ sudo mkdir /etc/ssl/private $ sudo chmod 700 /etc/ssl/private -2. Create a self-signed key and certificate pair with OpenSSL in a single command: +2. Create a self-signed key and certificate pair with OpenSSL with the following command: .. code-block:: console @@ -161,7 +159,7 @@ This section describes how to create your **/etc/ssl/private directory**, used f :: - * **-newkey rsa:2048** - Simultaneously generates a new certificate and new key. Because the key required to sign the certificate was not created in the previous step **(Comment** - *Step 1?*), it must be created along with the certificate. The **rsa:2048** generates an RSA 2048 bits long. + * **-newkey rsa:2048** - Simultaneously generates a new certificate and new key. Because the key required to sign the certificate was not created in the previous step, it must be created along with the certificate. The **rsa:2048** generates an RSA 2048 bits long. :: @@ -171,9 +169,7 @@ This section describes how to create your **/etc/ssl/private directory**, used f * **-out** - Determines the location of the certificate. - After creating a self-signed key and certificate pair with OpenSSL, a series of prompts about your server is presented (**Comment** - *By SSL?*) to correctly embed the information you provided in the certificate. - -**Comment** - *Dor, please confirm that the sentence above is correct.* + After creating a self-signed key and certificate pair with OpenSSL, a series of prompts about your server is presented to correctly embed the information you provided in the certificate. 3. Provide the information requested by the prompts. @@ -193,9 +189,7 @@ This section describes how to create your **/etc/ssl/private directory**, used f Both files you create are stored in their own subdirectories of the **/etc/ssl** directory. - While (**Comment** - *"Although" instead of "while"?*) SQream uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. - - **Comment** - *Please explain what you meant by "negotiating".* + Although SQream uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. 4. Create a strong Diffie-Hellman group: @@ -205,13 +199,11 @@ This section describes how to create your **/etc/ssl/private directory**, used f Creating a Diffie-Hellman group takes a few minutes, which is stored as the **dhparam.pem** file in the **/etc/ssl/certs** directory. This file can use in the configuration. - **Comment** - *Please explain what you meant by that it can be used in the configuration.* - Configuring NGINX to use SSL ============== After creating your SSL certificate, you must configure NGINX to use SSL. -The default CentOS NGINX configuration is fairly unstructured, (**Comment** - *What is the intent of "unstructured"?) with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. (**Comment** - *What did you mean by "additional configuration"? How does this work?*) +The default CentOS NGINX configuration is fairly unstructured, with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a server block. This block serves content using the certificate files we generated. In addition, the default server block can be optionally configured to redirect HTTP requests to HTTPS. @@ -225,7 +217,7 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a $ sudo vi /etc/nginx/conf.d/ssl.conf -2. Inside, (**Comment** - *In the directory?*) open a server block: +2. In the file you created in Step 1 above, open a server block: 1. Listen to **port 443**, which is the TLS/SSL default port. @@ -237,8 +229,6 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a 3. Use the ``ssl_certificate``, ``ssl_certificate_key``, and ``ssl_dhparam`` directives to set the location of the SSL files you generated, as shown in the **/etc/nginx/conf.d/ssl.conf** file below: - **Comment** - *Please confirm Step 3 above.* - .. code-block:: console upstream ui { @@ -304,11 +294,7 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a .. code-block:: console $ sudo vi /etc/nginx/conf.d/nginx.conf - -**Comment** - *Why is this here (below)?* - -**/etc/nginx/nginx.conf** - + .. code-block:: console server { @@ -335,9 +321,7 @@ After configuring NGINX to use SSL, you must redirect Studio access from HTTP to According to your current configuration, NGINX responds with encrypted content for requests on port 443, but with **unencrypted** content for requests on **port 80**. This means that our site offers encryption, but does not enforce its usage. This may be fine for some use cases, but it is usually better to require encryption. This is especially important when confidential data like passwords may be transferred between the browser and the server. -Thankfully, the default Nginx configuration file allows us to easily add directives to the default port 80 server block by adding files in the /etc/nginx/default.d directory. - -**Comment** - *We need to discuss the paragraphs above together.* +The default NGINX configuration file allows us to easily add directives to the default port 80 server block by adding files in the /etc/nginx/default.d directory. **To create a redirect from HTTP to HTTPS:** @@ -351,16 +335,10 @@ Thankfully, the default Nginx configuration file allows us to easily add directi .. code-block:: console - $ /etc/nginx/default.d/ssl-redirect.conf - $ return 301 https://$host$request_uri:8080/; - **Comment** - *Confirm the above.* - -Enabling the Changes in NGINX +Activating Your NGINX Configuration ============== -**Comment** - *I suggest using "Activating" instead of "Enabling".* - After redirecting from HTTP to HTTPs, you must restart NGINX to activate your new configuration. **To activate your NGINX configuration:** @@ -380,8 +358,6 @@ After redirecting from HTTP to HTTPs, you must restart NGINX to activate your ne 2. Restart NGINX to activate your configuration: - **Comment** - *We need to tell them what to do if they do have syntax errors, i.e., to correct their syntax errors. If it is not obvious how to do this, we should tell them how.* - .. code-block:: console $ sudo systemctl restart nginx From 0a3b758916c1f37d7288b37f3abf8558ae5e9195 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 10:45:19 +0300 Subject: [PATCH 0043/1892] Update installing_studio_on_stand_alone_server.rst Added lines 159-192 based on discussion with Slavi and Dor. --- ...nstalling_studio_on_stand_alone_server.rst | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 874adba8d..ecec67c7f 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -5,8 +5,6 @@ *********************** Installing Studio on a Stand-Alone Server *********************** - - The **Installing Studio on a Stand-Alone Server** guide describes how to install SQream Studio on a stand-alone server. A stand-alone server is a server that does not run SQream based on binary files, Docker, or Kubernetes. The Installing Studio on a Stand-Alone Server guide includes the following sections: @@ -147,7 +145,7 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ npm run setup -- -y --host= --port=3108 + $ npm run setup -- -y --host= --port=3108 --data-collector-url=http://:8100/api/dashboard/data The above command creates the **sqream-admin-config.json** configuration file in the **sqream-admin** folder and shows the following output: @@ -158,6 +156,40 @@ After installing the Dashboard Data Collector, you can install Studio. For more information about the available set-up arguments, see :ref:`Set-Up Arguments`. :: + +5. To access Studio over a secure connection, in your configuration file do the following: + + #. Change your ``port`` value to **3109**. + + :: + + #. Change your ``ssl`` flag value to **true**. + + The following is an example of the correctly modified configuration file: + + .. code-block:: console + + { + "debugSqream": false, + "webHost": "localhost", + "webPort": 8080, + "webSslPort": 8443, + "logsDirectory": "", + "clusterType": "standalone", + "dataCollectorUrl": "", + "connections": [ + { + "host": "127.0.0.1", + "port":3109, + "isCluster": true, + "name": "default", + "service": "sqream", + "ssl":true, + "networkTimeout": 60000, + "connectionTimeout": 3000 + } + ] + } 5. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: @@ -575,4 +607,4 @@ Back to :ref:`Installing Studio in a Docker Container` +Back to :ref:`Installing Studio on a Stand-Alone Server` \ No newline at end of file From f0220f55206229027444bcfbfc82f953d417b99b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 13:41:20 +0300 Subject: [PATCH 0044/1892] Update data_encryption_permissions.rst --- .../data_encryption_permissions.rst | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst index 16f41dc70..d7c655ad5 100644 --- a/feature_guides/data_encryption_permissions.rst +++ b/feature_guides/data_encryption_permissions.rst @@ -3,18 +3,14 @@ *********************** Permissions *********************** -Users with the appropriate encryption permission privilege's can encrypt and decrypt data. +The **Permissions** tells you how to create a table with encrypted columns as a superuser. -**Comment** - *The rest of this content seems internal, correct?* +Users with the appropriate encryption permission privilege's can encrypt and decrypt data. In addition, only superusers granted permission can view encrypted tables in the **sqream_catalog**. -Implementation notes +You can create a table with encrypted columns as a superuser as follows: -one method to encrypt the data with is the TDE: Transparent data encryption which employed by Microsoft/IBM/Oracle etc. - -management. The requirement is that this will be programmatic via API. - -The centralized key management store should be one of the following (R&D to choose which one in accordance to easiness of deployment): - -KMS (AWS)- https://aws.amazon.com/kms/ - -IBM- IBM Security Guardium Key Lifecycle Manager - Overview \ No newline at end of file +.. code-block:: console + + $ create or replace table t_enc(c1 int encrypt); + +For more information about the SQream catalog, see the :ref:`catalog_reference`. \ No newline at end of file From 2e37e000af4f732b2cb3da95c37e34e852a8cddc Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 14:14:45 +0300 Subject: [PATCH 0045/1892] Update data_encryption_permissions.rst Added missing word. --- feature_guides/data_encryption_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst index d7c655ad5..d9a132b45 100644 --- a/feature_guides/data_encryption_permissions.rst +++ b/feature_guides/data_encryption_permissions.rst @@ -3,7 +3,7 @@ *********************** Permissions *********************** -The **Permissions** tells you how to create a table with encrypted columns as a superuser. +The **Permissions** page tells you how to create a table with encrypted columns as a superuser. Users with the appropriate encryption permission privilege's can encrypt and decrypt data. In addition, only superusers granted permission can view encrypted tables in the **sqream_catalog**. From 3ef220402188cbb4c03debd4becb8d28ee133b75 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 17:41:53 +0300 Subject: [PATCH 0046/1892] Added DECODE Function --- reference/sql/sql_functions/index.rst | 6 +-- .../scalar_functions/string/decode.rst | 47 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) create mode 100644 reference/sql/sql_functions/scalar_functions/string/decode.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 46d643308..395cdfd59 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -223,6 +223,8 @@ The following table shows the **string* functions: - Calculates the position where a string starts inside another string * - :ref:`concat` - Concatenates two strings + * - :ref:`decode` + - Decodes or extracts binary data from a textual input string * - :ref:`isprefixof` - Matches if a string is the prefix of another string * - :ref:`left` @@ -416,6 +418,4 @@ The following table shows the **workload management** functions: user_defined_functions/index aggregate_functions/index window_functions/index - system_functions/index - - + system_functions/index \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst new file mode 100644 index 000000000..1ed10e399 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -0,0 +1,47 @@ +.. _decode: + +******************** +DECODE +******************** +The **DECODE** function is a PostgreSQL function used for decoding or extracting binary data from a textual input string. + +Syntax +========== +The following shows the correct syntax for the DECODE function: + +.. code-block:: postgres + + decode(string input_text, format type_text) + +Parameters +============ +The following table shows the DECODE parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``input_text`` + - Defines the input text string. + * - ``type_text`` + - Defines the format used for decoding the input text. + +Returns +========= +**Comment** - *What does it return?* + +Notes +=========== +**Comment** - *Are there any relevant notes?* + +Examples +=========== +**Comment** - *What does the actual output look like? Can you provide an example?* + +Permissions +============= +**Comment** - *Please confirm what permissions the role requires.* + +The role must have the ``SUPERUSER`` permissions. \ No newline at end of file From a9de45732ef39b5cc7f93e9efb715dfbc6268f9b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 17:47:59 +0300 Subject: [PATCH 0047/1892] Update index.rst Added DECODE --- reference/sql/sql_functions/scalar_functions/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index bd05f9bbe..ae70874e3 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -17,6 +17,7 @@ The **Built-In Scalar Functions** page describes functions that return one value * :ref:`between` * :ref:`case` * :ref:`coalesce` + * :ref:`decode` * :ref:`in` * :ref:`is_ascii` * :ref:`is_null` From b2ea112fa7386044871feb78dfc1ae2f1a245560 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 17 Apr 2022 18:16:47 +0300 Subject: [PATCH 0048/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index ae0139607..eab8d8f84 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -100,6 +100,8 @@ Utility Commands * - Command - Usage + * - :ref:`EXPLAIN` + - Returns a static query plan, which can be used to debug query plans * - :ref:`SELECT GET_LICENSE_INFO` - View a user's license information * - :ref:`SELECT GET_DDL` @@ -112,7 +114,18 @@ Utility Commands - Recreate a view after schema changes * - :ref:`SELECT DUMP_DATABASE_DDL` - View the ``CREATE TABLE`` statement for an current database - + * - :ref:`SHOW CONNECTIONS` + - Returns a list of active sessions on the current worker + * - :ref:`SHOW LOCKS` + - Returns a list of locks from across the cluster + * - :ref:`SHOW NODE INFO` + - Returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases + * - :ref:`SHOW SERVER STATUS` + - Returns a list of active sessions across the cluster + * - :ref:`SHOW VERSION` + - Returns the system version for SQream DB + * - :ref:`STOP STATEMENT` + - Stops or aborts an active statement Monitoring From ab85fac18708fa16c1029524dc9f2c020f0e1929 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 24 Apr 2022 13:13:01 +0300 Subject: [PATCH 0049/1892] Moved System Functions to SQL Statements > Utility Commands Deleted System Functions section from SQL functions. Deleted System Functions folder (all system functions moved to SQL Syntax > Utility Commands)> --- reference/sql/sql_functions/index.rst | 27 -- .../utility_commands/explain.rst | 59 ++++ .../utility_commands/show_connections.rst | 78 +++++ .../utility_commands/show_locks.rst | 79 +++++ .../utility_commands/show_node_info.rst | 310 ++++++++++++++++++ .../utility_commands/show_server_status.rst | 108 ++++++ .../utility_commands/show_version.rst | 46 +++ .../utility_commands/stop_statement.rst | 77 +++++ 8 files changed, 757 insertions(+), 27 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/explain.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_connections.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_locks.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_node_info.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_server_status.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_version.rst create mode 100644 reference/sql/sql_statements/utility_commands/stop_statement.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 395cdfd59..5ef0a7c5f 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -363,32 +363,6 @@ For more information about window functions, see :ref:`window_functions`. - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible -System Functions ------------------- -System functions allow you to execute actions in the system, such as aborting a query or get information about system processes. - -The following table shows the **system** functions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Function - - Description - * - :ref:`explain` - - Returns a static query plan for a statement - * - :ref:`show_connections` - - Returns a list of jobs and statements on the current worker - * - :ref:`show_locks` - - Returns any existing locks in the database - * - :ref:`show_node_info` - - Returns a query plan for an actively running statement with timing information - * - :ref:`show_server_status` - - Shows running statements across the cluster - * - :ref:`show_version` - - Returns the version of SQream DB - * - :ref:`stop_statement` - - Stops a query (or statement) if it is currently running Workload Management Functions --------------------------------- @@ -418,4 +392,3 @@ The following table shows the **workload management** functions: user_defined_functions/index aggregate_functions/index window_functions/index - system_functions/index \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/explain.rst b/reference/sql/sql_statements/utility_commands/explain.rst new file mode 100644 index 000000000..e9b7e7ee9 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/explain.rst @@ -0,0 +1,59 @@ +.. _explain: + +***************** +EXPLAIN +***************** + +``EXPLAIN`` returns a static query plan, which can be used to debug query plans. + +To see an actively running query or statement, use :ref:`show_node_info` instead. + +See also :ref:`show_node_info`, :ref:`show_server_status`. + + +Permissions +============= + +The role must have the ``SELECT`` permissions for any tables referenced by the query. + +Syntax +========== + +.. code-block:: postgres + + explain_statement ::= + SELECT EXPLAIN(query_stmt) + ; + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``query_stmt`` + - The select query to generate the plan for. + +Notes +=========== + +Use dollar-quoting to escape the query text + +Examples +=========== + +Generating a static query plan +---------------------------------- + +.. code-block:: psql + + t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); + Select + Specific (TTNative Gpu) (dateadd@null := dt@null, + dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) + Table Scan + public.cool_dates ("dt@null", "dt@val") [] + diff --git a/reference/sql/sql_statements/utility_commands/show_connections.rst b/reference/sql/sql_statements/utility_commands/show_connections.rst new file mode 100644 index 000000000..1bd320a4c --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_connections.rst @@ -0,0 +1,78 @@ +.. _show_connections: + +******************** +SHOW_CONNECTIONS +******************** + +``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. + +To see sessions across the cluster, see :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_connections_statement ::= + SELECT SHOW_CONNECTIONS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``ip`` + - The worker hostname or IP + * - ``conn_id`` + - Connection ID + * - ``conn_start_time`` + - Connection start timestamp + * - ``stmt_id`` + - Statement ID. Connections with no active statement display ``-1``. + * - ``stmt_start_time`` + - Statement start timestamp + * - ``stmt`` + - Statement text + + +Notes +=========== + +* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. + +* A connection is typically reused. There could be many statements under a single connection ID. + +Examples +=========== + +Using ``SHOW_CONNECTIONS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst new file mode 100644 index 000000000..d5e7c02ec --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -0,0 +1,79 @@ +.. _show_locks: + +******************** +SHOW_LOCKS +******************** + +``SHOW_LOCKS`` returns a list of locks from across the cluster. + +Read more about locks in :ref:`concurrency_and_locks`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_locks_statement ::= + SELECT SHOW_LOCKS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``stmt_id`` + - Statement ID that caused the lock. + * - ``stmt_string`` + - Statement text + * - ``username`` + - The role that executed the statement + * - ``server`` + - The worker node's IP + * - ``port`` + - The worker node's port + * - ``locked_object`` + - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` + * - ``lockmode`` + - The locking mode (:ref:`inclusive` or :ref:`exclusive`). + * - ``statement_start_time`` + - Timestamp the statement started + * - ``lock_start_time`` + - Timestamp the lock was obtained + + +Examples +=========== + +Using ``SHOW_LOCKS`` to see active locks +--------------------------------------------------- + +In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. + + +.. code-block:: psql + + t=> SELECT SHOW_LOCKS(); + statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time + -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + + diff --git a/reference/sql/sql_statements/utility_commands/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst new file mode 100644 index 000000000..345d16440 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -0,0 +1,310 @@ +.. _show_node_info: + +******************** +SHOW_NODE_INFO +******************** + +``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. + +The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. + +See also :ref:`explain`, :ref:`show_server_status`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_node_info_statement ::= + SELECT SHOW_NODE_INFO(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to explore + +Returns +========= + +This utility returns details of the execution nodes, if the statement is still running. + +If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - Column name + - Description + * - ``stmt_id`` + - The ID for the statement + * - ``node_id`` + - This node's ID in this execution plan + * - ``node_type`` + - The node type + * - ``rows`` + - Total number of rows this node has processed + * - ``chunks`` + - Number of chunks this node has processed + * - ``avg_rows_in_chunk`` + - Average amount of rows that this node processes in each chunk (``rows / chunks``) + * - ``time`` + - Timestamp for this node's creation + * - ``parent_node_id`` + - The ``node_id`` of this node's parent + * - ``read`` + - Total data read from disk + * - ``write`` + - Total data written to disk + * - ``comment`` + - Additional information (e.g. table name for ``ReadTable``) + * - ``timesum`` + - Total elapsed time for this execution node's processing + + +.. _node_types: + +Node types +============= + +This is a full list of node types: + +.. list-table:: Node types + :widths: auto + :header-rows: 1 + + * - Column name + - Execution location + - Description + * - ``AddChunkId`` + - + - Used during insert operations + * - ``AddSequences`` + - + - Used during insert operations, with :ref:`identity columns` + * - ``AddMinMaxMetadata`` + - + - Used to calculate ranges for the :ref:`chunk metadata system` + * - ``AddTopSortFilters`` + - + - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Compress`` + - CPU and GPU + - Compress data with both CPU and GPU schemes + * - ``CpuDecompress`` + - CPU + - Decompression operation, common for longer ``VARCHAR`` types + * - ``CpuLoopJoin`` + - CPU + - A non-indexed nested loop join, performed on the CPU + * - ``CpuReduce`` + - CPU + - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) + * - ``CpuToGpu``, ``GpuToCpu`` + - + - An operation that moves data to or from the GPU for processing + * - ``CpuTransform`` + - CPU + - A transform operation performed on the CPU, usually a :ref:`scalar function` + * - ``CrossJoin`` + - + - A join without a join condition + * - ``DeferredGather`` + - CPU + - Merges the results of GPU operations with a result set [#f0]_ + * - ``Distinct`` + - GPU + - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) + * - ``Distinct_Merge`` + - CPU + - The merge operation of the ``Distinct`` operation + * - ``Filter`` + - GPU + - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause + * - ``GpuCopy`` + - GPU + - Copies data between GPUs or within a single GPU + * - ``GpuDecompress`` + - GPU + - Decompression operation + * - ``GpuReduceMerge`` + - GPU + - An operation to optimize part of the merger phases in the GPU + * - ``GpuTransform`` + - GPU + - A transformation operation such as a type cast or :ref:`scalar function` + * - ``Hash`` + - CPU + - Hashes the output result. Used internally. + * - ``JoinSideMarker`` + - + - Used internally. + * - ``LiteralValues`` + - CPU + - Creates a virtual relation (table), when :ref:`values` is used + * - ``LocateFiles`` + - CPU + - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns + * - ``LoopJoin`` + - GPU + - A non-indexed nested loop join, performed on the GPU + * - ``MarkMatchedJoinRows`` + - + - Used in outer joins, matches rows for larger join operations + * - ``NullifyDuplicates`` + - + - Replaces duplicate values with ``NULL`` to calculate distinct aggregates + * - ``NullSink`` + - CPU + - Used internally + * - ``ParseCsv`` + - CPU + - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data + * - ``PopNetworkQueue`` + - CPU + - Fetches data from the network queue (e.g. when used with :ref:`insert`) + * - ``PushToNetworkQueue`` + - CPU + - Sends result sets to a client connected over the network + * - ``ReadCatalog`` + - CPU + - Converts the :ref:`catalog` into a relation (table) + * - ``ReadFiles`` + - CPU + - Reads external flat-files + * - ``ReadOrc`` + - CPU + - Reads data from an ORC file + * - ``ReadParquet`` + - CPU + - Reads data from a Parquet file + * - ``ReadTable`` + - CPU + - Reads data from a standard table stored on disk + * - ``ReadTableMetadata`` + - CPU + - Reads only table metadata as an optimization + * - ``Rechunk`` + - + - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used + * - ``Reduce`` + - GPU + - A reduction operation, such as a ``GROUP BY`` + * - ``ReduceMerge`` + - GPU + - A merge operation of a reduction operation, helps operate on larger-than-RAM data + * - ``ReorderInput`` + - + - Change the order of arguments in preparation for the next operation + * - ``SeparatedGather`` + - GPU + - Gathers additional columns for the result + * - ``Sort`` + - GPU + - Sort operation [#f1]_ + * - ``SortMerge`` + - CPU + - A merge operation of a sort operation, helps operate on larger-than-RAM data + * - ``SortMergeJoin`` + - GPU + - A sort-merge join, performed on the GPU + * - ``TakeRowsFromChunk`` + - + - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` + * - ``Top`` + - + - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) + * - ``UdfTransform`` + - CPU + - Executes a :ref:`user defined function` + * - ``UnionAll`` + - + - Combines two sources of data when ``UNION ALL`` is used + * - ``VarCharJoiner`` + - + - Used internally + * - ``VarCharSplitter`` + - + - Used intenrally + * - ``Window`` + - GPU + - Executes a non-ranking :ref:`window function` + * - ``WindowRanking`` + - GPU + - Executes a ranking :ref:`window function` + * - ``WriteTable`` + - CPU + - Writes the result set to a standard table stored on disk + +.. rubric:: Footnotes + +.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. + +.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. + +Statement statuses +======================= + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Notes +=========== + +* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. + +* This utility is primarily intended for troubleshooting with SQream support. + +Examples +=========== + +Getting execution details for a statement +------------------------------------------------ + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 + sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 + + +The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. + +The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` + +.. code-block:: psql + + t=> SELECT SHOW_NODE_INFO(176); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- + 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 + 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 + 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 + 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 + 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 + 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 + 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 + 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 + 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 + 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 + 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 + diff --git a/reference/sql/sql_statements/utility_commands/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst new file mode 100644 index 000000000..f59f79ccc --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_server_status.rst @@ -0,0 +1,108 @@ +.. _show_server_status: + +******************** +SHOW_SERVER_STATUS +******************** + +``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. + +To list active statements on the current worker only, see :ref:`show_connections`. + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + show_server_status_statement ::= + SELECT SHOW_SERVER_STATUS() + ; + +Parameters +============ + +None + +Returns +========= + +This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. + +.. list-table:: Result columns + :widths: auto + :header-rows: 1 + + * - ``service`` + - The service name for the statement + * - ``instance`` + - The worker ID + * - ``connection_id`` + - Connection ID + * - ``serverip`` + - Worker end-point IP + * - ``serverport`` + - Worker end-point port + * - ``database_name`` + - Database name for the statement + * - ``user_name`` + - Username running the statement + * - ``clientip`` + - Client IP + * - ``statementid`` + - Statement ID + * - ``statement`` + - Statement text + * - ``statementstarttime`` + - Statement start timestamp + * - ``statementstatus`` + - Statement status (see table below) + * - ``statementstatusstart`` + - Last updated timestamp + +.. include from here: 66 + + +.. list-table:: Statement status values + :widths: auto + :header-rows: 1 + + * - Status + - Description + * - ``Preparing`` + - Statement is being prepared + * - ``In queue`` + - Statement is waiting for execution + * - ``Initializing`` + - Statement has entered execution checks + * - ``Executing`` + - Statement is executing + * - ``Stopping`` + - Statement is in the process of stopping + + +.. include until here 86 + +Notes +=========== + +* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. + +Examples +=========== + +Using ``SHOW_SERVER_STATUS`` to get statement IDs +---------------------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- + sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 + +The statement ID is ``128``, running on worker ``192.168.1.91``. diff --git a/reference/sql/sql_statements/utility_commands/show_version.rst b/reference/sql/sql_statements/utility_commands/show_version.rst new file mode 100644 index 000000000..8c3e7565e --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_version.rst @@ -0,0 +1,46 @@ +.. _show_version: + +***************** +SHOW_VERSION +***************** + +``SHOW_VERSION()`` is a function that returns the system version for SQream DB. + +Permissions +============= + +No special permissions are required. + +Syntax +========== + +.. code-block:: postgres + + show_version_statement ::= + SELECT SHOW_VERSION() + ; + +Parameters +============ + +None + +Notes +========== + +To check the SQream DB version from the shell, run ``$ sqreamd --version`` + +Examples +=========== + +Getting the current SQream DB version +--------------------------------------- + + +.. code-block:: psql + + t=> SELECT SHOW_VERSION(); + bytesread + --------- + v2019.3 + diff --git a/reference/sql/sql_statements/utility_commands/stop_statement.rst b/reference/sql/sql_statements/utility_commands/stop_statement.rst new file mode 100644 index 000000000..30efc25b5 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/stop_statement.rst @@ -0,0 +1,77 @@ +.. _stop_statement: + +******************** +STOP_STATEMENT +******************** + +``STOP_STATEMENT`` stops or aborts an active statement. + +To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. + +.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. + +Syntax +========== + +.. code-block:: postgres + + stop_statement_statement ::= + SELECT STOP_STATEMENT(stmt_id) + ; + + stmt_id ::= bigint + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``stmt_id`` + - The statement ID to stop + +Returns +========= + +This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. + + +Notes +=========== + +* This utility always succeeds even if the statement does not exist, or has already stopped. + +Examples +=========== + +Using :ref:`show_connections` to get statement IDs +---------------------------------------------------- + +.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. + +.. code-block:: psql + + t=> SELECT SHOW_CONNECTIONS(); + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + -------------+---------+---------------------+---------+---------------------+-------------------------- + 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... + 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | + 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + + +The statement ID we're interested in is ``129``. We can now stop this statement: + +.. code-block:: psql + + t=> SELECT STOP_STATEMENT(129) + executed + From 784aaf0099a629ffe684863c51fe63a6f78ae479 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 24 Apr 2022 13:22:18 +0300 Subject: [PATCH 0050/1892] Moved System Functions to SQL Statements > Utility Commands Deleted System Functions section from SQL functions. Deleted System Functions folder (all system functions moved to SQL Syntax > Utility Commands)> --- reference/sql/sql_functions/index.rst | 3 +- .../system_functions/explain.rst | 59 ---- .../sql_functions/system_functions/index.rst | 19 -- .../system_functions/show_connections.rst | 78 ----- .../system_functions/show_locks.rst | 79 ----- .../system_functions/show_node_info.rst | 310 ------------------ .../system_functions/show_server_status.rst | 108 ------ .../system_functions/show_version.rst | 46 --- .../system_functions/stop_statement.rst | 77 ----- 9 files changed, 2 insertions(+), 777 deletions(-) delete mode 100644 reference/sql/sql_functions/system_functions/explain.rst delete mode 100644 reference/sql/sql_functions/system_functions/index.rst delete mode 100644 reference/sql/sql_functions/system_functions/show_connections.rst delete mode 100644 reference/sql/sql_functions/system_functions/show_locks.rst delete mode 100644 reference/sql/sql_functions/system_functions/show_node_info.rst delete mode 100644 reference/sql/sql_functions/system_functions/show_server_status.rst delete mode 100644 reference/sql/sql_functions/system_functions/show_version.rst delete mode 100644 reference/sql/sql_functions/system_functions/stop_statement.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 5ef0a7c5f..51d969f40 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -364,6 +364,7 @@ For more information about window functions, see :ref:`window_functions`. + Workload Management Functions --------------------------------- The following table shows the **workload management** functions: @@ -391,4 +392,4 @@ The following table shows the **workload management** functions: scalar_functions/index user_defined_functions/index aggregate_functions/index - window_functions/index + window_functions/index \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/explain.rst b/reference/sql/sql_functions/system_functions/explain.rst deleted file mode 100644 index e9b7e7ee9..000000000 --- a/reference/sql/sql_functions/system_functions/explain.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _explain: - -***************** -EXPLAIN -***************** - -``EXPLAIN`` returns a static query plan, which can be used to debug query plans. - -To see an actively running query or statement, use :ref:`show_node_info` instead. - -See also :ref:`show_node_info`, :ref:`show_server_status`. - - -Permissions -============= - -The role must have the ``SELECT`` permissions for any tables referenced by the query. - -Syntax -========== - -.. code-block:: postgres - - explain_statement ::= - SELECT EXPLAIN(query_stmt) - ; - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``query_stmt`` - - The select query to generate the plan for. - -Notes -=========== - -Use dollar-quoting to escape the query text - -Examples -=========== - -Generating a static query plan ----------------------------------- - -.. code-block:: psql - - t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); - Select - Specific (TTNative Gpu) (dateadd@null := dt@null, - dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) - Table Scan - public.cool_dates ("dt@null", "dt@val") [] - diff --git a/reference/sql/sql_functions/system_functions/index.rst b/reference/sql/sql_functions/system_functions/index.rst deleted file mode 100644 index ba99610ba..000000000 --- a/reference/sql/sql_functions/system_functions/index.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _system_functions_functions: - -******************** -System Functions -******************** -**System functions** are used for returning system information, such as version and node information, and for maintenance operations that are not regularly accessed from any interface. - -The System Functions page describes the following: - -.. hlist:: - :columns: 1 - - * :ref:`explain` - * :ref:`show_version` - * :ref:`show_connections` - * :ref:`show_locks` - * :ref:`show_node_info` - * :ref:`show_server_status` - * :ref:`stop_statement` \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_connections.rst b/reference/sql/sql_functions/system_functions/show_connections.rst deleted file mode 100644 index 1bd320a4c..000000000 --- a/reference/sql/sql_functions/system_functions/show_connections.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _show_connections: - -******************** -SHOW_CONNECTIONS -******************** - -``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. - -To see sessions across the cluster, see :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_connections_statement ::= - SELECT SHOW_CONNECTIONS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``ip`` - - The worker hostname or IP - * - ``conn_id`` - - Connection ID - * - ``conn_start_time`` - - Connection start timestamp - * - ``stmt_id`` - - Statement ID. Connections with no active statement display ``-1``. - * - ``stmt_start_time`` - - Statement start timestamp - * - ``stmt`` - - Statement text - - -Notes -=========== - -* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. - -* A connection is typically reused. There could be many statements under a single connection ID. - -Examples -=========== - -Using ``SHOW_CONNECTIONS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_functions/system_functions/show_locks.rst b/reference/sql/sql_functions/system_functions/show_locks.rst deleted file mode 100644 index d5e7c02ec..000000000 --- a/reference/sql/sql_functions/system_functions/show_locks.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _show_locks: - -******************** -SHOW_LOCKS -******************** - -``SHOW_LOCKS`` returns a list of locks from across the cluster. - -Read more about locks in :ref:`concurrency_and_locks`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_locks_statement ::= - SELECT SHOW_LOCKS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``stmt_id`` - - Statement ID that caused the lock. - * - ``stmt_string`` - - Statement text - * - ``username`` - - The role that executed the statement - * - ``server`` - - The worker node's IP - * - ``port`` - - The worker node's port - * - ``locked_object`` - - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` - * - ``lockmode`` - - The locking mode (:ref:`inclusive` or :ref:`exclusive`). - * - ``statement_start_time`` - - Timestamp the statement started - * - ``lock_start_time`` - - Timestamp the lock was obtained - - -Examples -=========== - -Using ``SHOW_LOCKS`` to see active locks ---------------------------------------------------- - -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. - - -.. code-block:: psql - - t=> SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - - diff --git a/reference/sql/sql_functions/system_functions/show_node_info.rst b/reference/sql/sql_functions/system_functions/show_node_info.rst deleted file mode 100644 index 345d16440..000000000 --- a/reference/sql/sql_functions/system_functions/show_node_info.rst +++ /dev/null @@ -1,310 +0,0 @@ -.. _show_node_info: - -******************** -SHOW_NODE_INFO -******************** - -``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. - -The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. - -See also :ref:`explain`, :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_node_info_statement ::= - SELECT SHOW_NODE_INFO(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to explore - -Returns -========= - -This utility returns details of the execution nodes, if the statement is still running. - -If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - Column name - - Description - * - ``stmt_id`` - - The ID for the statement - * - ``node_id`` - - This node's ID in this execution plan - * - ``node_type`` - - The node type - * - ``rows`` - - Total number of rows this node has processed - * - ``chunks`` - - Number of chunks this node has processed - * - ``avg_rows_in_chunk`` - - Average amount of rows that this node processes in each chunk (``rows / chunks``) - * - ``time`` - - Timestamp for this node's creation - * - ``parent_node_id`` - - The ``node_id`` of this node's parent - * - ``read`` - - Total data read from disk - * - ``write`` - - Total data written to disk - * - ``comment`` - - Additional information (e.g. table name for ``ReadTable``) - * - ``timesum`` - - Total elapsed time for this execution node's processing - - -.. _node_types: - -Node types -============= - -This is a full list of node types: - -.. list-table:: Node types - :widths: auto - :header-rows: 1 - - * - Column name - - Execution location - - Description - * - ``AddChunkId`` - - - - Used during insert operations - * - ``AddSequences`` - - - - Used during insert operations, with :ref:`identity columns` - * - ``AddMinMaxMetadata`` - - - - Used to calculate ranges for the :ref:`chunk metadata system` - * - ``AddTopSortFilters`` - - - - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Compress`` - - CPU and GPU - - Compress data with both CPU and GPU schemes - * - ``CpuDecompress`` - - CPU - - Decompression operation, common for longer ``VARCHAR`` types - * - ``CpuLoopJoin`` - - CPU - - A non-indexed nested loop join, performed on the CPU - * - ``CpuReduce`` - - CPU - - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) - * - ``CpuToGpu``, ``GpuToCpu`` - - - - An operation that moves data to or from the GPU for processing - * - ``CpuTransform`` - - CPU - - A transform operation performed on the CPU, usually a :ref:`scalar function` - * - ``CrossJoin`` - - - - A join without a join condition - * - ``DeferredGather`` - - CPU - - Merges the results of GPU operations with a result set [#f0]_ - * - ``Distinct`` - - GPU - - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) - * - ``Distinct_Merge`` - - CPU - - The merge operation of the ``Distinct`` operation - * - ``Filter`` - - GPU - - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause - * - ``GpuCopy`` - - GPU - - Copies data between GPUs or within a single GPU - * - ``GpuDecompress`` - - GPU - - Decompression operation - * - ``GpuReduceMerge`` - - GPU - - An operation to optimize part of the merger phases in the GPU - * - ``GpuTransform`` - - GPU - - A transformation operation such as a type cast or :ref:`scalar function` - * - ``Hash`` - - CPU - - Hashes the output result. Used internally. - * - ``JoinSideMarker`` - - - - Used internally. - * - ``LiteralValues`` - - CPU - - Creates a virtual relation (table), when :ref:`values` is used - * - ``LocateFiles`` - - CPU - - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns - * - ``LoopJoin`` - - GPU - - A non-indexed nested loop join, performed on the GPU - * - ``MarkMatchedJoinRows`` - - - - Used in outer joins, matches rows for larger join operations - * - ``NullifyDuplicates`` - - - - Replaces duplicate values with ``NULL`` to calculate distinct aggregates - * - ``NullSink`` - - CPU - - Used internally - * - ``ParseCsv`` - - CPU - - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data - * - ``PopNetworkQueue`` - - CPU - - Fetches data from the network queue (e.g. when used with :ref:`insert`) - * - ``PushToNetworkQueue`` - - CPU - - Sends result sets to a client connected over the network - * - ``ReadCatalog`` - - CPU - - Converts the :ref:`catalog` into a relation (table) - * - ``ReadFiles`` - - CPU - - Reads external flat-files - * - ``ReadOrc`` - - CPU - - Reads data from an ORC file - * - ``ReadParquet`` - - CPU - - Reads data from a Parquet file - * - ``ReadTable`` - - CPU - - Reads data from a standard table stored on disk - * - ``ReadTableMetadata`` - - CPU - - Reads only table metadata as an optimization - * - ``Rechunk`` - - - - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used - * - ``Reduce`` - - GPU - - A reduction operation, such as a ``GROUP BY`` - * - ``ReduceMerge`` - - GPU - - A merge operation of a reduction operation, helps operate on larger-than-RAM data - * - ``ReorderInput`` - - - - Change the order of arguments in preparation for the next operation - * - ``SeparatedGather`` - - GPU - - Gathers additional columns for the result - * - ``Sort`` - - GPU - - Sort operation [#f1]_ - * - ``SortMerge`` - - CPU - - A merge operation of a sort operation, helps operate on larger-than-RAM data - * - ``SortMergeJoin`` - - GPU - - A sort-merge join, performed on the GPU - * - ``TakeRowsFromChunk`` - - - - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Top`` - - - - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) - * - ``UdfTransform`` - - CPU - - Executes a :ref:`user defined function` - * - ``UnionAll`` - - - - Combines two sources of data when ``UNION ALL`` is used - * - ``VarCharJoiner`` - - - - Used internally - * - ``VarCharSplitter`` - - - - Used intenrally - * - ``Window`` - - GPU - - Executes a non-ranking :ref:`window function` - * - ``WindowRanking`` - - GPU - - Executes a ranking :ref:`window function` - * - ``WriteTable`` - - CPU - - Writes the result set to a standard table stored on disk - -.. rubric:: Footnotes - -.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. - -.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. - -Statement statuses -======================= - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Notes -=========== - -* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. - -* This utility is primarily intended for troubleshooting with SQream support. - -Examples -=========== - -Getting execution details for a statement ------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 - sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 - - -The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. - -The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` - -.. code-block:: psql - - t=> SELECT SHOW_NODE_INFO(176); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- - 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 - 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 - 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 - 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 - 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 - 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 - 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 - 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 - 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 - 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 - 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 - diff --git a/reference/sql/sql_functions/system_functions/show_server_status.rst b/reference/sql/sql_functions/system_functions/show_server_status.rst deleted file mode 100644 index f59f79ccc..000000000 --- a/reference/sql/sql_functions/system_functions/show_server_status.rst +++ /dev/null @@ -1,108 +0,0 @@ -.. _show_server_status: - -******************** -SHOW_SERVER_STATUS -******************** - -``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. - -To list active statements on the current worker only, see :ref:`show_connections`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_server_status_statement ::= - SELECT SHOW_SERVER_STATUS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``service`` - - The service name for the statement - * - ``instance`` - - The worker ID - * - ``connection_id`` - - Connection ID - * - ``serverip`` - - Worker end-point IP - * - ``serverport`` - - Worker end-point port - * - ``database_name`` - - Database name for the statement - * - ``user_name`` - - Username running the statement - * - ``clientip`` - - Client IP - * - ``statementid`` - - Statement ID - * - ``statement`` - - Statement text - * - ``statementstarttime`` - - Statement start timestamp - * - ``statementstatus`` - - Statement status (see table below) - * - ``statementstatusstart`` - - Last updated timestamp - -.. include from here: 66 - - -.. list-table:: Statement status values - :widths: auto - :header-rows: 1 - - * - Status - - Description - * - ``Preparing`` - - Statement is being prepared - * - ``In queue`` - - Statement is waiting for execution - * - ``Initializing`` - - Statement has entered execution checks - * - ``Executing`` - - Statement is executing - * - ``Stopping`` - - Statement is in the process of stopping - - -.. include until here 86 - -Notes -=========== - -* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. - -Examples -=========== - -Using ``SHOW_SERVER_STATUS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- - sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 - -The statement ID is ``128``, running on worker ``192.168.1.91``. diff --git a/reference/sql/sql_functions/system_functions/show_version.rst b/reference/sql/sql_functions/system_functions/show_version.rst deleted file mode 100644 index 8c3e7565e..000000000 --- a/reference/sql/sql_functions/system_functions/show_version.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. _show_version: - -***************** -SHOW_VERSION -***************** - -``SHOW_VERSION()`` is a function that returns the system version for SQream DB. - -Permissions -============= - -No special permissions are required. - -Syntax -========== - -.. code-block:: postgres - - show_version_statement ::= - SELECT SHOW_VERSION() - ; - -Parameters -============ - -None - -Notes -========== - -To check the SQream DB version from the shell, run ``$ sqreamd --version`` - -Examples -=========== - -Getting the current SQream DB version ---------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_VERSION(); - bytesread - --------- - v2019.3 - diff --git a/reference/sql/sql_functions/system_functions/stop_statement.rst b/reference/sql/sql_functions/system_functions/stop_statement.rst deleted file mode 100644 index 30efc25b5..000000000 --- a/reference/sql/sql_functions/system_functions/stop_statement.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _stop_statement: - -******************** -STOP_STATEMENT -******************** - -``STOP_STATEMENT`` stops or aborts an active statement. - -To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. - -.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - stop_statement_statement ::= - SELECT STOP_STATEMENT(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to stop - -Returns -========= - -This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. - - -Notes -=========== - -* This utility always succeeds even if the statement does not exist, or has already stopped. - -Examples -=========== - -Using :ref:`show_connections` to get statement IDs ----------------------------------------------------- - -.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can now stop this statement: - -.. code-block:: psql - - t=> SELECT STOP_STATEMENT(129) - executed - From 5f125bc08e51aec194d0482ea0277823adbf99d0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 27 Apr 2022 10:08:16 +0300 Subject: [PATCH 0051/1892] Update index.rst Improved page structure. --- reference/sql/sql_functions/index.rst | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 51d969f40..a66760b7f 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -117,9 +117,7 @@ The following table shows the **date and time** functions: Numeric ^^^^^^^^^^^ -The following table shows the **arithmetic operators** - -For more information about arithmetic operator, see :ref:`arithmetic_operators`. +The following table shows the **arithmetic operators**: .. list-table:: Arithmetic Operators :widths: auto @@ -150,6 +148,8 @@ For more information about arithmetic operator, see :ref:`arithmetic_operators`. - ``a % b`` - Modulu of ``a`` by ``b``. See also :ref:`mod` +For more information about arithmetic operators, see :ref:`arithmetic_operators`. + The following table shows the **arithmetic operator** functions: .. list-table:: Arithemtic Operator Functions @@ -209,7 +209,7 @@ The following table shows the **arithmetic operator** functions: Strings ^^^^^^^^^^^ -The following table shows the **string* functions: +The following table shows the **string** functions: .. list-table:: :widths: auto @@ -270,15 +270,13 @@ The following table shows the **string* functions: User-Defined Scalar Functions --------------------- -For more information about user-defined scalar functions, see :ref:`scalar_sql_udf` +For more information about user-defined scalar functions, see :ref:`scalar_sql_udf`. Aggregate Functions --------------------- The following table shows the **aggregate** functions: -For more information about aggregate functions, see :ref:`aggregate_functions`. - .. list-table:: :widths: auto :header-rows: 1 @@ -323,12 +321,12 @@ For more information about aggregate functions, see :ref:`aggregate_functions`. - ``varp`` - Calculates population variance of values +For more information about aggregate functions, see :ref:`aggregate_functions`. + Window Functions ------------------- The following table shows the **window** functions: -For more information about window functions, see :ref:`window_functions`. - .. list-table:: :widths: auto :header-rows: 1 @@ -362,8 +360,7 @@ For more information about window functions, see :ref:`window_functions`. * - :ref:`ntile` - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible - - +For more information about window functions, see :ref:`window_functions`. Workload Management Functions --------------------------------- From 981085951fca474428c7b8a4b80090b706d249a0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Apr 2022 17:48:10 +0300 Subject: [PATCH 0052/1892] Removed System Functions Moved System Functions to SQL Statements > Utilities, and removed System Functions --- reference/sql/sql_statements/index.rst | 5 + .../utility_commands/drop_saved_query.rst | 55 ++++++++ .../utility_commands/execute_saved_query.rst | 123 ++++++++++++++++++ .../utility_commands/list_saved_queries.rst | 77 +++++++++++ .../recompile_saved_query.rst | 88 +++++++++++++ .../utility_commands/show_saved_query.rst | 61 +++++++++ 6 files changed, 409 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/drop_saved_query.rst create mode 100644 reference/sql/sql_statements/utility_commands/execute_saved_query.rst create mode 100644 reference/sql/sql_statements/utility_commands/list_saved_queries.rst create mode 100644 reference/sql/sql_statements/utility_commands/recompile_saved_query.rst create mode 100644 reference/sql/sql_statements/utility_commands/show_saved_query.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index eab8d8f84..6845ae7cd 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -3,6 +3,11 @@ *************** SQL Statements *************** +The **SQL Statements** page describes the following commands: + +.. contents:: + :local: + :depth: 1 SQream DB supports commands from ANSI SQL. diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst new file mode 100644 index 000000000..f7faef6c5 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst @@ -0,0 +1,55 @@ +.. _drop_saved_query: + +******************** +DROP_SAVED_QUERY +******************** + +``DROP_SAVED_QUERY`` drops a :ref:`previously saved query`. + +Read more in the :ref:`saved_queries` guide. + +See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. + +Permissions +============= + +Dropping a saved query requires no special permissions. + +Syntax +========== + +.. code-block:: postgres + + drop_saved_query_statement ::= + SELECT DROP_SAVED_QUERY(saved_query_name) + ; + + saved_query_name ::= string_literal + +Returns +========== + +If saved query is dropped successfully, returns nothing. + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``saved_query_name`` + - The name of the query to drop + +Examples +=========== + +Dropping a previously saved query +--------------------------------------- + +.. code-block:: psql + + t=> SELECT DROP_SAVED_QUERY('select_all'); + executed diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst new file mode 100644 index 000000000..6fe41fa08 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -0,0 +1,123 @@ +.. _execute_saved_query: + +******************** +EXECUTE_SAVED_QUERY +******************** + +``EXECUTE_SAVED_QUERY`` executes a :ref:`previously saved query`. + +Read more in the :ref:`saved_queries` guide. + +See also: ref:`save_query`, :ref:`drop_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. + +Permissions +============= + +Executing a saved query requires ``SELECT`` permissions to access the tables referenced in the query. + +Syntax +========== + +.. code-block:: postgres + + execute_saved_query_statement ::= + SELECT EXECUTE_SAVED_QUERY(saved_query_name, [ , argument [ , ... ] ] ) + ; + + saved_query_name ::= string_literal + + argument ::= string_literal | number_literal + +Returns +========== + +Query execution results, based on the query saved. + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``saved_query_name`` + - The name of the query to execute + * - ``argument`` + - A comma separated list of argument literal values + + +Notes +========= + +* Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. + +* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) + +* Query parameters' types are inferred at compile time. + +Examples +=========== + +Assume a table named ``nba``, with the following structure: + +.. code-block:: postgres + + CREATE TABLE nba + ( + Name varchar(40), + Team varchar(40), + Number tinyint, + Position varchar(2), + Age tinyint, + Height varchar(4), + Weight real, + College varchar(40), + Salary float + ); + + +Here's a peek at the table contents (:download:`Download nba.csv `): + +.. csv-table:: nba.csv + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + + +Saving and executing a simple query +--------------------------------------- + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); + executed + t=> SELECT EXECUTE_SAVED_QUERY('select_all'); + Name | Team | Number | Position | Age | Height | Weight | College | Salary + -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + [...] + +Saving and executing parametrized query +------------------------------------------ + +Use parameters to replace them later at execution time. + +.. tip:: Use dollar quoting (`$$`) to avoid escaping strings. + + .. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + executed + t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + Name | Team | Number | Position | Age | Height | Weight | College | Salary + ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- + Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 + James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 + Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 + diff --git a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst new file mode 100644 index 000000000..bb1781840 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst @@ -0,0 +1,77 @@ +.. _list_saved_queries: + +******************** +LIST_SAVED_QUERIES +******************** + +``LIST_SAVED_QUERIES`` lists the available :ref:`previously saved queries`. + +This is an alternative way to using the ``savedqueries`` catalog view. + +Read more in the :ref:`saved_queries` guide. + +See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`show_saved_query`. + +Permissions +============= + +Listing the saved queries requires no special permissions. + +Syntax +========== + +.. code-block:: postgres + + list_saved_queries_statement ::= + SELECT LIST_SAVED_QUERIES() + ; + +Returns +========== + +List of saved query names, one per row. + +Parameters +============ + +None + +Notes +========= + +This statement returns an empty result set if no saved queries exist in the current database. + +Examples +=========== + +Listing previously saved queries +--------------------------------------- + +.. code-block:: psql + + t=> SELECT LIST_SAVED_QUERIES(); + saved_query + ------------------------- + select_all + select_by_weight + select_by_weight_and_team + + t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); + saved_query + ----------------------------------------------- + SELECT * FROM nba WHERE Weight > ? AND Team = ? + + +Listing saved queries with the catalog +--------------------------------------------- + +Using the :ref:`catalog` is also possible: + +.. code-block:: psql + + t=> SELECT * FROM sqream_catalog.savedqueries; + name | num_parameters + --------------------------+--------------- + select_all | 0 + select_by_weight | 1 + select_by_weight_and_team | 2 diff --git a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst new file mode 100644 index 000000000..d6b63e30e --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst @@ -0,0 +1,88 @@ +.. _recompile_saved_query: + +************************** +RECOMPILE_SAVED_QUERY +************************** + +``RECOMPILE_SAVED_QUERY`` recompiles a saved query that has been invalidated due to a schema change. + +Permissions +============= + +Recompiling a saved query requires no special permissions. + +Syntax +========== + +.. code-block:: postgres + + recompile_saved_query_statement ::= + SELECT RECOMPILE_SAVED_QUERY(saved_query_name) + ; + + saved_query_name ::= string_literal + +Returns +========== + +If saved query is recompiled successfully, returns nothing. + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``saved_query_name`` + - The name of the query to recompile + +Examples +=========== + +Recreating a query that has been invalidated +------------------------------------------------- + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + executed + t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + Name | Team | Number | Position | Age | Height | Weight | College | Salary + ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- + Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 + James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 + Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 + + +To invalidate the original saved query, we will change the schema without affecting our original query text: + +.. code-block:: psql + + t=> ALTER TABLE nba RENAME COLUMN age to "Age (as of 2015)"; + executed + +However, because the query was compiled previously, this change invalidates the query and causes it to fail: + +.. code-block:: psql + + t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + Error: column not found {Age@null} + column not found {Age@null} + +Recompiling the query will fix this issue + +.. code-block:: psql + + t=> SELECT RECOMPILE_SAVED_QUERY('select_by_weight_and_team'); + executed + t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + Name | Team | Number | Position | Age (as of 2015) | Height | Weight | College | Salary + ------------------+-----------------+--------+----------+------------------+--------+--------+-------------+-------- + Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 + James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 + Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 diff --git a/reference/sql/sql_statements/utility_commands/show_saved_query.rst b/reference/sql/sql_statements/utility_commands/show_saved_query.rst new file mode 100644 index 000000000..15ac4c1bd --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/show_saved_query.rst @@ -0,0 +1,61 @@ +.. _show_saved_query: + +******************** +SHOW_SAVED_QUERY +******************** + +``SHOW_SAVED_QUERY`` shows the query text for a :ref:`previously saved query`. + +Read more in the :ref:`saved_queries` guide. + +See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`list_saved_queries`. + +Permissions +============= + +Showing a saved query requires no special permissions. + +Syntax +========== + +.. code-block:: postgres + + show_saved_query_statement ::= + SELECT SHOW_SAVED_QUERY(saved_query_name) + ; + + saved_query_name ::= string_literal + +Returns +========== + +A single row result containing the saved query string. + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``saved_query_name`` + - The name of the query to show + + +Examples +=========== + +Showing a previously saved query +--------------------------------------- + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + executed + t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); + saved_query + ----------------------------------------------- + SELECT * FROM nba WHERE Weight > ? AND Team = ? + From 0b0604a184e022cedd87a3894bf097a399fce9ed Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 1 May 2022 09:53:06 +0300 Subject: [PATCH 0053/1892] Removed Global Locks: SQ-10436 https://sqream.atlassian.net/browse/SQ-10436 Capitalized headers --- feature_guides/concurrency_and_locks.rst | 27 ++++-------------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/feature_guides/concurrency_and_locks.rst b/feature_guides/concurrency_and_locks.rst index e18dea015..2a85d2642 100644 --- a/feature_guides/concurrency_and_locks.rst +++ b/feature_guides/concurrency_and_locks.rst @@ -10,7 +10,7 @@ Read only transactions are never blocked, and never block anything. Even if you .. _locking_modes: -Locking modes +Locking Modes ================ SQream DB has two kinds of locks: @@ -27,7 +27,7 @@ SQream DB has two kinds of locks: This lock allows other statements to insert or delete data from a table, but they'll have to wait in order to run DDL. -When are locks obtained? +When are Locks Obtained? ============================ .. list-table:: @@ -64,23 +64,7 @@ When are locks obtained? Statements that wait will exit with an error if they hit the lock timeout. The default timeout is 3 seconds, see ``statementLockTimeout``. -Global locks ----------------- - -Some operations require exclusive global locks at the cluster level. These usually short-lived locks will be obtained for the following operations: - - * :ref:`create_database` - * :ref:`create_role` - * :ref:`create_table` - * :ref:`alter_role` - * :ref:`alter_table` - * :ref:`drop_database` - * :ref:`drop_role` - * :ref:`drop_table` - * :ref:`grant` - * :ref:`revoke` - -Monitoring locks +Monitoring Locks =================== Monitoring locks across the cluster can be useful when transaction contention takes place, and statements appear "stuck" while waiting for a previous statement to release locks. @@ -101,7 +85,4 @@ In this example, we create a table based on results (:ref:`create_table_as`), bu 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 -For more information on troubleshooting lock related issues, see - - - +For more information on troubleshooting lock related issues, see :ref:`lock_related_issues`. \ No newline at end of file From b6b65d51a12db74a757a769d622f766bc9bdc2f7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 2 May 2022 11:31:21 +0300 Subject: [PATCH 0054/1892] TPD-123 --- .../ddl_commands/cluster_by.rst | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index 2a389e254..3f6023533 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -3,28 +3,38 @@ ********************** CLUSTER BY ********************** +The ``CLUSTER BY`` command is used for changing clustering keys in a table. -``CLUSTER BY`` can be used to change clustering keys in a table. +For more information, see the following: +* :ref:`flexible_data_clustering` -Read our :ref:`data_clustering` guide for more information. + :: -See also: :ref:`drop_clustering_key`, :ref:`create_table`. +* :ref:`drop_clustering_key` - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. + :: + +* :ref:`create_table` Syntax ========== +The following is the correct syntax for the CLUSTER BY command: .. code-block:: postgres alter_table_rename_table_statement ::= ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] ; + + create_table_statement ::= + CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( + { column_def [, ...] } + ) + [ CLUSTER BY { column_name [, ...] } ] + ; + + column_def :: = { column_name type_name [ default ] [ column_constraint ] } table_name ::= identifier @@ -33,6 +43,7 @@ Syntax Parameters ============ +The following table shows the CLUSTER BY parameters: .. list-table:: :widths: auto @@ -42,28 +53,32 @@ Parameters - Description * - ``schema_name`` - The schema name for the table. Defaults to ``public`` if not specified. + * - ``OR REPLACE`` + - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + * - ``column_def`` + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. * - ``table_name`` - The table name to apply the change to. * - ``column_name [, ... ]`` - - Comma separated list of columns to create clustering keys for + - Comma separated list of columns to create clustering keys for. - -Usage notes +Usage Notes ================= - Removing clustering keys does not affect existing data. -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). +To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table`). -Examples +Example =========== - -Reclustering a table +Reclustering a Table ----------------------------------------- +The following example shows how to recluster a table: .. code-block:: postgres ALTER TABLE public.users CLUSTER BY start_date; - +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From 5c9c1288a0ff89c313474415560bf6d3930235bf Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 2 May 2022 15:23:28 +0300 Subject: [PATCH 0055/1892] Update executing_statements_and_running_queries_from_the_editor.rst --- ...ts_and_running_queries_from_the_editor.rst | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 72cbff97b..8fa91d945 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -188,23 +188,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. + - Generates an `INSERT `_ statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. + - Generates a `DELETE `_ statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -223,23 +223,23 @@ The following table describes the DDL Optimizer screen: * - Column area - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. * - Run Optimizer - Starts the optimization process. Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices `_. +For more information, see `Optimization and Best Practices `_. Executing Pre-Defined Queries from the System Queries Panel --------------- The **System Queries** panel lets you execute predefined queries and includes the following system query types: -* **Catalog queries** - used for analyzing table compression rates, users and permissions, etc. +* **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. :: -* **Admin queries** - queries related to available (describe the functionality in a general way). Queries useful for SQream database management. +* **Admin queries** - Queries useful for SQream database management. Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. @@ -274,7 +274,7 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started `_. +.. tip:: If this is your first time using SQream, see `Getting Started `_. .. Keyboard shortcuts From 7bb5c634915b411365f9cb244f45681a54dbcf5a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 14:10:37 +0300 Subject: [PATCH 0056/1892] TPD-106 --- .../ddl_commands/rename_column.rst | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst index 41f1e1628..1022ce0f2 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_column.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_column.rst @@ -3,16 +3,11 @@ ********************** RENAME COLUMN ********************** - -``RENAME COLUMN`` can be used to rename columns in a table. - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. +The ``RENAME COLUMN`` command can be used to rename columns in a table. Syntax ========== +The following is the correct syntax for the ``RENAME_COLUMN`` command: .. code-block:: postgres @@ -30,6 +25,7 @@ Syntax Parameters ============ +The following table describes the `RENAME_COLUMN`` parameters: .. list-table:: :widths: auto @@ -48,18 +44,29 @@ Parameters Examples =========== +The **Examples** section includes the following examples: -Renaming a column +.. contents:: + :local: + :depth: 1 + +Renaming a Column ----------------------------------------- +The following is an example of renaming a column: .. code-block:: postgres -- Remove the 'weight' column ALTER TABLE users RENAME COLUMN weight TO mass; -Renaming a quoted name +Renaming a Quoted Name -------------------------- +The following is an example of renaming a quoted name: .. code-block:: postgres - ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); \ No newline at end of file + ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From dd7d6cfecfa88b7ae19632d67e450c8dded1ce7b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 14:42:30 +0300 Subject: [PATCH 0057/1892] TPD-155 --- .../ddl_commands/add_column.rst | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index cec4aec7b..bac71bd2c 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -3,14 +3,11 @@ ********************** ADD COLUMN ********************** - -The ``ADD COLUMN`` command is used to add columns to an existing table. - - +The ``ADD COLUMN`` command is used to add columns to an existing table. Syntax ========== -The following is the correct syntax for adding a table: +The following is the correct syntax for adding a column to an existing table: .. code-block:: postgres @@ -32,8 +29,6 @@ The following is the correct syntax for adding a table: default ::= DEFAULT default_value - - Parameters ============ The following parameters can be used for adding a table: @@ -52,19 +47,20 @@ The following parameters can be used for adding a table: - A comma separated list of ADD COLUMN commands * - ``column_def`` - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + +Usage Notes +=========== +The following usage notes apply when adding a column to an existing table: -.. note:: * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. - * A new column added to the table can not contain an IDENTITY or be of the TEXT type. - -Permissions -============= -The role must have the ``DDL`` permission at the database or table level. + :: + + * New columns you add to the table cannot be TEXT or contain an IDENTITY. Examples =========== -This section includes the following examples: +The **Examples** section includes the following examples: .. contents:: :local: @@ -77,8 +73,7 @@ This example shows how to add a simple column with a default value: .. code-block:: postgres ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; - + ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; Adding Several Columns in One Command ------------------------------------------- @@ -88,4 +83,8 @@ This example shows how to add several columns in one command: ALTER TABLE cool_animals ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, - ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + +Permissions +============= +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From 832934365ee43872388a3501a20eeda2b3a04a31 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 10 May 2022 17:31:35 +0300 Subject: [PATCH 0058/1892] TPD-88 --- reference/sql/sql_statements/ddl_commands/cluster_by.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index 3f6023533..e4cf42ad4 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -40,6 +40,7 @@ The following is the correct syntax for the CLUSTER BY command: column_name ::= identifier +.. note:: SQream does not support clustering by TEXT columns. Parameters ============ From 2a34788254b4702b4d1e4c9f41f3fe1a704fa344 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 12 May 2022 15:50:45 +0300 Subject: [PATCH 0059/1892] TPD-154: Partial implementation Implemented some of Nadia's comments. Questions remain about others. --- feature_guides/workload_manager.rst | 7 +++---- reference/configuration.rst | 5 ----- reference/sql/sql_statements/index.rst | 2 +- .../sql_statements/wlm_commands/unsubscribe_service.rst | 2 +- .../configuring_your_instance_of_sqream.rst | 2 +- 5 files changed, 6 insertions(+), 12 deletions(-) delete mode 100644 reference/configuration.rst diff --git a/feature_guides/workload_manager.rst b/feature_guides/workload_manager.rst index c8eb2468d..aece3d11f 100644 --- a/feature_guides/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -4,12 +4,11 @@ Workload Manager *********************** -The **Workload Manager** allows SQream DB workers to identify their availability to clients with specific service names. The load balancer uses that information to route statements to specific workers. +The **Workload Manager** allows SQream workers to identify their availability to clients with specific service names. The load balancer uses that information to route statements to specific workers. Overview =============================== - -The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resoucres for various tasks. +The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resources for various tasks. For example: @@ -60,7 +59,7 @@ The configuration in this example allocates resources as shown below: - ✓ - ✓ -This configuration gives the ETL queue dedicated access to two workers, one of which cannot be used by regular queries. +This configuration gives the ETL queue dedicated access to one worker, which cannot be used.. Queries from management uses any available worker. diff --git a/reference/configuration.rst b/reference/configuration.rst deleted file mode 100644 index bf487496e..000000000 --- a/reference/configuration.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. _configuration_reference: - -************************* -Configuration -************************* diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 6845ae7cd..04b24a58f 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -171,7 +171,7 @@ Workload Management * - :ref:`subscribe_service` - Add a SQream DB worker to a service queue * - :ref:`unsubscribe_service` - - Remove a SQream DB worker to a service queue + - Remove a SQream DB worker from a service queue * - :ref:`show_subscribed_instances` - Return a list of service queues and workers diff --git a/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst b/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst index a26df0554..939d8918a 100644 --- a/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst +++ b/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst @@ -47,7 +47,7 @@ Notes * If the service name does not currently exist, it will be created -.. warning:: ``UNSUBSCRIBE_SERVICE`` applies the service subscription immediately, but the setting applies for the duration of the session. To apply a persistent setting, use the ``initialSubscribedServices`` configuration setting. Read the :ref:`Workload manager guide` for more information. +.. warning:: ``UNSUBSCRIBE_SERVICE`` removes the service subscription immediately, but the setting applies for the duration of the session. To apply a persistent setting, use the ``initialSubscribedServices`` configuration setting. Read the :ref:`Workload manager guide` for more information. Examples =========== diff --git a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst index 2a60146e0..e5f4b11e5 100644 --- a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst @@ -20,4 +20,4 @@ Exporting and Importing Configuration Files ------------------------- You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. -For more information about configuring your instance of SQream, see `Configuration Guides `_. +For more information about configuring your instance of SQream, see `Configuration Guides `_. \ No newline at end of file From 6e3cfd2bf5f06ef1c97c1b155aa7258cf75773ec Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 11:21:40 +0300 Subject: [PATCH 0060/1892] SQ-10052 --- data_type_guides/converting_and_casting_types.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index e4de6eeb7..bb6475646 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT(30))``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. :: @@ -23,4 +23,6 @@ SQream supports the following three data conversion types: :: -* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. \ No newline at end of file +* See the :ref:`SQL functions reference ` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. + +.. note:: SQream interprets integer constants exceeding the maximum bigint value as float constants, which may cause precision loss. \ No newline at end of file From e648c7b600be1453493cf0e417c0bf819f964f70 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 11:52:00 +0300 Subject: [PATCH 0061/1892] Moved show_server_status to Utility Commands --- reference/sql/sql_statements/index.rst | 2 - .../show_server_status.rst | 108 ------------------ 2 files changed, 110 deletions(-) delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_server_status.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 04b24a58f..cdaf8a94f 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -152,8 +152,6 @@ Monitoring statements allow a database administrator to execute actions in the s - Returns any existing locks in the database * - :ref:`show_node_info` - Returns a query plan for an actively running statement with timing information - * - :ref:`show_server_status` - - Shows running statements across the cluster * - :ref:`show_version` - Returns the version of SQream DB * - :ref:`stop_statement` diff --git a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst b/reference/sql/sql_statements/monitoring_commands/show_server_status.rst deleted file mode 100644 index f59f79ccc..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_server_status.rst +++ /dev/null @@ -1,108 +0,0 @@ -.. _show_server_status: - -******************** -SHOW_SERVER_STATUS -******************** - -``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. - -To list active statements on the current worker only, see :ref:`show_connections`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_server_status_statement ::= - SELECT SHOW_SERVER_STATUS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``service`` - - The service name for the statement - * - ``instance`` - - The worker ID - * - ``connection_id`` - - Connection ID - * - ``serverip`` - - Worker end-point IP - * - ``serverport`` - - Worker end-point port - * - ``database_name`` - - Database name for the statement - * - ``user_name`` - - Username running the statement - * - ``clientip`` - - Client IP - * - ``statementid`` - - Statement ID - * - ``statement`` - - Statement text - * - ``statementstarttime`` - - Statement start timestamp - * - ``statementstatus`` - - Statement status (see table below) - * - ``statementstatusstart`` - - Last updated timestamp - -.. include from here: 66 - - -.. list-table:: Statement status values - :widths: auto - :header-rows: 1 - - * - Status - - Description - * - ``Preparing`` - - Statement is being prepared - * - ``In queue`` - - Statement is waiting for execution - * - ``Initializing`` - - Statement has entered execution checks - * - ``Executing`` - - Statement is executing - * - ``Stopping`` - - Statement is in the process of stopping - - -.. include until here 86 - -Notes -=========== - -* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. - -Examples -=========== - -Using ``SHOW_SERVER_STATUS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- - sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 - -The statement ID is ``128``, running on worker ``192.168.1.91``. From 4c0b91d170ef76eb295441588e972819d336a086 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 15 May 2022 12:21:33 +0300 Subject: [PATCH 0062/1892] Moved show_server_status to Utility Commands --- reference/sql/sql_statements/index.rst | 22 -- .../monitoring_commands/explain.rst | 59 ---- .../monitoring_commands/show_connections.rst | 78 ----- .../monitoring_commands/show_locks.rst | 79 ----- .../monitoring_commands/show_node_info.rst | 310 ------------------ .../monitoring_commands/stop_statement.rst | 77 ----- 6 files changed, 625 deletions(-) delete mode 100644 reference/sql/sql_statements/monitoring_commands/explain.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_connections.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_locks.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/show_node_info.rst delete mode 100644 reference/sql/sql_statements/monitoring_commands/stop_statement.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index cdaf8a94f..d0a6c04c8 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -133,29 +133,7 @@ Utility Commands - Stops or aborts an active statement -Monitoring -=============== -Monitoring statements allow a database administrator to execute actions in the system, such as aborting a query or get information about system processes. - -.. list-table:: Monitoring - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`explain` - - Returns a static query plan for a statement - * - :ref:`show_connections` - - Returns a list of jobs and statements on the current worker - * - :ref:`show_locks` - - Returns any existing locks in the database - * - :ref:`show_node_info` - - Returns a query plan for an actively running statement with timing information - * - :ref:`show_version` - - Returns the version of SQream DB - * - :ref:`stop_statement` - - Stops a query (or statement) if it is currently running Workload Management ====================== diff --git a/reference/sql/sql_statements/monitoring_commands/explain.rst b/reference/sql/sql_statements/monitoring_commands/explain.rst deleted file mode 100644 index e9b7e7ee9..000000000 --- a/reference/sql/sql_statements/monitoring_commands/explain.rst +++ /dev/null @@ -1,59 +0,0 @@ -.. _explain: - -***************** -EXPLAIN -***************** - -``EXPLAIN`` returns a static query plan, which can be used to debug query plans. - -To see an actively running query or statement, use :ref:`show_node_info` instead. - -See also :ref:`show_node_info`, :ref:`show_server_status`. - - -Permissions -============= - -The role must have the ``SELECT`` permissions for any tables referenced by the query. - -Syntax -========== - -.. code-block:: postgres - - explain_statement ::= - SELECT EXPLAIN(query_stmt) - ; - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``query_stmt`` - - The select query to generate the plan for. - -Notes -=========== - -Use dollar-quoting to escape the query text - -Examples -=========== - -Generating a static query plan ----------------------------------- - -.. code-block:: psql - - t=> SELECT EXPLAIN($$SELECT DATEADD(hour,1,dt) FROM cool_dates$$); - Select - Specific (TTNative Gpu) (dateadd@null := dt@null, - dateadd@val := (pure_if dt@null "0" (addHoursdt2dt dt@val "1"))) - Table Scan - public.cool_dates ("dt@null", "dt@val") [] - diff --git a/reference/sql/sql_statements/monitoring_commands/show_connections.rst b/reference/sql/sql_statements/monitoring_commands/show_connections.rst deleted file mode 100644 index 1bd320a4c..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_connections.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _show_connections: - -******************** -SHOW_CONNECTIONS -******************** - -``SHOW_CONNECTIONS`` returns a list of active sessions on the current worker. - -To see sessions across the cluster, see :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_connections_statement ::= - SELECT SHOW_CONNECTIONS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active sessions. If no sessions are active on the worker, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``ip`` - - The worker hostname or IP - * - ``conn_id`` - - Connection ID - * - ``conn_start_time`` - - Connection start timestamp - * - ``stmt_id`` - - Statement ID. Connections with no active statement display ``-1``. - * - ``stmt_start_time`` - - Statement start timestamp - * - ``stmt`` - - Statement text - - -Notes -=========== - -* This utility shows the active connections. Some sessions may be actively connected, but not currently running a statement. - -* A connection is typically reused. There could be many statements under a single connection ID. - -Examples -=========== - -Using ``SHOW_CONNECTIONS`` to get statement IDs ----------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can see the connection started at 00:01:27, while the statement started at 00:38:18. \ No newline at end of file diff --git a/reference/sql/sql_statements/monitoring_commands/show_locks.rst b/reference/sql/sql_statements/monitoring_commands/show_locks.rst deleted file mode 100644 index d5e7c02ec..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_locks.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. _show_locks: - -******************** -SHOW_LOCKS -******************** - -``SHOW_LOCKS`` returns a list of locks from across the cluster. - -Read more about locks in :ref:`concurrency_and_locks`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_locks_statement ::= - SELECT SHOW_LOCKS() - ; - -Parameters -============ - -None - -Returns -========= - -This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - ``stmt_id`` - - Statement ID that caused the lock. - * - ``stmt_string`` - - Statement text - * - ``username`` - - The role that executed the statement - * - ``server`` - - The worker node's IP - * - ``port`` - - The worker node's port - * - ``locked_object`` - - The full qualified name of the object being locked, separated with ``$`` (e.g. ``table$t$public$nba2`` for table ``nba2`` in schema ``public``, in database ``t`` - * - ``lockmode`` - - The locking mode (:ref:`inclusive` or :ref:`exclusive`). - * - ``statement_start_time`` - - Timestamp the statement started - * - ``lock_start_time`` - - Timestamp the lock was obtained - - -Examples -=========== - -Using ``SHOW_LOCKS`` to see active locks ---------------------------------------------------- - -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. - - -.. code-block:: psql - - t=> SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - - diff --git a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst b/reference/sql/sql_statements/monitoring_commands/show_node_info.rst deleted file mode 100644 index 9c1e1ec11..000000000 --- a/reference/sql/sql_statements/monitoring_commands/show_node_info.rst +++ /dev/null @@ -1,310 +0,0 @@ -.. _show_node_info: - -******************** -SHOW_NODE_INFO -******************** - -``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. - -The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. - -See also :ref:`explain`, :ref:`show_server_status`. - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - show_node_info_statement ::= - SELECT SHOW_NODE_INFO(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to explore - -Returns -========= - -This utility returns details of the execution nodes, if the statement is still running. - -If the statement has finished, or the statment ID does not exist, the utility returns an empty result set. - -.. list-table:: Result columns - :widths: auto - :header-rows: 1 - - * - Column name - - Description - * - ``stmt_id`` - - The ID for the statement - * - ``node_id`` - - This node's ID in this execution plan - * - ``node_type`` - - The node type - * - ``rows`` - - Total number of rows this node has processed - * - ``chunks`` - - Number of chunks this node has processed - * - ``avg_rows_in_chunk`` - - Average amount of rows that this node processes in each chunk (``rows / chunks``) - * - ``time`` - - Timestamp for this node's creation - * - ``parent_node_id`` - - The ``node_id`` of this node's parent - * - ``read`` - - Total data read from disk - * - ``write`` - - Total data written to disk - * - ``comment`` - - Additional information (e.g. table name for ``ReadTable``) - * - ``timesum`` - - Total elapsed time for this execution node's processing - - -.. _node_types: - -Node types -============= - -This is a full list of node types: - -.. list-table:: Node types - :widths: auto - :header-rows: 1 - - * - Column name - - Execution location - - Description - * - ``AddChunkId`` - - - - Used during insert operations - * - ``AddSequences`` - - - - Used during insert operations, with :ref:`identity columns` - * - ``AddMinMaxMetadata`` - - - - Used to calculate ranges for the :ref:`chunk metadata system` - * - ``AddTopSortFilters`` - - - - An operation to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Compress`` - - CPU and GPU - - Compress data with both CPU and GPU schemes - * - ``CpuDecompress`` - - CPU - - Decompression operation, common for longer ``TEXT`` types - * - ``CpuLoopJoin`` - - CPU - - A non-indexed nested loop join, performed on the CPU - * - ``CpuReduce`` - - CPU - - A reduce process performed on the CPU, primarily with ``DISTINCT`` aggregates (e.g. ``COUNT(DISTINCT ...)``) - * - ``CpuToGpu``, ``GpuToCpu`` - - - - An operation that moves data to or from the GPU for processing - * - ``CpuTransform`` - - CPU - - A transform operation performed on the CPU, usually a :ref:`scalar function` - * - ``CrossJoin`` - - - - A join without a join condition - * - ``DeferredGather`` - - CPU - - Merges the results of GPU operations with a result set [#f0]_ - * - ``Distinct`` - - GPU - - Removes duplicate rows (usually as part of the ``DISTINCT`` operation) - * - ``Distinct_Merge`` - - CPU - - The merge operation of the ``Distinct`` operation - * - ``Filter`` - - GPU - - A filtering operation, such as a ``WHERE`` or ``JOIN`` clause - * - ``GpuCopy`` - - GPU - - Copies data between GPUs or within a single GPU - * - ``GpuDecompress`` - - GPU - - Decompression operation - * - ``GpuReduceMerge`` - - GPU - - An operation to optimize part of the merger phases in the GPU - * - ``GpuTransform`` - - GPU - - A transformation operation such as a type cast or :ref:`scalar function` - * - ``Hash`` - - CPU - - Hashes the output result. Used internally. - * - ``JoinSideMarker`` - - - - Used internally. - * - ``LiteralValues`` - - CPU - - Creates a virtual relation (table), when :ref:`values` is used - * - ``LocateFiles`` - - CPU - - Validates external file paths for foreign data wrappers, expanding directories and GLOB patterns - * - ``LoopJoin`` - - GPU - - A non-indexed nested loop join, performed on the GPU - * - ``MarkMatchedJoinRows`` - - - - Used in outer joins, matches rows for larger join operations - * - ``NullifyDuplicates`` - - - - Replaces duplicate values with ``NULL`` to calculate distinct aggregates - * - ``NullSink`` - - CPU - - Used internally - * - ``ParseCsv`` - - CPU - - A CSV parser, used after ``ReadFiles`` to convert the CSV into columnar data - * - ``PopNetworkQueue`` - - CPU - - Fetches data from the network queue (e.g. when used with :ref:`insert`) - * - ``PushToNetworkQueue`` - - CPU - - Sends result sets to a client connected over the network - * - ``ReadCatalog`` - - CPU - - Converts the :ref:`catalog` into a relation (table) - * - ``ReadFiles`` - - CPU - - Reads external flat-files - * - ``ReadOrc`` - - CPU - - Reads data from an ORC file - * - ``ReadParquet`` - - CPU - - Reads data from a Parquet file - * - ``ReadTable`` - - CPU - - Reads data from a standard table stored on disk - * - ``ReadTableMetadata`` - - CPU - - Reads only table metadata as an optimization - * - ``Rechunk`` - - - - Reorganize multiple small :ref:`chunks` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY` is used - * - ``Reduce`` - - GPU - - A reduction operation, such as a ``GROUP BY`` - * - ``ReduceMerge`` - - GPU - - A merge operation of a reduction operation, helps operate on larger-than-RAM data - * - ``ReorderInput`` - - - - Change the order of arguments in preparation for the next operation - * - ``SeparatedGather`` - - GPU - - Gathers additional columns for the result - * - ``Sort`` - - GPU - - Sort operation [#f1]_ - * - ``SortMerge`` - - CPU - - A merge operation of a sort operation, helps operate on larger-than-RAM data - * - ``SortMergeJoin`` - - GPU - - A sort-merge join, performed on the GPU - * - ``TakeRowsFromChunk`` - - - - Take the first N rows from each chunk, to optimize ``LIMIT`` when used alongside ``ORDER BY`` - * - ``Top`` - - - - Limits the input size, when used with ``LIMIT`` (or its alias ``TOP``) - * - ``UdfTransform`` - - CPU - - Executes a :ref:`user defined function` - * - ``UnionAll`` - - - - Combines two sources of data when ``UNION ALL`` is used - * - ``VarCharJoiner`` - - - - Used internally - * - ``VarCharSplitter`` - - - - Used intenrally - * - ``Window`` - - GPU - - Executes a non-ranking :ref:`window function` - * - ``WindowRanking`` - - GPU - - Executes a ranking :ref:`window function` - * - ``WriteTable`` - - CPU - - Writes the result set to a standard table stored on disk - -.. rubric:: Footnotes - -.. [#f0] Gathers columns which should be returned. This node typically spends most of the time on decompressing additional columns. - -.. [#f1] A GPU sort operation can be added by the statement compiler before ``GROUP BY`` or ``JOIN`` operations. - -Statement statuses -======================= - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Notes -=========== - -* This utility shows the execution information for active statements. Once a query has finished execution, the information is no longer available using this utility. See :ref:`logging` for more information about extracting the information from the logs. - -* This utility is primarily intended for troubleshooting with SQream support. - -Examples -=========== - -Getting execution details for a statement ------------------------------------------------- - - -.. code-block:: psql - - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 - sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 - - -The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. - -The query text is ``SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1;`` - -.. code-block:: psql - - t=> SELECT SHOW_NODE_INFO(176); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- - 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 - 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 - 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 - 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 - 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 - 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 - 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 - 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 - 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 - 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 - 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 - diff --git a/reference/sql/sql_statements/monitoring_commands/stop_statement.rst b/reference/sql/sql_statements/monitoring_commands/stop_statement.rst deleted file mode 100644 index 30efc25b5..000000000 --- a/reference/sql/sql_statements/monitoring_commands/stop_statement.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _stop_statement: - -******************** -STOP_STATEMENT -******************** - -``STOP_STATEMENT`` stops or aborts an active statement. - -To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. - -.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - -Syntax -========== - -.. code-block:: postgres - - stop_statement_statement ::= - SELECT STOP_STATEMENT(stmt_id) - ; - - stmt_id ::= bigint - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``stmt_id`` - - The statement ID to stop - -Returns -========= - -This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. - - -Notes -=========== - -* This utility always succeeds even if the statement does not exist, or has already stopped. - -Examples -=========== - -Using :ref:`show_connections` to get statement IDs ----------------------------------------------------- - -.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. - -.. code-block:: psql - - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | - - -The statement ID we're interested in is ``129``. We can now stop this statement: - -.. code-block:: psql - - t=> SELECT STOP_STATEMENT(129) - executed - From 2fdcb0647adb8d2a30bcd41521be1b18d80b218e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 19 May 2022 16:09:58 +0300 Subject: [PATCH 0063/1892] Avro, Encryption, Update Published to private 2022.1 branch to share with Product team. --- _static/images/new.png | Bin 0 -> 1503 bytes _static/images/new_2022.1.png | Bin 0 -> 2056 bytes data_ingestion/avro.rst | 182 +++++++----------- feature_guides/data_encryption.rst | 6 +- .../sql_statements/dml_commands/update.rst | 9 +- 5 files changed, 83 insertions(+), 114 deletions(-) create mode 100644 _static/images/new.png create mode 100644 _static/images/new_2022.1.png diff --git a/_static/images/new.png b/_static/images/new.png new file mode 100644 index 0000000000000000000000000000000000000000..a0df8ff0fc2fc25204895ade1d958e69c4651696 GIT binary patch literal 1503 zcmV<51t9u~P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1$0S7K~!i%<(fTc z6hRcnCqanuBgq-Run=P5MLdHZpDr-+_E{v2;-X6J6-zIktUlO}7esmjx*=FS~+ z|Gs(s+8vfkQR}}+vFJVv1+#0HIe5??W&HA6>m_SFEs0m+E;NPq_V^o%Y;0`~JPZ_Jt(*2t$iSyL`ExtFg6svF+-z zQ&Zjv0Wlw85QeJr{~xVdWhW-QD=IAX5gfF3tv)SLBO`Wt+UeOd+uN&qLye93kv%=S z>+cjY%=ox>NJQWxEV29%6f!%jdqcrHLSLWm`fG(~3Km_nFK_enX5T(DHRTU$qP^XW zjd{B$xS-b6194ESE$57m_+JcJDmHM>>! z=~EP2^>Y2XdGf^DhYx!r52%JH9{?-;!2@&YlGDwb=IvY8xO%nAcOk4Q+qZjzV40)5 z3L7?fBZQ|sdgP5feEeu`+%R_cZtc80B5c9B6Vx(Eiz7xKPK?I|&kAQ_EW|?$!$RWA zjZvoBtE#KZ*v*@DYaS7{aMh?SWtxu=^Fm_kp$C;acqhU}h_eZ5PTT__Eth4et{Y%%Iu{b}M>RE@Z{Pgd`*lV~y-{^b+1u;3 zR6u2%kPjccfx(0+Y0DOG0M3S7Be`tjM)yg!ZS%&xd)}ytI-l~1YRA$L7)pt81Uo+} z0EI9B878o~+Z~Ycf1q2kV-?gQD@xmLz^XKjpfy4OPw8?$S zj(>dIeS)o9y)iK0jfW4tQ4@tilRa|83=aC^{J47-(bVJ(GCgh9uXhGE1jXXdL)7&% zXPg20`poIm&cM>3TN8nUu(t>q88HVAI0M^-9Xp&MKj!XTvv;pE@Mr}OVySj?xWiJ( zueB2=^i+Ak^Mf57{nb6BQn;mroxRr3%f_5iC67~aer9gj0Z8sw)i$S=EV2Fl#=Y3D zRg@QeK(z~KU%trvBTT^ao z7;3N=fk3S}N!p~sK?~(k^pSv=>hHJR-R=dr`i_5Bt*tI_E?-XkN09|s`vX%AH1)Cb8WaEk002ovPDHLk FV1f&!$;JQx literal 0 HcmV?d00001 diff --git a/_static/images/new_2022.1.png b/_static/images/new_2022.1.png new file mode 100644 index 0000000000000000000000000000000000000000..fc043757cd3728088194fbb6951830f5bf7fcc0c GIT binary patch literal 2056 zcmV+j2>17iP)X1^@s6uYt=p00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L2c1boK~#8N?OaVx z<1iF<3P%A6q`5#A9H2;L#{pPm!G;C1n*+>_F4%OzVh+HLNb~?*^a3MMi5>-#dCz{& zdHHeT)ak%5`6R1p+800D@852tx3{-kN!*{Q$;+k67B_Tb#E20FTcxhA)I|LN{g~1{ zr7B9aRFlJ*id3w!%}V7*bbG{z5rAg>n3xyB{ZIG;Ao)>NAn;BHhllFm?4E9TV0#Z8 z0?px>ia>$?X)IwZXEX<&bxd2dk`P5$9-#rxlk256pqE&1*1>NVeVo90Hqdd~cmKijy~*EW`8*g;Zo`7|tH(ws$zGn~SGM+1#H1+<5?GuH%=<$I^vv!h4Xz5&mAOOH}o;a-U z@>(4@=@Uc0eozN4`q2JE={o^ycm^`NrnkWm-sp}L!Dv^Zsg0gScp}q0H2EudqE9~t zVPR_)lbRhv)7r9C-IYGH|4{mlCTMXDvxMb1#1lcY&o$2>PxPuHt*J1g^A;1E%vFX; zsK7Gy$&W_t2is@6ZrLwKHTCF5Wr?|rUS7=wgQJfwdTn_z3c1s-7NPxz(zgLT?BwK@ zJX``EZl$tQ{Yf~E&Q(r&fKi!IBF|7x{RZ{>MJ{%Is}3;f3q>tyKZN(-x~s_~h8*ClAh7>n`gYh5akT)!*S7}3k;=c(v5<_diXQ1X>qkfR3tZm(0BwAsx-rc=y|({LPj^(8ECU-?&ydR5zb``R_l0AM zR@N`5M8aM60todgwF1&BKO%vzZR$#J_y$Z`*w`FHAbmmLP!7D>cT$jANaq{M^#G3p z7ue-FWMbT;*noWgovsE3=7>DzRCv$7h0y*#nty~x2wC<-y)iB4M~#-Y3Kn<((3BGK zQp4jF2%#`GHm`(h?DBPj3_NL;s^4J?I+R5d`R8!W1A$5ekonQ=)o%HbH;Rz1WYsy8;{^GFLP1#)wcc-_P_7T`f>b@|o=_FQ zq4Fz)PjVmH|33NO13-xal19eOO1+cy@3XUv6I4pX8(Zac0EcuoToa)j?{RS`Xmh8+ zYkaEYbRX~)z$2jyuU(oA^XD7#e-#BfHaU+^v90WhIw!LQ3(Ai=H)0E=?X`KvkRhEW zr;Xy$UI&MCR1UWlo)1b+c?&^(^V<*E6}<$I=g6I_S@>4SzKQ}NFqZ`*?&RV1#Y8so zDJhYtdG8Kb6j_P7bHx7$&JmibY@HAx9hSPOY+c*y;E)c#BL+Mi3O+i=L0bsJ_Fus+ z0!VY@-d7{Y0*XtAzLEm@KqEs9aY5tO@R<{Z`B;CYxx-jwzk7~ zO)bG^aqD;{v@A*U(oy?On!od5!Nxu-N84R|`S8)!>_Nj8TG2-~hjGZyYP8~XJG9#RSh*^l;s$UI(UoL+0rCYtsM?0bO1*DV zmB*A@FyMVY$0Ib=(+mO}&o_l~3>&V%i1!sr!B|_zfk&F~G{Qc>xt7M-9X@wKpR7n# zmH@wWOGEPCG{vF)htgv>t*0FL9CUrL=t655&+B<0r3buSBK~7xsm$-kLEzH2kEvpf z81d=BdSZ^OVYOA1xIz24C}7X4jTkYagoghias1oQ=#55boezEA AS + SELECT * FROM ; + +After creating a table you can ingest data from an Avro file into SQream using the following syntax: + +.. code-block:: postgres + + avro_fdw [OPTIONS(option=value[,...])] + +Example +----------- +The following is an example of creating a table: + +.. code-block:: postgres + + CREATE TABLE nba AS + SELECT * FROM ext_nba; + +The following is an example of loading data from an Avro file into SQream: + +.. code-block:: postgres + + WRAPPER avro_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.avro' + ); + +For more examples, see :ref:`additional_examples`. + +Avro Data Types +=========== Avro includes the following data types: .. contents:: @@ -48,12 +90,6 @@ The following table shows the supported **Primitive** data types: | ``string`` | | Supported | Supported | | +-------------+-----------+---------------+-----------+--------------+ - - - - - - Complex Data Types -------------- The following table shows the supported **Complex** data types: @@ -76,8 +112,6 @@ The following table shows the supported **Complex** data types: | ``fixed`` | | | | | +------------+-----------+---------------+-----------+-----------+ - - Logical Data Types -------------- The following table shows the supported **Logical** data types: @@ -107,72 +141,20 @@ The following table shows the supported **Logical** data types: +----------------------------+-----------+---------------+-----------+---------+ | ``duration`` | | | | | +----------------------------+-----------+---------------+-----------+---------+ + +.. note:: Number types include **tinyint**, **smallint**, **int**, **bigint**, **real** and **float**, and **numeric**. String types include **text**. Mapping Objects to Rows =============== -When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. - -Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. +When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. -Ingesting Avro Files +Best Practices ==================== -This section describes how to ingest Avro files into SQream and covers the following: - +This section describes the best practices when ingesting Avro files into SQream: .. contents:: :local: :depth: 1 - - -Preparing Your Avro Source File ----------- -Prepare your Avro source files according to the following requirements: - -* RFC 4180 standard CSV files, but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). - - :: - -* Files are encoded with UTF-8 or ASCII. - - :: - -* Field delimiter is an ASCII character or characters. - - :: - -* Record delimiter, also known as a new line separator, is a Unix-style newline (``\n``), DOS-style newline (``\r\n``), or Mac style newline (``\r``). - - :: - -* If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. - - :: - -* Fields can be enclosed by double-quotes (optional), or mandatory quotes if they contain one of the following characters: - - * The record delimiter or field delimiter. - - :: - - * A double quote character. - - :: - - * A newline. - -SQream does not support other modes of escaping, such as ``1,"What are \"birds\"?"``. - -``NULL`` values can be marked in the following ways in Avro files: - - * An explicit null marker. For example, ``col1,\N,col3``. - - :: - - * An empty field delimited by the field delimiter. For example, ``col1,,col3``. - - .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field and not ``NULL``. - -For more information about standard CSV files, see `RFC 4180 standard CSVs `_. Making Avro Files Accessible to Workers --------------------- @@ -190,16 +172,16 @@ For more information about restricted worker access, see :ref:`workload_manager` Basing Your Table Structure on Inserted Tables --------------------- -Before loading data, you must build the ``CREATE EXTERNAL TABLE`` to correspond with the file structure of the inserted table. +Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. -The example in this section is based on the source ``nba.parquet`` table shown below: +The example in this section is based on the source ``nba.avro`` table shown below: -.. csv-table:: nba.parquet +.. csv-table:: nba.avro :file: nba-t10.csv :widths: auto :header-rows: 1 -The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the **nba.parquet** table: +The following example shows the correct file structure used to create the ``CREATE FOREIGN TABLE`` statement based on the **nba.avro** table: .. code-block:: postgres @@ -216,23 +198,23 @@ The following example shows the correct file structure used to create the ``CREA College TEXT(40), Salary FLOAT ) - WRAPPER parquet_fdw + WRAPPER avro_fdw OPTIONS ( - LOCATION = 's3://sqream-demo-data/nba.parquet' + LOCATION = 's3://sqream-demo-data/nba.avro' ); .. tip:: An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. -.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. +.. note:: The **nba.avro** file is stored on S3 at ``s3://sqream-demo-data/nba.avro``. Verifying Your Table Output --------------------- Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. -The following is an example of the output based on the **nba.parquet** table: +The following is an example of the output based on the **nba.avro** table: .. code-block:: psql @@ -252,38 +234,18 @@ The following is an example of the output based on the **nba.parquet** table: .. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. -Loading Data into SQream ---------------------- +.. _additional_examples: -Syntax -~~~~~~~~~~~~~~~~~~~~~ -The following is the correct syntax for loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE
AS - SELECT * FROM ; - -The following is an example of loading data into SQream: - -.. code-block:: postgres - - CREATE TABLE nba AS - SELECT * FROM ext_nba; - -For more information about the **CREATE TABLE AS** statement, see :ref:`create_table_as`. - -Examples -~~~~~~~~~~~~~~~~~~~~~ - -This section includes the following examples of loading data into SQream: +Additional Examples +=============== +This section includes the following additional examples of loading data into SQream: .. contents:: :local: :depth: 1 Omitting Unsupported Column Types -********************** +-------------- When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. In the example below, the ``Position`` column is not supported due its type. @@ -291,11 +253,10 @@ In the example below, the ``Position`` column is not supported due its type. .. code-block:: postgres CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; - + SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; Modifying Data Before Loading -********************** +-------------- One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement @@ -309,19 +270,18 @@ In the example below, the ``Position`` column is set to the default ``NULL``. FROM ext_nba ORDER BY weight; - Loading a Table from a Directory of Avro Files on HDFS -********************** +-------------- The following is an example of loading a table from a directory of Avro files on HDFS: .. code-block:: postgres CREATE FOREIGN TABLE ext_users (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER parquet_fdw + WRAPPER avro_fdw OPTIONS ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.avro' ); CREATE TABLE users AS SELECT * FROM ext_users; @@ -329,16 +289,16 @@ The following is an example of loading a table from a directory of Avro files on For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. Loading a Table from a Directory of Avro Files on S3 -********************** +-------------- The following is an example of loading a table from a directory of Avro files on S3: .. code-block:: postgres CREATE FOREIGN TABLE ext_users (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER parquet_fdw + WRAPPER avro_fdw OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', + ( LOCATION = 's3://pp-secret-bucket/users/*.avro', AWS_ID = 'our_aws_id', AWS_SECRET = 'our_aws_secret' ); diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 4e51a28aa..e5b30c94a 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -4,8 +4,12 @@ Data Encryption *********************** -The **Data Encryption** page describes the following: +The **Data Encryption** page |icon-new_2022.1| describes the following: +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png + :align: middle + :width: 110 + .. toctree:: :maxdepth: 1 :titlesonly: diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 143363b3b..82262d884 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -3,8 +3,11 @@ ********************** UPDATE ********************** +The **UPDATE** statement page |icon-new_2022.1| describes the following: -The **UPDATE** statement page describes the following: +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png + :align: middle + :width: 110 .. contents:: :local: @@ -12,7 +15,7 @@ The **UPDATE** statement page describes the following: Overview ========== -The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. +The ``UPDATE`` statement is used to modify the value of certain columns in existing rows without creating a table. It can be used to do the following: @@ -20,6 +23,8 @@ It can be used to do the following: * Setting columns based on the values of others. +The ``UPDATE`` statement cannot be used to reference other tables in the ``WHERE`` or ``SET`` clauses. + Syntax ========== The following is the correct syntax for the ``UPDATE`` command: From f9cd06dfe305ce662960b59f3858208641f8e19c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 19 May 2022 16:12:34 +0300 Subject: [PATCH 0064/1892] Encryption, Update, Avro Published the 2022.1 features and updated the respective pages on the private 2022.1 branch to show Product team. --- releases/2022.1.rst | 42 ++++++++---------------------------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 51a7333cc..b1b6a61ae 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -13,10 +13,9 @@ Version Content ---------- The 2022.1 Release Notes describes the following: -* Example - Major feature release targeted for all on-premises customers. -* Example - Basic Cloud functionality. - -**Comment** - *This will be done at the end.* +* Enhanced security features. +* New data manipulation command. +* Additional data ingestion format. New Features ---------- @@ -32,6 +31,8 @@ SQream now supports data encryption mechanisms in accordance with **General Data For more information, see `Data Encryption `_. +**Comment** - *Information regarding performance degradation, pending.* + Update Feature ************ SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows without creating a table. @@ -44,18 +45,9 @@ SQream now supports ingesting data from Avro files. For more information, see `Inserting Data from Avro `_. -Main Features --------- -The following list describes the main features: - -* Main feature -* Main feature - -**Comment** - *This will be done at the end.* - Resolved Issues --------- -The following table lists the issues that were resolved in Version 2021.2: +The following table lists the issues that were resolved in Version 2022.1: .. list-table:: :widths: 17 200 @@ -70,36 +62,18 @@ The following table lists the issues that were resolved in Version 2021.2: * - SQ-xxxx - Text -**Comment** - *I will be updated regarding which resolved issues to include.* +**Comment** - *The table above will be updated regarding which resolved issues to include.* Operations and Configuration Changes -------- -**Comment** - *TBD* - - -Subject -************ -Text - - - - -Subject -************ -Text - - +No relevant operations and configuration changes were made. Naming Changes ------- -**Comment** - *TBD* - No relevant naming changes were made. Deprecated Features ------- -**Comment** - *TBD* - No features were depecrated. Known Issues and Limitations From 0bb07df6dc07046aeb3d5f5ca8dd8bc2e73b3366 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 19 May 2022 16:21:29 +0300 Subject: [PATCH 0065/1892] Added date Needs to be updated on release date --- feature_guides/data_encryption.rst | 1 - releases/index.rst | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index e5b30c94a..82e1bf657 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -3,7 +3,6 @@ *********************** Data Encryption *********************** - The **Data Encryption** page |icon-new_2022.1| describes the following: .. |icon-new_2022.1| image:: /_static/images/new_2022.1.png diff --git a/releases/index.rst b/releases/index.rst index d06a7a8bf..e23036f7a 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -13,7 +13,7 @@ Release Notes * - Version - Release Date * - :ref:`2022.1` - - April 17, 2022 + - MM DD, YYYY * - :ref:`2021.2` - September 13, 2021 * - :ref:`2021.1` From b65615c5287cef86975ff8d2f2c605f099777f42 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 14:25:50 +0300 Subject: [PATCH 0066/1892] Replaced missed instances of VARCHAR with TEXT --- data_type_guides/converting_and_casting_types.rst | 2 +- .../utility_commands/execute_saved_query.rst | 14 +++++++------- .../utility_commands/show_node_info.rst | 2 +- ...tements_and_running_queries_from_the_editor.rst | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index bb6475646..44579a068 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO VARCHAR(30))``. +* ``CAST( TO )``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT(30))``. :: diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index 6fe41fa08..39675d47f 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -8,7 +8,7 @@ EXECUTE_SAVED_QUERY Read more in the :ref:`saved_queries` guide. -See also: ref:`save_query`, :ref:`drop_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. +See also: :ref:`save_query`, :ref:`drop_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. Permissions ============= @@ -53,7 +53,7 @@ Notes * Query parameters can be used as substitutes for literal expressions. Parameters cannot be used to substitute identifiers, column names, table names, or other parts of the query. -* Query parameters of a string datatype (like ``VARCHAR``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) +* Query parameters of a string datatype (like ``text``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc) * Query parameters' types are inferred at compile time. @@ -66,14 +66,14 @@ Assume a table named ``nba``, with the following structure: CREATE TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ); diff --git a/reference/sql/sql_statements/utility_commands/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst index 345d16440..9c1e1ec11 100644 --- a/reference/sql/sql_statements/utility_commands/show_node_info.rst +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -108,7 +108,7 @@ This is a full list of node types: - Compress data with both CPU and GPU schemes * - ``CpuDecompress`` - CPU - - Decompression operation, common for longer ``VARCHAR`` types + - Decompression operation, common for longer ``TEXT`` types * - ``CpuLoopJoin`` - CPU - A non-indexed nested loop join, performed on the CPU diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst index 8fa91d945..e1b6765eb 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst @@ -223,7 +223,7 @@ The following table describes the DDL Optimizer screen: * - Column area - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. * - Run Optimizer - Starts the optimization process. From 89e6037be32c759df3487a23fe2af2fc09490b9e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 16:06:18 +0300 Subject: [PATCH 0067/1892] Fixed broken links. --- configuration_guides/current_configuration_method.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst index e7ca5c0d3..078e2dac2 100644 --- a/configuration_guides/current_configuration_method.rst +++ b/configuration_guides/current_configuration_method.rst @@ -704,8 +704,8 @@ Configuration Roles =========== SQream divides flags into the following roles, each with their own set of permissions: -* **`Administration flags `_**: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* **`Generic flags `_**: can be modified by standard users on a session basis. +* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. +* `Generic flags `_: can be modified by standard users on a session basis. Showing All Flags in the Catalog Table ======= From 842860c092fce79c3df27f875cddee91b45a8f80 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 17:02:43 +0300 Subject: [PATCH 0068/1892] Update 2022.1.rst --- releases/2022.1.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index b1b6a61ae..9a2de884e 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -35,7 +35,7 @@ For more information, see `Data Encryption `_. @@ -87,8 +87,7 @@ The the list below describes the following known issues and limitations: End of Support ------- -**Comment** - *TBD* - +This section is not relevant to the 2022.1 release notes. Upgrading to v2022.1 ------- From 1fa25d21a222683e65d8d352c691290fbd57cfa4 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 22 May 2022 17:12:48 +0300 Subject: [PATCH 0069/1892] Updated .Net Driver Link --- third_party_tools/client_drivers/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index d52b41e95..91cb94e8f 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -44,8 +44,7 @@ The following are applicable to Windows: For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. - -* **Net driver** - `SQream .Net driver v3.0.2 `_ +* **Net driver** - `SQream .Net driver v3.0.2 `_ From 2a4ae2eef990dfd1e7b3c6dfa88ff2b25e5d97d3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 24 May 2022 10:34:50 +0300 Subject: [PATCH 0070/1892] Updated --- .../sql_statements/dml_commands/update.rst | 104 +----------------- 1 file changed, 4 insertions(+), 100 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 82262d884..19881d62c 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -3,7 +3,7 @@ ********************** UPDATE ********************** -The **UPDATE** statement page |icon-new_2022.1| describes the following: +The **UPDATE** statement page |icon-new_2022.1| describes the following: .. |icon-new_2022.1| image:: /_static/images/new_2022.1.png :align: middle @@ -15,7 +15,7 @@ The **UPDATE** statement page |icon-new_2022.1| describes the following: Overview ========== -The ``UPDATE`` statement is used to modify the value of certain columns in existing rows without creating a table. +The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. It can be used to do the following: @@ -23,8 +23,6 @@ It can be used to do the following: * Setting columns based on the values of others. -The ``UPDATE`` statement cannot be used to reference other tables in the ``WHERE`` or ``SET`` clauses. - Syntax ========== The following is the correct syntax for the ``UPDATE`` command: @@ -33,7 +31,6 @@ The following is the correct syntax for the ``UPDATE`` command: UPDATE target_table_name [[AS] alias1] SET column_name = expression [,...] - [FROM additional_table_name [[AS] alias2][,...]] [WHERE condition] The following is the correct syntax for triggering a clean-up: @@ -74,30 +71,6 @@ The **Examples** section includes the following examples: :local: :depth: 1 -Updating an Entire Table ------------------ -The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: - -.. image:: /_static/images/delete_optimization.png - -The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 WHERE true; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; - Performing Simple Updates ----------------- The following is an example of performing a simple update: @@ -106,72 +79,6 @@ The following is an example of performing a simple update: UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; -Updating Tables that Contain Multi-Table Conditions ------------------ -The following shows an example of updating tables that contain multi-table conditions: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + 1 - WHERE EXISTS ( - SELECT 1 FROM countries - WHERE countries.id=bands.country_id - AND country.name = 'Sweden' - ); - -You can also write the statement above using the FROM clause: - -.. code-block:: psql - - UPDATE bands - SET records_sold = records_sold + 1 - FROM countries - WHERE countries.id=bands.country_id AND country.name = 'Sweden'; - -Updating Tables that Contain Multi-Table Expressions ------------------ -The following shows an example of updating tables that contain multi-table expressions: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + - CASE - WHEN c.name = 'Israel' THEN 2 - ELSE 1 - END - FROM countries c - -Configuring Update Behavior ------------------ -The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. - -**Note to self** - *Check if the Studio documentation must be updated for this flag.* - -For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. - -When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). - -You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. - -**Comment** - *Does the system actually choose one, or does it generate an error?* - -Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: - -.. code-block:: postgres - - UPDATE bands - SET record_count = record_count + 1 - FROM countries c - WHERE c.name = 'Israel' - -However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. - -**Comment** - *Please review the paragraph above. I'm pretty sure I described this correctly.* - -For more information, see `SQream Acceleration Studio `_. - Identifying and Cleaning Up Tables --------------------------------------- **Comment** - *I copied and pasted this entire section from "DELETE". Does anything have to adjusted here for "UPDATE"?* @@ -240,11 +147,8 @@ The following shows an example of triggering a clean-up: Permissions ============= -Executing an ``UPDATE`` statement requires the following permissions: - -* Both ``UPDATE`` and ``SELECT`` permissions on the target table. -* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). +Executing an ``UPDATE`` statement requires both ``UPDATE`` and ``SELECT`` permissions on the target table. Locking and Concurrency ============= -Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file +Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table. \ No newline at end of file From 0be3b83caec8bdc6ac8f569104f3fafdfd1a4257 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 24 May 2022 12:18:54 +0300 Subject: [PATCH 0071/1892] Updated Encryption Pages based on Inon/Maya Meeting --- feature_guides/data_encryption.rst | 2 - feature_guides/data_encryption_methods.rst | 14 +-- feature_guides/data_encryption_overview.rst | 8 +- .../data_encryption_permissions.rst | 16 ---- feature_guides/data_encryption_process.rst | 88 ------------------- feature_guides/data_encryption_syntax.rst | 56 +++--------- feature_guides/data_encryption_types.rst | 6 +- 7 files changed, 26 insertions(+), 164 deletions(-) delete mode 100644 feature_guides/data_encryption_permissions.rst delete mode 100644 feature_guides/data_encryption_process.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 82e1bf657..dbc6152ed 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -16,6 +16,4 @@ The **Data Encryption** page |icon-new_2022.1| describes the following: data_encryption_overview data_encryption_methods data_encryption_types - data_encryption_process - data_encryption_permissions data_encryption_syntax \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index 0069b161c..dc6e7c122 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -3,7 +3,7 @@ *********************** Encryption Methods *********************** -The **Encryption Methods** section describes the following: +Data exists in one of following states and determines the encryption method: .. contents:: :local: @@ -11,16 +11,10 @@ The **Encryption Methods** section describes the following: Encrypting Data in Transit ---------------- -**In-transit data** refers to data files inserted from customer repositories using the COPY FROM command, and is transmitted to SQream over a TLS-encrypted channel using a JDBC or ODBC connection. +**Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. -For more information, see the following: - -* :ref:`copy_from` -* `JDBC `_ -* :ref:`odbc` +For more information, see :ref:`installing_nginx_proxy_over_secure_connection`. Encrypting Data at Rest ---------------- -For **data at rest,** housed physically on computer data, you can encrypt one or more column as needed according to your specifications. Data at rest is encrypted before being written into files, and decrypted after being read from them. All existing unencrypted historical and data inserted into this column at a later time is encrypted for the specified column values. Data at rest is encrypted (**Comment** - *And decrypted?*) using the **AES-256** algorithm. - -**Comment** - *Because the encryption keys are hidden from users, I didn't document them here. Please confirm that this is correct.* \ No newline at end of file +**Data at rest** refers to data stored on your hard drive or on the cloud. Because this data can be potentially intercepted **physically**, it requires a form of encryption that protects your data wherever you store it. SQream faciliates encryption by letting you encrypt any columns located in your database that you want to keep private. \ No newline at end of file diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 4c0455291..58bb7ea40 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -3,7 +3,11 @@ *********************** Overview *********************** -**Data Encryption** helps protect sensitive data by preventing unauthorized users from reading it in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. +**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. Encryption can be used for the following: @@ -25,4 +29,6 @@ Encryption can be used for the following: * Selecting data from an encrypted column. +For more information on the encryption syntax, see :ref:`data_encryption_syntax`. + For more information on GDPR compliance requirements, see the `GDPR checklist `_. \ No newline at end of file diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst deleted file mode 100644 index d9a132b45..000000000 --- a/feature_guides/data_encryption_permissions.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _data_encryption_permissions: - -*********************** -Permissions -*********************** -The **Permissions** page tells you how to create a table with encrypted columns as a superuser. - -Users with the appropriate encryption permission privilege's can encrypt and decrypt data. In addition, only superusers granted permission can view encrypted tables in the **sqream_catalog**. - -You can create a table with encrypted columns as a superuser as follows: - -.. code-block:: console - - $ create or replace table t_enc(c1 int encrypt); - -For more information about the SQream catalog, see the :ref:`catalog_reference`. \ No newline at end of file diff --git a/feature_guides/data_encryption_process.rst b/feature_guides/data_encryption_process.rst deleted file mode 100644 index e76e6a9cc..000000000 --- a/feature_guides/data_encryption_process.rst +++ /dev/null @@ -1,88 +0,0 @@ -.. _data_encryption_process: - -*********************** -Data Encryption Process -*********************** -The **Data Encryption Process** page describes end-to-end encryption process, and describes the following: - -.. contents:: - :local: - :depth: 1 - -The Encryption Process ----------------- -The following describes the encryption process: - -1. A user with the required encryption execution permission accesses the system. - - :: - -#. In the file to be uploaded, the user selects columns to encrypt. The syntax will (**Comment** - *"should" instead of "will"?)* includes the hint that triggers the encryption (see syntax section). - - :: - -#. The user provides the location of the master key for deriving (**Comment** - *...generating/activating?*) the encryption in the remote repository. This applies to both **KMS** and **IBM SKLM**. - - :: - - **Comment** - *The source doc says, "this section will not be applied in the MVP scope." Should it stay in this doc?* - - :: - -#. The user trigger (**Comment** - *"runs"?*) the COPY command to transport the data upon TLS session (not yet data at rest encryption) (**Comment** - *"Upon TLS session = when the TLS session is activated?"* - - :: - -#. When the data is successfully inserted into the SQream database, it is encrypted and saved. - -For more information, see the following: - -* More information on permissions, see :ref:`data_encryption_permissions`. - - :: - -* More information on which columns to encrypt, see the :ref:`Constraints` section below. - - :: - -* More information on triggering the encryption, and the master key location syntax, see :ref:`data_encryption_syntax`. - -The Decryption Process ----------------- -The following describes the encryption process: - -1. A user with the required encryption execution permission accesses the system. - - :: - -#. The user indicates the decryption. **Comment** - *"Indicates" = "triggers"?*) - - :: - -#. The user can view the data derived from a table holding the encrypted data by decrypting the data by providing the location of the master key and selecting the required fields. - - :: - - **Comment** - *the source doc said, "this section will not be applied in the MVP scope." Should it stay in this doc?* - -#. When the statement has ended, the user can view the data in a human readable format as plain text. - -For more information on triggering the decryption, see :ref:`data_encryption_syntax`. - -Encrypted Columns ----------------- -**Comment** - *This section and "Constraints" don't really seem like phases in a flow, at least the way they are currently described. If they really are part of a flow, we should discuss how to reword them.* - -Tables with encrypted columns are tagged with the ``encrypted`` label, allowing you to select what data to encrypt. - -.. _constraints: - -Constraints ----------------- -The encryption will be done in the database server- data at rest as the data will be encrypted in transit based on the TLS protocol. - -**Comment** - *I need some clarification on the sentence above.* - -Users without permissions to view tables with one or more encrypted table cannot view the entire table. - -**Comment** - *Please confirm that the above sentence is correct. Below is the original sentence:"* \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 85cef25ee..a7cb3e68d 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -3,55 +3,23 @@ *********************** Syntax *********************** -The **Syntax** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Encrypting a New Table ----------------- -The following is the correct syntax for **encrypting** a new table: +The following is the syntax for encrypting a new table: .. code-block:: console - CREATE TABLE client_name ( - first_name TEXT(128), - last_name TEXT(128), - salary INT(6) ENCRYPT); + CREATE TABLE ( + <(maximum string length)>, + + last_name <(maximum string length)>, + salary (<(maximum string length)>) ENCRYPT); The following is an example of encrypting a new table: .. code-block:: console - EXAMPLE - -**Comment** - *Please provide an actual example.* - -Decrypting a New Table ----------------- -The following is the correct syntax for **decrypting** a new table: - -.. code-block:: console - - SELECT * FROM TABLE; - -The following is an example of decrypting a new table: - -.. code-block:: console - - EXAMPLE - -**Comment** - *Please provide an actual example.* - -Incorrectly Encrypting or Decrypting Your Data ----------------- -Using the incorrect master key or location while encrypting or decrypting generates an error. - -**Comment** - *Can I get an example of this error to include in the doc?* - -**Comment** - *I thought that the master key was completely hidden from users... The internal doc says, "Master Key- the key will be generated within the server side, it will reside within a repository which will be hidden from the user."* - -In logs, master keys are masked to protect user privacy. Users are responsible for maintaining their master keys for the remote repository. - -**Comment** - *I'm not sure I fully understand the part about maintaing the master keys on the remote repository.* \ No newline at end of file + CREATE TABLE client_name ( + first_name TEXT(128), + last_name TEXT(128), + salary INT(6) ENCRYPT); + +.. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. \ No newline at end of file diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst index 3da9071c2..ad6d96dc3 100644 --- a/feature_guides/data_encryption_types.rst +++ b/feature_guides/data_encryption_types.rst @@ -3,12 +3,12 @@ *********************** Data Types *********************** -SQream's data encryption supports the following data types: +Typically speaking, sensitive pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +SQream's data encryption feature supports encrypting column-based data belonging to the following data types: * INT * BIGINT * TEXT -Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file From f312568993019bb8eaecdf772fccbfb5dff60566 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 24 May 2022 18:43:11 +0300 Subject: [PATCH 0072/1892] Updated Updated according to comments by: Avro: Ben Esh, Maya Faibish Update: Maayan Kurz Data Encryption: Inon Maman, Alex Karpov --- data_ingestion/avro.rst | 238 +++++++++++------- feature_guides/data_encryption_methods.rst | 2 +- feature_guides/flexible_data_clustering.rst | 16 -- .../flexible_data_clustering_chunks.rst | 18 -- ...ata_clustering_data_clustering_methods.rst | 180 ------------- ...flexible_data_clustering_data_examples.rst | 22 -- ...e_data_clustering_data_rechunking_data.rst | 11 - .../flexible_data_clustering_overview.rst | 16 -- feature_guides/index.rst | 1 - .../sql_statements/dml_commands/update.rst | 73 +----- releases/2022.1.rst | 38 ++- 11 files changed, 199 insertions(+), 416 deletions(-) delete mode 100644 feature_guides/flexible_data_clustering.rst delete mode 100644 feature_guides/flexible_data_clustering_chunks.rst delete mode 100644 feature_guides/flexible_data_clustering_data_clustering_methods.rst delete mode 100644 feature_guides/flexible_data_clustering_data_examples.rst delete mode 100644 feature_guides/flexible_data_clustering_data_rechunking_data.rst delete mode 100644 feature_guides/flexible_data_clustering_overview.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index 776d44bba..e943fe41c 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -17,48 +17,113 @@ Overview =========== **Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. Avro files are represented using the **Object Container File** format, in which the Avro schema is encoded alongside binary data. Multiple files loaded in the same transaction are serialized using the same schema. If they are not serialized using the same schema, an error message is displayed. SQream uses the **.avro** extension for ingested Avro files. -Loading Data into SQream -=========== +Making Avro Files Accessible to Workers +================ +To give workers access to files every node must have the same view of the storage being used. -Syntax ------------ -Before ingesting data into SQream from an Avro file, you must create a table using the following syntax: +The following apply for Avro files to be accessible to workers: -.. code-block:: postgres - - CREATE TABLE
AS - SELECT * FROM ; - -After creating a table you can ingest data from an Avro file into SQream using the following syntax: +* For files hosted on NFS, ensure that the mount is accessible from all servers. -.. code-block:: postgres +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Preparing Your Table +=============== +You can build your table structure on both local and foreign tables: - avro_fdw [OPTIONS(option=value[,...])] +.. contents:: + :local: + :depth: 1 -Example ------------ -The following is an example of creating a table: +Creating a Table +--------------------- +Before loading data, you must build the ``CREATE TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.avro`` table shown below: + +.. csv-table:: nba.avro + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE TABLE`` statement based on the **nba.avro** table: .. code-block:: postgres - CREATE TABLE nba AS - SELECT * FROM ext_nba; + CREATE TABLE ext_nba + ( -The following is an example of loading data from an Avro file into SQream: + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER avro_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.avro' + ); + +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.avro** file is stored on S3 at ``s3://sqream-demo-data/nba.avro``. + +Creating a Foreign Table +--------------------- +Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.avro`` table shown below: + +.. csv-table:: nba.avro + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE FOREIGN TABLE`` statement based on the **nba.avro** table: .. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) WRAPPER avro_fdw OPTIONS ( LOCATION = 's3://sqream-demo-data/nba.avro' ); - -For more examples, see :ref:`additional_examples`. -Avro Data Types -=========== -Avro includes the following data types: +.. tip:: + + An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.avro** file is stored on S3 at ``s3://sqream-demo-data/nba.avro``. + +.. note:: The examples in the sections above are identical except for the syntax used to create the tables. + +Mapping Between SQream and Avro Data Types +================= +Mapping between SQream and Avro data types depends on the Avro data type: .. contents:: :local: @@ -94,23 +159,23 @@ Complex Data Types -------------- The following table shows the supported **Complex** data types: -+------------+---------------------------------------------------+ -| | SQream Type | -| +-----------+---------------+-----------+-----------+ -|Avro Type | Number | Date/Datetime | String | Boolean | -+============+===========+===============+===========+===========+ -| ``record`` | | | | | -+------------+-----------+---------------+-----------+-----------+ -| ``enum`` | | | Supported | | -+------------+-----------+---------------+-----------+-----------+ -| ``array`` | | | | | -+------------+-----------+---------------+-----------+-----------+ -| ``map`` | | | | | -+------------+-----------+---------------+-----------+-----------+ -| ``union`` | Supported | Supported | Supported | Supported | -+------------+-----------+---------------+-----------+-----------+ -| ``fixed`` | | | | | -+------------+-----------+---------------+-----------+-----------+ ++------------+-------------------------------------------------------+ +| | SQream Type | +| +---------------+---------------+-----------+-----------+ +|Avro Type | Number | Date/Datetime | String | Boolean | ++============+============+================+=============+===========+ +| ``record`` | | | | | ++------------+------------+----------------+-------------+-----------+ +| ``enum`` | | | Supported | | ++------------+------------+----------------+-------------+-----------+ +| ``array`` | | | | | ++------------+------------+----------------+-------------+-----------+ +| ``map`` | | | | | ++------------+------------+----------------+-------------+-----------+ +| ``union`` | Supported | Supported | Supported | Supported | ++------------+------------+----------------+-------------+-----------+ +| ``fixed`` | | | | | ++------------+------------+----------------+-------------+-----------+ Logical Data Types -------------- @@ -143,76 +208,77 @@ The following table shows the supported **Logical** data types: +----------------------------+-----------+---------------+-----------+---------+ .. note:: Number types include **tinyint**, **smallint**, **int**, **bigint**, **real** and **float**, and **numeric**. String types include **text**. - + Mapping Objects to Rows =============== When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. -Best Practices -==================== -This section describes the best practices when ingesting Avro files into SQream: +Ingesting Data into SQream +============== +This section includes the following: .. contents:: :local: :depth: 1 -Making Avro Files Accessible to Workers ---------------------- -To give workers access to files every node must have the same view of the storage being used. - -The following apply for Avro files to be accessible to workers: - -* For files hosted on NFS, ensure that the mount is accessible from all servers. - -* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. - -* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. +Syntax +----------- +Before ingesting data into SQream from an Avro file, you must create a table using the following syntax: -For more information about restricted worker access, see :ref:`workload_manager`. +.. code-block:: postgres + + COPY [schema name.]table_name + FROM WRAPPER fdw_name + ; + +After creating a table you can ingest data from an Avro file into SQream using the following syntax: -Basing Your Table Structure on Inserted Tables ---------------------- -Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. +.. code-block:: postgres -The example in this section is based on the source ``nba.avro`` table shown below: + avro_fdw + +Example +----------- +The following is an example of creating a table: -.. csv-table:: nba.avro - :file: nba-t10.csv - :widths: auto - :header-rows: 1 +.. code-block:: postgres + + COPY t + FROM WRAPPER fdw_name + OPTIONS + ( + [ copy_from_option [, ...] ] + ) + ; -The following example shows the correct file structure used to create the ``CREATE FOREIGN TABLE`` statement based on the **nba.avro** table: +The following is an example of loading data from an Avro file into SQream: .. code-block:: postgres - - CREATE FOREIGN TABLE ext_nba - ( - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) WRAPPER avro_fdw OPTIONS ( LOCATION = 's3://sqream-demo-data/nba.avro' ); + +For more examples, see :ref:`additional_examples`. -.. tip:: - - An exact match must exist between the SQream and Avro types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. +Parameters +=================== +The following table shows the Avro parameter: -.. note:: The **nba.avro** file is stored on S3 at ``s3://sqream-demo-data/nba.avro``. +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema name for the table. Defaults to ``public`` if not specified. -Verifying Your Table Output ---------------------- -Because external tables do not automatically verify the file integrity or structure, you must manually verify that the table output is identical to the original inserted table. +Best Practices +============ +Because external tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Avro files into SQream. This lets you determine if your table output is identical to your originally inserted table. The following is an example of the output based on the **nba.avro** table: diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index dc6e7c122..0e5638058 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -13,7 +13,7 @@ Encrypting Data in Transit ---------------- **Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. -For more information, see :ref:`installing_nginx_proxy_over_secure_connection`. +For more information, see `Use TLS/SSL When Possible `_. Encrypting Data at Rest ---------------- diff --git a/feature_guides/flexible_data_clustering.rst b/feature_guides/flexible_data_clustering.rst deleted file mode 100644 index ce0f3d321..000000000 --- a/feature_guides/flexible_data_clustering.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _flexible_data_clustering: - -*********************** -Flexible Data Clustering -*********************** -The **Flexible Data Clustering** section describes the following: - -.. toctree:: - :maxdepth: 4 - :titlesonly: - - flexible_data_clustering_overview - flexible_data_clustering_chunks - flexible_data_clustering_data_clustering_methods - flexible_data_clustering_data_rechunking_data - flexible_data_clustering_data_examples \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_chunks.rst b/feature_guides/flexible_data_clustering_chunks.rst deleted file mode 100644 index b8146d0fc..000000000 --- a/feature_guides/flexible_data_clustering_chunks.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _flexible_data_clustering_chunks: - -*********************** -What are Chunks? -*********************** -Chunks, sometimes referred to as **partitions**, are a contiguous number of rows in a specific column. SQream relies on an advanced partitioning method called **chunking**, which provides all static partitioning capabilities without the known limitations. - -The following figure shows a table rows grouped as chunks: - -.. figure:: /_static/images/chunking2.png - :scale: 75 % - :align: center - -The following figure shows the rows from the table above converted into chunks: - -.. figure:: /_static/images/chunking_metadata2.png - :scale: 75 % - :align: center \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_clustering_methods.rst b/feature_guides/flexible_data_clustering_data_clustering_methods.rst deleted file mode 100644 index 6949547ba..000000000 --- a/feature_guides/flexible_data_clustering_data_clustering_methods.rst +++ /dev/null @@ -1,180 +0,0 @@ -.. _flexible_data_clustering_data_clustering_methods: - -*********************** -Data Clustering Methods -*********************** -The following data clustering methods can be used in tandem or separately to enhance query performance: - -.. contents:: - :local: - :depth: 1 - -Using Time-Based Data Management -============ -Overview -~~~~~~~~~~ -**Time-based data management** refers to sorting table data along naturally occuring dimensions. The most common and naturally occuring sorting mechanism is a **timestamp**, which indicates the point in time at which data was inserted into SQream. Because SQream is a columnar storage system, timestamped metadata facilitates quick and easy query processing. - -The following is the correct syntax for timestamping a chunk: - -.. code-block:: postgres - - SELECT DATEPART(HOUR, timestamp), - MIN(transaction_amount), - MAX(transaction_amount), - avg(transaction_amount) - FROM transactions - WHERE timestamp BETWEEN (CURRENT_TIMESTAMP AND DATEADD(MONTH,-3,CURRENT_TIMESTAMP)) - GROUP BY 1; - -Timestamping data includes the following properties: - -* Data is loaded in a natural order while being inserted. - - :: - -* Updates are infrequent or non-existent. Updates occur by inserting new rows, which have their own timestamps. - - :: - -* Queries on timestamped data is typically on continuous time range. - - :: - -* Inserting and reading data are performed independently, not in the operation or transaction. - - :: - -* Timestamped data has a high data volume and accumulates faster than typical online transactional processing workloads. - -The following are some scenarios ideal for timestamping: - -* Running analytical queries spanning specific date ranges (such as the sum of transactions during August-July 2020 versus August-July 2019). - - :: - -* Deleting data older than a specific number of months old. - - :: - -* Regulations require you to maintain several years of data that you do not need to query on a regular basis. - -Best Practices for Time-Based Management -~~~~~~~~~~ -Data inserted in bulks is automatically timestamped with the insertion date and time. Therefore, inserting data through small and frequent bulks has the effect of naturally ordering data according to timestamp. Frequent bulks generally refers to short time frames, such as at 15-minute, hourly, or daily intervals. As you insert new data, SQream chunks and appends it into your existing tables according to its timestamp. - -The ``DATE`` and ``DATETIME`` types were created to improve performance, minimze storage size, and maintain data integrity. SQream recommends using them instead of ``TEXT``. - -Using Clustering Keys -============ -Overview -~~~~~~~~~~ -While data clustering occurs relatively naturally within a table, certain practices can be used to actively enhance query performance and runtime. Defining **clustering keys** increases performance by explicitly co-locating your data, enabling SQream to avoid processing irrelevant chunks. - -A clustering key is a subset of table columns or expressions and is defined using the ``CLUSTER BY`` statement, as shown below: - -.. code-block:: postgres - - CREATE TABLE users ( - name TEXT(30) NOT NULL, - start_date datetime not null, - country TEXT(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY country; - - - -The ``CLUSTER BY`` statement splits ingested data based on the range of data corresponding to the clustering key. This helps create chunks based on specific or related data, avoiding mixed chunks as much as possible. For example, instead of creating chunks based on a fixed number of rows, the ``CLUSTER_BY`` statement creates them based on common values. This optimizes the ``DELETE`` command as well, which deletes rows based on their location in a table. - -For more information, see the following: - -* `The CLUSTER_BY statement `_ -* `The DELETE statement `_ -* `The Deleting Data Guide `_ - -Inspecting Clustered Table Health -~~~~~~~~~~ -You can use the ``clustering_health`` utility function to check how well a table is clustered, as shown below: - -.. code-block:: postgres - - SELECT CLUSTERING_HEALTH('table_name','clustering_keys'); - -The ``CLUSTERING_HEALTH`` function returns the average clustering depth of your table relative to the clustering keys. A lower value indicates a well-clustered table. - -Clustering keys are useful for restructuring large tables not optimally ordered when inserted or as a result of extensive DML. A table that uses clustering keys is referred to as a **clustered table**. Tables that are not clustered require SQream's query optimizer to scan entire tables while running queries, dramatically increasing runtime. Some queries significantly benefit from clustering, such as filtering or joining extensively on clustered columns. - -SQream partially sorts data that you load into a clustered table. Note that while clustering tables increases query performance, clustering during the insertion stage can decrease performance by 75%. Nevertheless, once a table is clustered subsequent queries run more quickly. - -.. note:: - - To determine whether clustering will enhance performance, SQream recommends end-to-end testing your clustering keys on a small subset of your data before committing them to permanent use. This is relevant for testing insert and query performance. - -For more information, see the following: - -* **Data Manipulation commands (DML)** - see `Data Manipulation Commands (DML) `_. - -* **Creating tables** - see :ref:`create_table`. When you create a table, all new data is clustered upon insert. - -* **Modifying tables** - see :ref:`cluster_by`. - -* **Modifying a table schema** - see :ref:`alter_table`. - -Using Metadata -============ -SQream uses an automated and transparent system for collecting metadata describing each chunk. This metadata enables skipping unnecessary chunks and extents during query runtime. The system collects chunk metadata when data is inserted into SQream. This is done by splitting data into chunks and collecting and storing specific parameters to be used later. - -Because collecting metadata is not process-heavy and does not contribute significantly to query processing, it occurs continuously as a background process. Most metadata collection is typically performed by the GPU. For example, for a 10TB dataset, the metadata storage overhead is approximately 0.5GB. - -When a query includes a filter (such as a ``WHERE`` or ``JOIN`` condition) on a range of values spanning a fraction of the table values, SQream scans only the filtered segment of the table. - -Once collected, several metadata parameters are stored for later use, including: - -* The range of values on each column chunk (minimum, maximum). - - :: - -* The number of values. - - :: - -* Additional information for query optimization. - -Data is collected automatically and transparently on every column type. - -Queries filtering highly granular date and time ranges are the most effective, particularly when data is timestamped, and when tables contain a large amount of historical data. - -Using Chunks and Extents -============ -SQream stores data in logical tables made up of rows spanning one or more columns. Internally, data is stored in vertical partitions by column, and horizontally by chunks. The **Using Chunks and Extents** section describes how to leverge chunking to optimize query performance. - -A **chunk** is a contiguous number of rows in a specific column. Depending on data type, a chunk's uncompressed size typically ranges between 1MB and a few hundred megabytes. This size range is suitable for filtering and deleting data from large tables, which may contain between hundreds, millions, or billions of chunks. - -An **extent** is a specific number of contiguous chunks. Extents optimize disk access patterns, at around 20MB uncompressed, on-disk. Extents typically include between one and 25 chunks based on the compressed size of each chunk. - -.. note:: - - SQream compresses all data. In addition, all tables are automatically and transparently chunked. - -Unlike node-partitioning (or sharding), chunks are: - -* Small enough to be read concurrently by multiple workers. - - :: - -* Optimized for inserting data quickly. - - :: - -* Capable of carrying metadata, which narrows down their contents for the query optimizer. - - :: - -* Ideal for data retension because they can be deleted in bulk. - - :: - -* Optimized for reading into RAM and the GPU. - - :: - -* Compressed individually to improve compression and data locality. \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_examples.rst b/feature_guides/flexible_data_clustering_data_examples.rst deleted file mode 100644 index bf08a111a..000000000 --- a/feature_guides/flexible_data_clustering_data_examples.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _flexible_data_clustering_data_examples: - -*********************** -Examples -*********************** -The **Examples** includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Creating a Clustered Table ------------------------------ -The following is an example of syntax for creating a clustered table on a table naturally ordered by ``start_date``. An alternative cluster key can be defined on such a table to improve performance on queries already ordered by ``country``: - -.. code-block:: postgres - - CREATE TABLE users ( - name text(30) NOT NULL, - start_date datetime not null, - country text(30) DEFAULT 'Unknown' NOT NULL - ) CLUSTER BY country; \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_data_rechunking_data.rst b/feature_guides/flexible_data_clustering_data_rechunking_data.rst deleted file mode 100644 index 30a74bbaa..000000000 --- a/feature_guides/flexible_data_clustering_data_rechunking_data.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _flexible_data_clustering_data_rechunking_data: - -*********************** -Rechunking Data -*********************** -SQream performs background storage reorganization operations to optimize I/O and read patterns. - -For example, when small batches of data are inserted, SQream runs two background processes called **rechunk** and **reextent** to reorganize the data into larger contiguous chunks and extents. This is also what happens when data is deleted. - - -Instead of overwriting data, SQream writes new optimized chunks and extents to replace old ones. After rewriting all old data, SQream switches to the new optimized chunks and extents and deletes the old data. \ No newline at end of file diff --git a/feature_guides/flexible_data_clustering_overview.rst b/feature_guides/flexible_data_clustering_overview.rst deleted file mode 100644 index 3ba59a603..000000000 --- a/feature_guides/flexible_data_clustering_overview.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _flexible_data_clustering_overview: - -*********************** -Overeview -*********************** -**Flexible data clustering** refers to sorting table data along naturally occuring dimensions, such as name, date, or location. Data clustering optimizes table structure to significantly improve query performance, especially on very large tables. A well-clustered table increases the effectivity of the metadata collected by focusing on a specific and limited range of rows, called **chunks**. - -The following are some scenarios ideal for data clustering: - -* Queries containg a ``WHERE`` predicate written as ``column COMPARISON value``, such as ``date_column > '2019-01-01'`` or ``id = 107`` when the columns referenced are clustering keys. - - In such a case SQream reads the portion of data that contain values matching these predicates only. - -* Two clustered tables joined by their respective clustering keys. - - In such a case SQream uses metadata to more easily identify matching chunks. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 2ba36198d..fb663a336 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -15,7 +15,6 @@ This section describes the following features: key_evaluation data_encryption compression - flexible_data_clustering python_functions workload_manager transactions diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 19881d62c..f16d90337 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -31,7 +31,7 @@ The following is the correct syntax for the ``UPDATE`` command: UPDATE target_table_name [[AS] alias1] SET column_name = expression [,...] - [WHERE condition] + [WHERE condition] The following is the correct syntax for triggering a clean-up: @@ -39,9 +39,8 @@ The following is the correct syntax for triggering a clean-up: SELECT cleanup_chunks('schema_name','table_name'); SELECT cleanup_extents('schema_name','table_name'); + SELECT cleanup_discarded_chunks(‘public’,’t’); -**Comment** - *The cleanup example above is different than the one used on the DELETED page. Is this correct?* - Parameters ============ The following table describes the ``UPDATE`` parameters: @@ -79,71 +78,21 @@ The following is an example of performing a simple update: UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; -Identifying and Cleaning Up Tables +Triggering a Clean-Up --------------------------------------- -**Comment** - *I copied and pasted this entire section from "DELETE". Does anything have to adjusted here for "UPDATE"?* - -The following section shows examples of each phase required for cleaning up tables: - -* :ref:`Listing tables that require clean-up` -* :ref:`Identifying clean-up predicates` -* :ref:`Triggering a clean-up` - -.. _listing_tables_that_require_cleanup: - -Listing Tables that Require Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing tables that require clean-up: +The following section shows an example of triggering a clean-up: .. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row -.. _identifying_cleanup_predicates: + SELECT * FROM sqream_catalog.discarded_chunks; + SELECT cleanup_discarded_chunks('public','t'); -Identifying Clean-Up Predicates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing the clean-up predicates: +The following is an output example: -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -.. _triggering_a_cleanup: - -Triggering a Clean-Up -^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of triggering a clean-up: - -.. code-block:: psql - - -- Chunk reorganization (SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows +* **database_name** - _discarded_master +* **table_id** - 24 +* **column_id** - 1 +* **extent_ID** - 0 Permissions ============= diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 9a2de884e..7b2d9d4dd 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -29,9 +29,9 @@ Data Encryption ************ SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. -For more information, see `Data Encryption `_. +Using the data encryption feature may lead to a maximum of a 40% increase in performance degradation. -**Comment** - *Information regarding performance degradation, pending.* +For more information, see `Data Encryption `_. Update Feature ************ @@ -91,4 +91,36 @@ This section is not relevant to the 2022.1 release notes. Upgrading to v2022.1 ------- -**Comment** - *TBD* \ No newline at end of file +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. \ No newline at end of file From 5c07b951cb154b32c279d12c2342f6b7dfebae6c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 24 May 2022 19:15:54 +0300 Subject: [PATCH 0073/1892] Update new_2022.1.png --- _static/images/new_2022.1.png | Bin 2056 -> 882 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/_static/images/new_2022.1.png b/_static/images/new_2022.1.png index fc043757cd3728088194fbb6951830f5bf7fcc0c..4861ba76a5b6c7d35703267596db1f4c0a8c9fb5 100644 GIT binary patch delta 845 zcmV-T1G4;x5b_2giBL{Q4GJ0x0000DNk~Le0001S0000E2m$~A0GDWFlaV1be**_e zL_t(oN9~tAa_TS;$N%^&K*4YVa{@?1mG*U_Oqz5l)1@&bK0+#**e8fjz))b{#cx+y z%aXA2!6TV@Gx?1QX|>4O)vi{cB?{H18FzjXg%;G(widyENZqDrRiXO@o1?qrQ$1ni zgfTU93?+&D?0VGMzj~8bFsBl1e@~kuQ%Yn+Oh3BL8SEKnLB{oI+h(chCum+#DJ3tW~MlW#m*acZ#|Lt z&oK`(rDT>0Zc3Hie|h!>cy(WwOS`NovP}Pq9)Q%sDopr0bZr^de|MeWWfH6Vy+dR; z_?B|)Fi+y(XC#s4e1q2MU0~FPY%qjxDeXSf0$)3O>2V+G((IdQXsMWfbRFNP?DumW zBJinfctq>!cklb9;FnK8F9+?(L|1L6&i-;SUHuqQ$nwklBWZTwCH;#)|4>$->|f$9 XQ>c)1B;vX600000NkvXXu0mjf(aoL- delta 2028 zcmVPUA2Xb_z!U38c9|795~RWyb+nWWk07vzr6VjxN}A!D0@;j!5(XUGxGY zQHdS}l6lX5&w2TA;?(KDF!>~_Y1$V*+wb3Qqqn!WTuI!YsmaTw$`&_tW5kFN23w`B zuhc~S0R5QKJ*6s2v{aMBnTk}bf3nR=fr32Zg^mO4;=!{;hBm+f&XbNVJv4f2cLCJTeOl8MOYr80nd}`r8c0Q*e+GnM8EVL zXmJ05^ge*+n`d9sjTSV@{8VN07+%+EawYDgCo(O~Go|ue#rgY&?@^n_e{df^Q+YPu zls|K|&D{OGf2pO39edF}*_ePwGuN)x!EYCRoWOcE&~e*$|H1RU$=_r7JQz>o_e5iv zkLQ)o>UvUmqUDqELh)s57#H21fOVobUmoDTXAkBwo-3F%_5OzK6NS3y@qtIPc9KVE z>0E&z0KjsdIIQpTS{*p)e-lH$eozN4`q2JE={o^ycm^`NrnkWm-sp}L!Dv^Zsg0gS zcp}q0H2EudqE9~tVPR_)lbRhv)7r9C-IYGH|4{mlCTMXDvxMb1#1lcY&o$2>PxPuH zt*J1g^A;1E%vFX;sK7Gy$&W_t2is@6ZrLwKHTCF5Wr?|rUS7=we}kisE_!WwF$%fU zuNI;GhtjtJJnZD;mONYn9&V+wQ~gOej?Pt1dVo=xQ6kS!PW=Y;`$aBxeX9;I=?g_I zX+MPb;JT~HB!(SbNuf^xdat=XR(S#; zSG5r2!taU@K5?kpf3fc8@VUM)LQ^2H|6uxd*bs5G0KwO{2EvibztQFEmXzofv;*<& z*u1s@Ed#{L8V|F8{K!;e4rU;z>vF&v=@=Z8>0Sun^un=_jID|u={f61NA(N@mEa!M8f0Zv5r9F!}U|wi>%j+xV z;_}>FxL_?Wtj&{{{Gk2;q4aH-E=*pv+S7jLDS2n`jz)=I%;I@190D0+7eCvv+!osZQZ6|D3F&8C$_jR!2DqY z%f_(dfcZ;OfAJk?GBI!Qj?onu5*>0BwAsx-rc=y|({LPj^(8ECU-Gy?WidNPys6@hD_5uj?DzyUAD?cKEuWjl|aQFsHTG-eeLm+)Y z;7|^{+ILcrT1e*`%Jl$`0~grkIb>qoq}YIb{++G{2Ih!7=2UpkzlG5LKbn7pM+jN= zM7=RBf9FSymbMBOcmU9p67f>Q;}r;@Fg7-?glp{bb%G2$X_l(rVGBBxMHA!b@@y18 zmkfeLp9sJgD1f(yKkX&|wiOTU|D*ZmaLogON(7Mk(e2f4`H?q@kgjCaIh5lB`GP`0 zSrWD0Z=g`F5A1?eJ?NfL6~LkLD}+ySAKL#ufBD}7K#2m9M#jxby_5Ctv$Kp7R7%7f zTjg{Bhjcbv6QLaMad9YUbEm>-R*V{SQgsw7w-H+R|#Y;&eN-+WJ_z zDxKm6a1POxWO@Pe1wN?ShQ&&~e{WKi$CO(z;C(*FBQ(|13<4a_H-&Nx8?L~J_Z3RP zSX;+|N1E_7!al&cmd4s0K6gQ%tVmUs0KargL-OA=#i9L&(qlNSryTekbbYbtLTee% z>vOVvej~wN;e3LHoEUV9%?KLKrckgoghi zas1oQ=#55boezEA Date: Sun, 29 May 2022 11:01:15 +0300 Subject: [PATCH 0074/1892] Update copy_to.rst Added Avro to COPY TO page. --- reference/sql/sql_statements/dml_commands/copy_to.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 61e6b35b2..85632904f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -29,7 +29,7 @@ Syntax ) ; - fdw_name ::= csw_fdw | parquet_fdw | orc_fdw + fdw_name ::= csw_fdw | parquet_fdw | orc_fdw | avro_fdw schema_name ::= identifer From 1cbd8ce0cb4973a7809f40137dbc1c358eb19dab Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 11:23:56 +0300 Subject: [PATCH 0075/1892] Updated Delete Guide Moved delete_guide from Feature Guides to Operational guides. Delete delete page and replaced with delete_guide. --- operational_guides/delete.rst | 214 ------------------ .../delete_guide.rst | 0 operational_guides/index.rst | 1 + 3 files changed, 1 insertion(+), 214 deletions(-) delete mode 100644 operational_guides/delete.rst rename {feature_guides => operational_guides}/delete_guide.rst (100%) diff --git a/operational_guides/delete.rst b/operational_guides/delete.rst deleted file mode 100644 index 24ab5a218..000000000 --- a/operational_guides/delete.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. _delete_guide: - -*********************** -Deleting Data -*********************** - -SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. - -How does deleting in SQream DB work? -======================================== - -In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. -Deleted rows are tracked in a separate location, in *delete predicates*. - -After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. - -Some benefits to this design are: - -#. Delete transactions complete quickly - -#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). - - -Phase 1: Delete ---------------------------- - -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? - -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them - -When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. - -This filtering process takes full advantage of SQream's zone map feature. - -Phase 2: Clean-up --------------------- - -The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. - -Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. - -.. note:: - * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. - * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. - -Notes on data deletion -========================================= - -.. note:: - * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. - * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. - * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: - -.. code-block:: postgres - - set mixedColumnChunksThreshold=XXX; - - -Deleting data does not free up space ------------------------------------------ - -With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. - -``SELECT`` performance on deleted rows ----------------------------------------- - -Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. -In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. - -Use ``TRUNCATE`` instead of ``DELETE`` ---------------------------------------- -For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. - -Cleanup is I/O intensive -------------------------------- - -The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. - -Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. - -If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. - - -Example -============= - -Deleting values from a table ------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Deleting values based on more complex predicates ---------------------------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Identifying and cleaning up tables ---------------------------------------- - -List tables that haven't been cleaned up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -Identify predicates for clean-up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -Triggering a cleanup -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - -- Chunk reorganization (aka SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (aka VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows - - - -Best practices for data deletion -===================================== - -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. - -* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. - -* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. - -* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. - - - -.. soft update concept - -.. delete cleanup and it's properties. automatic/manual, in transaction or background - -.. automatic background gives fast delete, minimal transaction overhead, -.. small cost to queries until background reorganised - -.. when does delete use the metadata effectively - -.. more examples - diff --git a/feature_guides/delete_guide.rst b/operational_guides/delete_guide.rst similarity index 100% rename from feature_guides/delete_guide.rst rename to operational_guides/delete_guide.rst diff --git a/operational_guides/index.rst b/operational_guides/index.rst index dcad76172..b6d3e50f4 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -16,6 +16,7 @@ This section summarizes the following operational guides: creating_or_cloning_a_storage_cluster external_data external_tables + delete_guide exporting_data logging monitoring_query_performance From 5ac738294af255e8afaf3185bc8582ff09335cc8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 11:38:02 +0300 Subject: [PATCH 0076/1892] Updated External Tables Page Replaced External Tables with Foreign Tables. Modified content on Foreign Tables page (replaced external tables with foreign tables). In Index, replaced external_tables with foreign_tables. Copied nba-t10.csv file into operational_guides folder (table was missing and therefore causing syntax error). --- ...external_tables.rst => foreign_tables.rst} | 33 ++++++++++--------- operational_guides/index.rst | 2 +- operational_guides/nba-t10.csv | 10 ++++++ 3 files changed, 29 insertions(+), 16 deletions(-) rename operational_guides/{external_tables.rst => foreign_tables.rst} (94%) create mode 100644 operational_guides/nba-t10.csv diff --git a/operational_guides/external_tables.rst b/operational_guides/foreign_tables.rst similarity index 94% rename from operational_guides/external_tables.rst rename to operational_guides/foreign_tables.rst index 6ee2f67a0..b914d7b3c 100644 --- a/operational_guides/external_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -1,37 +1,39 @@ -.. _external_tables: +.. _foreign_tables: *********************** -External Tables +Foreign Tables *********************** -External tables can be used to run queries directly on data without inserting it into SQream DB first. +Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. + Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. + Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. .. contents:: In this topic: :local: -What kind of data is supported? +Supported Data Formats ===================================== SQream DB supports external tables over: -* text files (e.g. CSV, PSV, TSV) +* Text files (e.g. CSV, PSV, TSV) * ORC * Parquet -What kind of data staging is supported? +Supported Data Staging ============================================ -SQream DB can stage data from: +SQream can stage data from: * a local filesystem (e.g. ``/mnt/storage/....``) * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) -Using external tables - a practical example +Using External Tables ============================================== Use an external table to stage data before loading from CSV, Parquet or ORC files. -Planning for data staging +Planning for Data Staging -------------------------------- For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: @@ -44,7 +46,7 @@ For the following examples, we will want to interact with a CSV file. Here's a p The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. -Creating the external table +Creating an External Table ----------------------------- Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. @@ -68,7 +70,8 @@ Based on the source file structure, we we :ref:`create an external table SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. +* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index b6d3e50f4..aca578e8b 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -15,7 +15,7 @@ This section summarizes the following operational guides: access_control creating_or_cloning_a_storage_cluster external_data - external_tables + foreign_tables delete_guide exporting_data logging diff --git a/operational_guides/nba-t10.csv b/operational_guides/nba-t10.csv new file mode 100644 index 000000000..024530355 --- /dev/null +++ b/operational_guides/nba-t10.csv @@ -0,0 +1,10 @@ +Name,Team,Number,Position,Age,Height,Weight,College,Salary +Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 +Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 +John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, +R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 +Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 +Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 +Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 +Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 +Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 From 732df57cd53c332b0de03641102ca92382fc5ac5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 12:21:57 +0300 Subject: [PATCH 0077/1892] Modified nba-t10.csv syntax. Tried to get nba-t10.csv file to display properly. --- operational_guides/foreign_tables.rst | 5 +- .../ddl_commands/create_external_table.rst | 156 ------------------ 2 files changed, 2 insertions(+), 159 deletions(-) delete mode 100644 reference/sql/sql_statements/ddl_commands/create_external_table.rst diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index b914d7b3c..739652bfa 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -36,12 +36,11 @@ Use an external table to stage data before loading from CSV, Parquet or ORC file Planning for Data Staging -------------------------------- For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: - + .. csv-table:: nba.csv - :file: nba-t10.csv :widths: auto - :header-rows: 1 + :header-rows: 1 The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. diff --git a/reference/sql/sql_statements/ddl_commands/create_external_table.rst b/reference/sql/sql_statements/ddl_commands/create_external_table.rst deleted file mode 100644 index e877a3983..000000000 --- a/reference/sql/sql_statements/ddl_commands/create_external_table.rst +++ /dev/null @@ -1,156 +0,0 @@ -.. _create_external_table: - -*********************** -CREATE EXTERNAL TABLE -*********************** - -.. warning:: - - The ``CREATE EXTERNAL TABLE`` syntax is deprecated, and will be removed in future versions. - - Starting with SQream DB v2020.2, external tables have been renamed to :ref:`foreign tables`, and use a more flexible foreign data wrapper concept. See :ref:`create_foreign_table` instead. - - Upgrading to a new version of SQream DB converts existing tables automatically. When creating a new external tables, use the new foreign table syntax. - - -``CREATE TABLE`` creates a new external table in an existing database. - -See more in the :ref:`External tables guide`. - -.. tip:: - - * Data in an external table can change if the sources change, and frequent access to remote files may harm performance. - - * To create a regular table, see :ref:`CREATE TABLE ` - -Permissions -============= - -The role must have the ``CREATE`` permission at the database level. - -Syntax -========== - -.. code-block:: postgres - - create_table_statement ::= - CREATE [ OR REPLACE ] EXTERNAL TABLE [schema_name].table_name ( - { column_def [, ...] } - ) - USING FORMAT format_def - WITH { external_table_option [ ...] } - ; - - schema_name ::= identifier - - table_name ::= identifier - - format_def ::= { PARQUET | ORC | CSV } - - external_table_option ::= { - PATH '{ path_spec }' - | FIELD DELIMITER '{ field_delimiter }' - | RECORD DELIMITER '{ record_delimiter }' - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS SECRET }' - } - - path_spec ::= { local filepath | S3 URI | HDFS URI } - - field_delimiter ::= delimiter_character - - record_delimiter ::= delimiter_character - - column_def ::= { column_name type_name [ default ] [ column_constraint ] } - - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] - -.. _cet_parameters: - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. - * - ``schema_name`` - - The name of the schema in which to create the table. - * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. - * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. - * - ``USING FORMAT ...`` - - Specifies the format of the source files, such as ``PARQUET``, ``ORC``, or ``CSV``. - * - ``WITH PATH ...`` - - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. - * - ``FIELD DELIMITER`` - - Specifies the field delimiter for CSV files. Defaults to ``,``. - * - ``RECORD DELIMITER`` - - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` - * - ``AWS_ID``, ``AWS_SECRET`` - - Credentials for authenticated S3 access - - -Examples -=========== - -A simple table from Tab-delimited file (TSV) ----------------------------------------------- - -.. code-block:: postgres - - CREATE OR REPLACE EXTERNAL TABLE cool_animals - (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) - USING FORMAT csv - WITH PATH '/home/rhendricks/cool_animals.csv' - FIELD DELIMITER '\t'; - - -A table from a directory of Parquet files on HDFS ------------------------------------------------------ - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet'; - -A table from a bucket of files on S3 --------------------------------------- - -.. code-block:: postgres - - CREATE EXTERNAL TABLE users - (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) - USING FORMAT Parquet - WITH PATH 's3://pp-secret-bucket/users/*.parquet' - AWS_ID 'our_aws_id' - AWS_SECRET 'our_aws_secret'; - - -Changing an external table to a regular table ------------------------------------------------- - -Materializes an external table into a regular table. - -.. tip: Using an external table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files - -.. code-block:: postgres - - CREATE TABLE real_table - AS SELECT * FROM external_table; - From fd1e61a64a2dca4ebf60e00d4e5921c457dbc674 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 13:12:36 +0300 Subject: [PATCH 0078/1892] Update update.rst TPD-171: Update - Support Clustering Key --- .../sql/sql_statements/dml_commands/update.rst | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index f16d90337..d0f545017 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -19,10 +19,14 @@ The ``UPDATE`` command is used to modify the value of certain columns in existin It can be used to do the following: -* Perform localized changes in existing data, such as correcting mistakes discovered after ingesting data. +* Performing localized changes in existing data, such as correcting mistakes discovered after ingesting data. + + :: * Setting columns based on the values of others. +.. warning:: Using the ``UPDATE`` command on column clustered using a cluster key can undo your clustering. + Syntax ========== The following is the correct syntax for the ``UPDATE`` command: @@ -60,7 +64,7 @@ The following table describes the ``UPDATE`` parameters: * - ``condition`` - Specifies the condition for updating the data. -.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. +.. note:: Similar to a ``DELETE`` statement, an ``UPDATE`` statement may leave some uncleaned data behind, which requires a clean-up operation. Examples =========== @@ -87,17 +91,17 @@ The following section shows an example of triggering a clean-up: SELECT * FROM sqream_catalog.discarded_chunks; SELECT cleanup_discarded_chunks('public','t'); -The following is an output example: +The following is an example of the output generated from the above: * **database_name** - _discarded_master * **table_id** - 24 * **column_id** - 1 * **extent_ID** - 0 -Permissions +Locking and Concurrency ============= -Executing an ``UPDATE`` statement requires both ``UPDATE`` and ``SELECT`` permissions on the target table. +Executing the ``UPDATE`` statement obtains an exclusive ``UPDATE`` lock on the target table. -Locking and Concurrency +Permissions ============= -Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table. \ No newline at end of file +Executing an ``UPDATE`` statement requires both ``UPDATE`` and ``SELECT`` permissions on the target table. \ No newline at end of file From 138e683d0caea04d0534de8e86be73ea539b6fe5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 29 May 2022 13:33:33 +0300 Subject: [PATCH 0079/1892] Modified Delete Guide Moved delete_guide from feature_guides to operational_guides --- feature_guides/delete.rst | 214 -------------------------------------- feature_guides/index.rst | 1 - 2 files changed, 215 deletions(-) delete mode 100644 feature_guides/delete.rst diff --git a/feature_guides/delete.rst b/feature_guides/delete.rst deleted file mode 100644 index 24ab5a218..000000000 --- a/feature_guides/delete.rst +++ /dev/null @@ -1,214 +0,0 @@ -.. _delete_guide: - -*********************** -Deleting Data -*********************** - -SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. - -How does deleting in SQream DB work? -======================================== - -In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. -Deleted rows are tracked in a separate location, in *delete predicates*. - -After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. - -Some benefits to this design are: - -#. Delete transactions complete quickly - -#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). - - -Phase 1: Delete ---------------------------- - -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? - -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them - -When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. - -This filtering process takes full advantage of SQream's zone map feature. - -Phase 2: Clean-up --------------------- - -The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. - -Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. - -.. note:: - * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. - * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. - -Notes on data deletion -========================================= - -.. note:: - * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. - * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. - * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: - -.. code-block:: postgres - - set mixedColumnChunksThreshold=XXX; - - -Deleting data does not free up space ------------------------------------------ - -With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. - -``SELECT`` performance on deleted rows ----------------------------------------- - -Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. -In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. - -Use ``TRUNCATE`` instead of ``DELETE`` ---------------------------------------- -For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. - -Cleanup is I/O intensive -------------------------------- - -The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. - -Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. - -If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. - - -Example -============= - -Deleting values from a table ------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Deleting values based on more complex predicates ---------------------------------------------------- - -.. code-block:: psql - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N - - 6 rows - - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed - - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N - - 4 rows - -Identifying and cleaning up tables ---------------------------------------- - -List tables that haven't been cleaned up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -Identify predicates for clean-up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -Triggering a cleanup -^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - -- Chunk reorganization (aka SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed - - -- Delete leftover files (aka VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed - - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - - 0 rows - - - -Best practices for data deletion -===================================== - -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. - -* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. - -* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. - -* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. - - - -.. soft update concept - -.. delete cleanup and it's properties. automatic/manual, in transaction or background - -.. automatic background gives fast delete, minimal transaction overhead, -.. small cost to queries until background reorganised - -.. when does delete use the metadata effectively - -.. more examples - diff --git a/feature_guides/index.rst b/feature_guides/index.rst index fb663a336..2ca100a0f 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -11,7 +11,6 @@ This section describes the following features: :maxdepth: 1 :titlesonly: - delete_guide key_evaluation data_encryption compression From e2be508ed8dec82a2fa18a5dc91c318a2804d074 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 30 May 2022 12:06:21 +0300 Subject: [PATCH 0080/1892] Update data_encryption_overview.rst Integrated Raz Tamir's comments on this page. --- feature_guides/data_encryption_overview.rst | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 58bb7ea40..a37325e52 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -11,11 +11,7 @@ The demand for confidentiality has steadily increased to protect the growing vol Encryption can be used for the following: -* Deleting encrypted columns. - - :: - -* Creating tables with one or more encrypted columns. +* Creating tables up to three encrypted columns. :: @@ -23,10 +19,6 @@ Encryption can be used for the following: :: -* Encrypting existing data. - - :: - * Selecting data from an encrypted column. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. From ce49d1129f120de98bb8308fa40df062d2243f31 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 30 May 2022 12:08:48 +0300 Subject: [PATCH 0081/1892] Updated for 2022.1 --- index.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/index.rst b/index.rst index cb7d685b2..29ea038b0 100644 --- a/index.rst +++ b/index.rst @@ -4,7 +4,7 @@ SQream DB Documentation ************************* -The **2022.3 Preview** branch is a private branch designed for internal use only. +The **v2022.1** branch is a private branch designed for internal use only until the release date. .. only:: html @@ -57,7 +57,9 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` + :ref:`2022.1<2022.1>` + + :ref:`2021.2<2021.2>` :ref:`2021.1<2021.1>` @@ -87,7 +89,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? -This version of the documentation is for SQream DB Version 2021.2. +This version of the documentation is for SQream DB Version 2022.1. If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . From c675e002792e47bc2c5e9c392c7ca47e13f56095 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 30 May 2022 13:18:40 +0300 Subject: [PATCH 0082/1892] Changed 40% to 30% Degradation Raz Tamar email. --- releases/2022.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 7b2d9d4dd..53c314faf 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -29,7 +29,7 @@ Data Encryption ************ SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. -Using the data encryption feature may lead to a maximum of a 40% increase in performance degradation. +Using the data encryption feature may lead to a maximum of a 30% increase in performance degradation. For more information, see `Data Encryption `_. From fa271aa442ddc9638db3f6950676a19bc93d4d09 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 30 May 2022 15:01:47 +0300 Subject: [PATCH 0083/1892] Update cluster_by.rst --- reference/sql/sql_statements/ddl_commands/cluster_by.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index e4cf42ad4..7dcedaaf1 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -7,10 +7,6 @@ The ``CLUSTER BY`` command is used for changing clustering keys in a table. For more information, see the following: -* :ref:`flexible_data_clustering` - - :: - * :ref:`drop_clustering_key` :: From 49bb8df32937b571e8af6e37d3f2669e6b20873c Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 7 Jun 2022 14:37:41 +0300 Subject: [PATCH 0084/1892] Update show_server_status.rst TPD-128 --- .../utility_commands/show_server_status.rst | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst index f59f79ccc..73902a046 100644 --- a/reference/sql/sql_statements/utility_commands/show_server_status.rst +++ b/reference/sql/sql_statements/utility_commands/show_server_status.rst @@ -3,18 +3,13 @@ ******************** SHOW_SERVER_STATUS ******************** - ``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. To list active statements on the current worker only, see :ref:`show_connections`. -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - Syntax ========== +The following is the correct syntax when showing your server status: .. code-block:: postgres @@ -24,85 +19,90 @@ Syntax Parameters ============ - -None +The Parameters section is not relevant for the ``SHOW_SERVER_STATUS`` statement. Returns ========= +The ``SHOW_SERVER_STATUS`` function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. -This function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. +The following table shows the ``SHOW_SERVER_STATUS`` result columns; -.. list-table:: Result columns +.. list-table:: Result Columns :widths: auto :header-rows: 1 - * - ``service`` - - The service name for the statement + * - service + - Statement Service Name * - ``instance`` - - The worker ID + - Shows the worker ID. * - ``connection_id`` - - Connection ID + - Shows the connection ID. * - ``serverip`` - - Worker end-point IP + - Shows the worker end-point IP. * - ``serverport`` - - Worker end-point port + - Shows the worker end-point port. * - ``database_name`` - - Database name for the statement + - Shows the statement's database name. * - ``user_name`` - - Username running the statement + - Shows the username running the statement. * - ``clientip`` - - Client IP + - Shows the client IP. * - ``statementid`` - - Statement ID + - Shows the statement ID. * - ``statement`` - - Statement text + - Shows the statement text. * - ``statementstarttime`` - - Statement start timestamp + - Shows the statement start timestamp. * - ``statementstatus`` - - Statement status (see table below) + - Shows the statement status (see table below). * - ``statementstatusstart`` - - Last updated timestamp + - Shows the most recently updated timestamp. .. include from here: 66 +The following table shows the statement status values: -.. list-table:: Statement status values +.. list-table:: Statement Status Values :widths: auto :header-rows: 1 * - Status - Description * - ``Preparing`` - - Statement is being prepared + - The statement is being prepared. * - ``In queue`` - - Statement is waiting for execution + - The statement is waiting for execution. * - ``Initializing`` - - Statement has entered execution checks + - The statement has entered execution checks. * - ``Executing`` - - Statement is executing + - The statement is executing. * - ``Stopping`` - - Statement is in the process of stopping - + - The statement is in the process of stopping. .. include until here 86 Notes =========== +This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. -* This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. - -Examples +Example =========== -Using ``SHOW_SERVER_STATUS`` to get statement IDs +Using SHOW_SERVER_STATUS to Get Statement IDs ---------------------------------------------------- - +The following example shows how to use the ``SHOW_SERVER_STATUS`` statement to get statement IDs: .. code-block:: psql t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+--------------+------------+---------------+------------+-------------+-------------+-----------------------------+---------------------+-----------------+--------------------- - sqream | | 102 | 192.168.1.91 | 5000 | t | rhendricks | 192.168.0.1 | 128 | SELECT SHOW_SERVER_STATUS() | 24-12-2019 00:14:53 | Executing | 24-12-2019 00:14:53 + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 17-01-2022 16:19:31 | Executing | 17-01-2022 16:19:32 + sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 17-01-2022 16:19:39 | Executing | 17-01-2022 16:19:39 + sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 17-01-2022 15:55:01 | In Queue | 17-01-2022 15:55:02 The statement ID is ``128``, running on worker ``192.168.1.91``. + +Permissions +============= +The role must have the ``SUPERUSER`` permissions. From 1025d496f917f67922b863891adbb1a8949f85da Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Sun, 12 Jun 2022 10:44:51 +0300 Subject: [PATCH 0085/1892] TPD-67 --- .../client_drivers/jdbc/index.rst | 127 ++++++++++-------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/third_party_tools/client_drivers/jdbc/index.rst b/third_party_tools/client_drivers/jdbc/index.rst index 42a04548f..4c35c3eff 100644 --- a/third_party_tools/client_drivers/jdbc/index.rst +++ b/third_party_tools/client_drivers/jdbc/index.rst @@ -3,160 +3,169 @@ ************************* JDBC ************************* +The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. -The SQream DB JDBC driver allows many Java applications and tools connect to SQream DB. -This tutorial shows how to write a Java application using the JDBC interface. +The JDBC page includes the following sections: -The JDBC driver requires Java 1.8 or newer. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 -Installing the JDBC driver +Installing the JDBC Driver ================================== +The **Installing the JDBC Driver** section describes the following: + +.. contents:: + :local: + :depth: 1 Prerequisites ---------------- +The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: -The SQream DB JDBC driver requires Java 1.8 or newer. We recommend either Oracle Java or OpenJDK. - -**Oracle Java** - -Download and install Java 8 from Oracle for your platform +* **Oracle Java** - Download and install `Java 8 `_ from Oracle for your platform. -https://www.java.com/en/download/manual.jsp - -**OpenJDK** - -For Linux and BSD, see https://openjdk.java.net/install/ - -For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk + :: + +* **OpenJDK** - Install `OpenJDK `_ -.. _get_jdbc_jar: + :: + +* **Windows** - SQream recommends installing `Zulu 8 `_ Getting the JAR file --------------------- +SQream provides the JDBC driver as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can be integrated into your Java-based applications or projects. -The JDBC driver is provided as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can integrate into your Java-based applications or projects. - - -Extract the zip archive +Extracting the ZIP Archive ------------------------- - -Extract the JAR file from the zip archive +Run the following command to extract the JAR file from the ZIP archive: .. code-block:: console $ unzip sqream-jdbc-4.3.0.zip -Setting up the Class Path +Setting Up the Class Path ---------------------------- +To use the driver, you must include the JAR named ``sqream-jdbc-.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -To use the driver, the JAR named ``sqream-jdbc-.jar`` (for example, ``sqream-jdbc-4.3.0.jar``) needs to be included in the class path, either by putting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. - -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the application should be run as follows: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: .. code-block:: console $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH $ java my_java_app -An alternative method is to pass ``-classpath`` to the Java executable: +Alternatively, you can pass ``-classpath`` to the Java executable file: .. code-block:: console $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app - -Connect to SQream DB with a JDBC application +Connecting to SQream Using a JDBC Application ============================================== +You can connect to SQream using one of the following JDBC applications: -Driver class +.. contents:: + :local: + :depth: 1 + +Driver Class -------------- - Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. - -.. _connection_string: - -Connection string +Connection String -------------------- +JDBC drivers rely on a connection string. -JDBC drivers rely on a connection string. Use the following syntax for SQream DB +The following is the syntax for SQream: .. code-block:: text jdbc:Sqream:///;user=;password=sqream;[; ...] -Connection parameters +Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the connection string parameters: .. list-table:: :widths: auto :header-rows: 1 * - Item - - Optional + - State - Default - Description * - ```` - - ✗ + - Mandatory - None - Hostname and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` * - ```` - - ✗ + - Mandatory - None - Database name to connect to. For example, ``master`` * - ``username=`` - - ✗ + - Mandatory - None - Username of a role to use for connection. For example, ``username=rhendricks`` * - ``password=`` - - ✗ + - Mandatory - None - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` * - ``service=`` - - ✓ + - Optional - ``sqream`` - Specifices service queue to use. For example, ``service=etl`` * - ```` - - ✓ + - Optional - ``false`` - Specifies SSL for this connection. For example, ``ssl=true`` * - ```` - - ✓ + - Optional - ``true`` - Connect via load balancer (use only if exists, and check port). + * - ```` + - Optional + - ``true`` + - Enables on-demand loading, and defines double buffer size for result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the fetchSize is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. + * - ```` + - Optional + - ``true`` + - Defines the bytes size for inserting a buffer before flushing data to the server. Clients running a parameterized insert (network insert) can define the amount of data to collect before flushing the buffer. + * - ```` + - Optional + - ``true`` + - Defines the logger level as either ``debug`` or ``trace``. + * - ```` + - Optional + - ``true`` + - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. -Connection string examples +Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -For a SQream DB cluster with load balancer and no service queues, with SSL +The following is an example of a SQream cluster with load balancer and no service queues (with SSL): .. code-block:: text jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true -Minimal example for a local, standalone SQream DB +The following is a minimal example for a local standalone SQream database: .. code-block:: text jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 -For a SQream DB cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` +The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` .. code-block:: text jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl - -Sample Java program +Sample Java Program -------------------- - -Download this file by right clicking and saving to your computer :download:`sample.java `. +You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. .. literalinclude:: sample.java :language: java - :caption: JDBC application sample + :caption: JDBC Application Sample :linenos: - From 3abe6527279c7dfd15a3ce07cdcebc5e2b4bf194 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 11:08:59 +0300 Subject: [PATCH 0086/1892] Added missing table --- .../ddl_commands/create_table.rst | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 788c71b31..51f46582b 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -3,7 +3,7 @@ ***************** CREATE TABLE ***************** - + The ``CREATE TABLE`` statement is used to create a new table in an existing database. .. tip:: @@ -62,7 +62,7 @@ The following parameters can be used when creating a table: - A commma separated list of clustering column keys. - See :ref:`data_clustering` for more information. + See :ref:`flexible_data_clustering` for more information. * - ``LIKE`` - Duplicates the column structure of an existing table. @@ -141,7 +141,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name text(30) NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -155,7 +155,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name text(30) NOT NULL, + name varchar(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -171,8 +171,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name TEXT(30) NOT NULL, - country TEXT(30) DEFAULT 'Unknown' NOT NULL + name VARCHAR(30) NOT NULL, + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -203,9 +203,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name TEXT(30) NOT NULL, + name VARCHAR(30) NOT NULL, start_date datetime not null, - country TEXT(30) DEFAULT 'Unknown' NOT NULL + country VARCHAR(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. @@ -261,9 +261,9 @@ Either of the following examples can be used to create a second table based on t The generated output of both of the statements above is identical. -Creating a Table based on External Tables and Views +Creating a Table based on Foreign Tables and Views ~~~~~~~~~~~~ -The following is example of creating a table based on external tables and views: +The following is example of creating a table based on foreign tables and views: .. code-block:: postgres @@ -272,7 +272,7 @@ The following is example of creating a table based on external tables and views: CREATE TABLE t3 LIKE v; When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. - + The following table describes the properties that must be copied from the target table: +-----------------------------+------------------+---------------------------------+---------------------------------+ @@ -293,4 +293,4 @@ The following table describes the properties that must be copied from the target Permissions ============= -The role must have the ``CREATE`` permission at the schema level. +The role must have the ``CREATE`` permission at the schema level. \ No newline at end of file From cadff73cb4b1bd196ba74fffc98c00dda54fdad5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 23 Jun 2022 11:21:16 +0300 Subject: [PATCH 0087/1892] Added missing varchar --- reference/sql/sql_syntax/literals.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index d1ec35dbe..906684590 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -86,7 +86,7 @@ Examples '1997-01-01' -- This is a string -The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``TEXT``. +The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``VARCHAR``. .. code-block:: postgres @@ -239,6 +239,7 @@ The following is a syntax reference for typed literals: | REAL | DATE | DATETIME + | VARCHAR ( digits ) | TEXT ( digits ) Examples From 0c1373094a37eb668559673b03df0c7974132758 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 28 Jun 2022 11:06:27 +0300 Subject: [PATCH 0088/1892] Update 2022.1.rst Changed 30% to 10%. --- releases/2022.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 53c314faf..45479026d 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -29,7 +29,7 @@ Data Encryption ************ SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. -Using the data encryption feature may lead to a maximum of a 30% increase in performance degradation. +Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. For more information, see `Data Encryption `_. From b456263b75d53f853c33e27592592f2ace13e152 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 30 Jun 2022 16:10:36 +0300 Subject: [PATCH 0089/1892] Update 2022.1.rst --- releases/2022.1.rst | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 45479026d..a98a397f8 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -74,7 +74,31 @@ No relevant naming changes were made. Deprecated Features ------- -No features were depecrated. +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. ``VARCHAR`` will be maintained in all previous versions until migration to ``TEXT`` is complete, at which point it will be deprecated in all earlier versions. + +If you are using an earlier version of SQream, see `Using Legacy String Literals `_. + +An automated process is being used to facilitate migration from ``VARCHAR`` to ``TEXT``. For more information, contact SQream. + +**Comment** - *Below is the original text of the VARCHAR deprecation email. I don't think that we need to necessarily expose our logic to our customers, but focus on certain aspects of it (see the first paragraph above). However, I can use more/all of this content if deemed necessary.* + +* SQream has decided to deprecated support in varchar data type, the decision made out of SQream effort to enhance its core functionalities and with respect to ever changing eco system requirements. + + :: + +* For new customers Varchar data type is not supported + + :: + +* The supported data type that will replace this data type is text as all different functionalities encapsulated within this data type + + :: + +* SQream will maintain varchar data type support until the last customer will be fully migrated + + :: + +* In order to enhance the conversion mechanism to be as fast as possible SQream will provide an automated and secured tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information Known Issues and Limitations -------- @@ -87,6 +111,8 @@ The the list below describes the following known issues and limitations: End of Support ------- +**Comment** - *We need to know what to put here.* + This section is not relevant to the 2022.1 release notes. Upgrading to v2022.1 From 24011e664692d0116fd4875a93a980acc7b30bc0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 11:10:24 +0300 Subject: [PATCH 0090/1892] Removed FULL OUTER JOIN https://sqream.atlassian.net/browse/SQ-10996 --- reference/sql/sql_syntax/joins.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index 2563e7a5d..b12b08875 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -46,8 +46,8 @@ The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres - left_side [ INNER ] JOIN right_side ON value_expr - left_side [ INNER ] JOIN right_side USING ( join_column [, ... ] ) + left_side [ INNER ] JOIN left_side ON value_expr + left_side [ INNER ] JOIN left_side USING ( join_column [, ... ] ) Inner joins are the default join type and return rows from the ``left_side`` and ``right_side`` based on a matching condition. @@ -60,7 +60,6 @@ An inner join can also be specified by listing several tables in the ``FROM`` cl [ { INNER JOIN | LEFT [OUTER] JOIN | RIGHT [OUTER] JOIN - | FULL [OUTER] JOIN } table2 ON table1.column1 = table2.column1 ] Omitting the ``ON`` or ``WHERE`` clause creates a ``CROSS JOIN``, where every ``left_side`` row is matched with every ``right_side`` row. @@ -117,7 +116,7 @@ The ``CROSS JOIN`` clause cannot have an ``ON`` clause, but the ``WHERE`` clause The following is an example of two tables that will be used as the basis for a cross join: -.. image:: /_static/images/joins/color_table.png +.. image:: /_static/images/color_table.png The following is the output result of the cross join: @@ -323,4 +322,4 @@ The following is an example of using a join hint: --+--- 2 | 2 4 | 4 - 5 | 5 + 5 | 5 \ No newline at end of file From dd2da3b8656204245f2349bf8b832df7547c9638 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 11:22:40 +0300 Subject: [PATCH 0091/1892] Create color_table.png --- _static/images/color_table.png | Bin 0 -> 5672 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 _static/images/color_table.png diff --git a/_static/images/color_table.png b/_static/images/color_table.png new file mode 100644 index 0000000000000000000000000000000000000000..b815f96167688d7c5b770dc427a358bc6169789a GIT binary patch literal 5672 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 literal 0 HcmV?d00001 From 823c64e552c995b1006ac98af4ba145630fbd03a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 3 Jul 2022 14:11:33 +0300 Subject: [PATCH 0092/1892] Updated Tableau Connector Link --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index 91cb94e8f..eebeeb003 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -24,7 +24,7 @@ The following are applicable to all operating systems: * **Tableau**: - * `https://sq-ftp-public.s3.amazonaws.com/SQreamTaco.rar>`_ - SQream (.taco) + * `Tableau connector `_ - SQream (.taco) * `Tableau manual installation `_ From bceda57ad26b51c5bd2731796f5d4eae3456f0f7 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 6 Jul 2022 11:46:13 +0300 Subject: [PATCH 0093/1892] Tables: https://sqream.atlassian.net/browse/TPD-208 --- .../sql_statements/dml_commands/copy_to.rst | 376 ++++++++++++++++-- 1 file changed, 345 insertions(+), 31 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 85632904f..bd32a325f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -3,20 +3,23 @@ ********************** COPY TO ********************** +The **COPY TO** page includes the following sections: +.. contents:: + :local: + :depth: 1 + +Overview +========== ``COPY ... TO`` is a statement that can be used to export data from a SQream database table or query to a file on the filesystem. In general, ``COPY`` moves data between filesystem files and SQream DB tables. .. note:: To copy data from a file to a table, see :ref:`COPY FROM`. -Permissions -============= - -The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. - Syntax ========== +The following is the correct syntax for using the **COPY TO** statement: .. code-block:: postgres @@ -29,7 +32,7 @@ Syntax ) ; - fdw_name ::= csw_fdw | parquet_fdw | orc_fdw | avro_fdw + fdw_name ::= csw_fdw | parquet_fdw | orc_fdw schema_name ::= identifer @@ -48,6 +51,11 @@ Syntax | AWS_ID = '{ AWS ID }' | AWS_SECRET = '{ AWS Secret }' + + | MAX_FILE_SIZE = '{ size_in_bytes }' + + | ENFORCE_SINGLE_FILE = { true | false } + delimiter ::= string @@ -57,8 +65,13 @@ Syntax AWS Secret ::= string +.. note:: The DELIMITER is applicable to the CSV format only. + +.. note:: In Studio, you must write the parameters using lower case letters. Using upper case letters generates an error. + Elements ============ +The following table shows the ``COPY_TO`` elements: .. list-table:: :widths: auto @@ -80,41 +93,332 @@ Elements - Specifies the character that separates fields (columns) within each row of the file. The default is a comma character (``,``). * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets + * - ``MAX_FILE_SIZE`` + - Sets the maximum file size (bytes). Default value: 16*2^20 (16MB). + * - ``ENFORCE_SINGLE_FILE`` + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``FALSE``. -Usage notes +Usage Notes =============== +The **Usage Notes** describes the following: + +.. contents:: + :local: + :depth: 1 -Supported field delimiters +Supported Field Delimiters ------------------------------ +The **Supported Field Delimiters** section describes the following: -Printable characters -^^^^^^^^^^^^^^^^^^^^^ +.. contents:: + :local: + :depth: 1 +Printable ASCII Characters +^^^^^^^^^^^^^^^^^^^^^ Any printable ASCII character can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). -A printable character is any ASCII character in the range 32 - 126. - -Non-printable characters +The following table shows the supported printable ASCII characters: + ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **ASCII** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| (Space) | Space | 32 | 40 | 20 | 100000 | | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ! | Exclamation Mark | 33 | 41 | 21 | 100001 | ! | ! | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| # | Hash or Number | 35 | 43 | 23 | 100011 | # | # | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| $ | Dollar Sign | 36 | 44 | 24 | 100100 | $ | $ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| % | Percentage | 37 | 45 | 25 | 100101 | % | % | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| & | Ampersand | 38 | 46 | 26 | 100110 | & | & | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ( | Left Parenthesis | 40 | 50 | 28 | 101000 | ( | ( | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ) | Right Parenthesis | 41 | 51 | 29 | 101001 | ) | ) | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| * | Asterisk | 42 | 52 | 2A | 101010 | * | * | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| + | Plus Sign | 43 | 53 | 2B | 101011 | + | + | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| , | Comma | 44 | 54 | 2C | 101100 | , | , | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| / | Slash | 47 | 57 | 2F | 101111 | / | / | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ; | Semicolon | 59 | 73 | 3B | 111011 | ; | ; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| < | Less Than | 60 | 74 | 3C | 111100 | < | < | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| = | Equals Sign | 61 | 75 | 3D | 111101 | = | = | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| > | Greater Than | 62 | 76 | 3E | 111110 | > | > | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ? | Question Mark | 63 | 77 | 3F | 111111 | ? | ? | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| @ | At Sign | 64 | 100 | 40 | 1000000 | @ | @ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| [ | Left Square Bracket | 91 | 133 | 5B | 1011011 | [ | [ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \ | Backslash | 92 | 134 | 5C | 1011100 | \ | \ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ] | Right Square Bracket | 93 | 135 | 5D | 1011101 | ] | ] | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ^ | Caret or Circumflex | 94 | 136 | 5E | 1011110 | ^ | &hat; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| _ | Underscore | 95 | 137 | 5F | 1011111 | _ | _ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ` | Grave Accent | 96 | 140 | 60 | 1100000 | ` | ` | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| { | Left Curly Bracket | 123 | 173 | 7B | 1111011 | { | { | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| | | Vertical Bar | 124 | 174 | 7C | 1111100 | | | | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| } | Right Curly Bracket | 125 | 175 | 7D | 1111101 | } | } | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ~ | Tilde | 126 | 176 | 7E | 1111110 | ~ | ˜ | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ + +Non-Printable ASCII Characters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -A non-printable character (1 - 31, 127) can be used in its octal form. - +The following table shows the supported non-printable ASCII characters: + ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **Octal** | **ASCII** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NUL | Null | 0 | 0 | 0 | 0 | � | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SOH | Start of Heading | 1 | 1 | 1 | 1 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| STX | Start of Text | 2 | 2 | 2 | 10 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETX | End of Text | 3 | 3 | 3 | 11 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EOT | End of Transmission | 4 | 4 | 4 | 100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ENQ | Enquiry | 5 | 5 | 5 | 101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ACK | Acknowledge | 6 | 6 | 6 | 110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BEL | Bell | 7 | 7 | 7 | 111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BS | Backspace | 10 | 8 | 8 | 1000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| HT | Horizontal Tab | 11 | 9 | 9 | 1001 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| VT | Vertical Tab | 13 | 11 | 0B | 1011 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FF | NP Form Feed, New Page | 14 | 12 | 0C | 1100 | | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SO | Shift Out | 16 | 14 | 0E | 1110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SI | Shift In | 17 | 15 | 0F | 1111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DLE | Data Link Escape | 20 | 16 | 10 | 10000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC1 | Device Control 1 | 21 | 17 | 11 | 10001 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC2 | Device Control 2 | 22 | 18 | 12 | 10010 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC3 | Device Control 3 | 23 | 19 | 13 | 10011 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC4 | Device Control 4 | 24 | 20 | 14 | 10100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NAK | Negative Acknowledge | 25 | 21 | 15 | 10101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SYN | Synchronous Idle | 26 | 22 | 16 | 10110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETB | End of Transmission Block | 27 | 23 | 17 | 10111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| CAN | Cancel | 30 | 24 | 18 | 11000 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EM | End of Medium | 31 | 25 | 19 | 11001 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SUB | Substitute | 32 | 26 | 1A | 11010 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ESC | Escape | 33 | 27 | 1B | 11011 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FS | File Separator | 34 | 28 | 1C | 11100 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| GS | Group Separator | 35 | 29 | 1D | 11101 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| RS | Record Separator | 36 | 30 | 1E | 11110 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| US | Unit Separator | 37 | 31 | 1F | 11111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DEL | Delete | 177 | 127 | 7F | 1111111 |  | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ + A tab can be specified by escaping it, for example ``\t``. Other non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. For example, ASCII character ``15``, known as "shift in", can be specified using ``E'\017'``. +.. note:: Delimiters are only applicable to the CSV file format. -Date format +Unsupported ASCII Field Delimiters +------------------------------ +The following table shows the unsupported ASCII field delimiters: + ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| **ASCII** | **Character** | **Description** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 10 | LF | NL Line Feed, New Line | 12 | 0A | 1010 | | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 13 | CR | Carriage Return | 15 | 0D | 1101 | | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 34 | " | Double Quote | 42 | 22 | 100010 | " | " | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 39 | ' | Single Quote | 47 | 27 | 100111 | ' | ' | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 45 | - | Minus Sign | 55 | 2D | 101101 | - | − | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 46 | . | Period | 56 | 2E | 101110 | . | . | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 48 | 0 | Zero | 60 | 30 | 110000 | 0 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 49 | 1 | Number One | 61 | 31 | 110001 | 1 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 50 | 2 | Number Two | 62 | 32 | 110010 | 2 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 51 | 3 | Number Three | 63 | 33 | 110011 | 3 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 52 | 4 | Number Four | 64 | 34 | 110100 | 4 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 53 | 5 | Number Five | 65 | 35 | 110101 | 5 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 54 | 6 | Number Six | 66 | 36 | 110110 | 6 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 55 | 7 | Number Seven | 67 | 37 | 110111 | 7 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 56 | 8 | Number Eight | 70 | 38 | 111000 | 8 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 57 | 9 | Number Nine | 71 | 39 | 111001 | 9 | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 58 | : | Colon | 72 | 3A | 111010 | : | : | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 65 | A | Upper Case Letter A | 101 | 41 | 1000001 | A | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 66 | B | Upper Case Letter B | 102 | 42 | 1000010 | B | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 67 | C | Upper Case Letter C | 103 | 43 | 1000011 | C | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 68 | D | Upper Case Letter D | 104 | 44 | 1000100 | D | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 69 | E | Upper Case Letter E | 105 | 45 | 1000101 | E | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 70 | F | Upper Case Letter F | 106 | 46 | 1000110 | F | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 71 | G | Upper Case Letter G | 107 | 47 | 1000111 | G | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 72 | H | Upper Case Letter H | 110 | 48 | 1001000 | H | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 73 | I | Upper Case Letter I | 111 | 49 | 1001001 | I | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 74 | J | Upper Case Letter J | 112 | 4A | 1001010 | J | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 75 | K | Upper Case Letter K | 113 | 4B | 1001011 | K | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 76 | L | Upper Case Letter L | 114 | 4C | 1001100 | L | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 77 | M | Upper Case Letter M | 115 | 4D | 1001101 | M | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 78 | N | Upper Case Letter N | 116 | 4E | 1001110 | N | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 79 | O | Upper Case Letter O | 117 | 4F | 1001111 | O | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 80 | P | Upper Case Letter P | 120 | 50 | 1010000 | P | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 81 | Q | Upper Case Letter Q | 121 | 51 | 1010001 | Q | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 82 | R | Upper Case Letter R | 122 | 52 | 1010010 | R | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 83 | S | Upper Case Letter S | 123 | 53 | 1010011 | S | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 84 | T | Upper Case Letter T | 124 | 54 | 1010100 | T | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 85 | U | Upper Case Letter U | 125 | 55 | 1010101 | U | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 86 | V | Upper Case Letter V | 126 | 56 | 1010110 | V | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 87 | W | Upper Case Letter W | 127 | 57 | 1010111 | W | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 88 | X | Upper Case Letter X | 130 | 58 | 1011000 | X | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 89 | Y | Upper Case Letter Y | 131 | 59 | 1011001 | Y | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 90 | Z | Upper Case Letter Z | 132 | 5A | 1011010 | Z | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 97 | a | Lower Case Letter a | 141 | 61 | 1100001 | a | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 98 | b | Lower Case Letter b | 142 | 62 | 1100010 | b | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 99 | c | Lower Case Letter c | 143 | 63 | 1100011 | c | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 100 | d | Lower Case Letter d | 144 | 64 | 1100100 | d | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 101 | e | Lower Case Letter e | 145 | 65 | 1100101 | e | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 102 | f | Lower Case Letter f | 146 | 66 | 1100110 | f | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 103 | g | Lower Case Letter g | 147 | 67 | 1100111 | g | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 104 | h | Lower Case Letter h | 150 | 68 | 1101000 | h | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 105 | i | Lower Case Letter i | 151 | 69 | 1101001 | i | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 106 | j | Lower Case Letter j | 152 | 6A | 1101010 | j | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 107 | k | Lower Case Letter k | 153 | 6B | 1101011 | k | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 108 | l | Lower Case Letter l | 154 | 6C | 1101100 | l | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 109 | m | Lower Case Letter m | 155 | 6D | 1101101 | m | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 110 | n | Lower Case Letter n | 156 | 6E | 1101110 | n | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 111 | o | Lower Case Letter o | 157 | 6F | 1101111 | o | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 112 | p | Lower Case Letter p | 160 | 70 | 1110000 | p | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 113 | q | Lower Case Letter q | 161 | 71 | 1110001 | q | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 114 | r | Lower Case Letter r | 162 | 72 | 1110010 | r | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 115 | s | Lower Case Letter s | 163 | 73 | 1110011 | s | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 116 | t | Lower Case Letter t | 164 | 74 | 1110100 | t | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 117 | u | Lower Case Letter u | 165 | 75 | 1110101 | u | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 118 | v | Lower Case Letter v | 166 | 76 | 1110110 | v | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 119 | w | Lower Case Letter w | 167 | 77 | 1110111 | w | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 120 | x | Lower Case Letter x | 170 | 78 | 1111000 | x | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 121 | y | Lower Case Letter y | 171 | 79 | 1111001 | y | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 122 | z | Lower Case Letter z | 172 | 7A | 1111010 | z | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ + +Date Format --------------- - The date format in the output CSV is formatted as ISO 8601 (``2019-12-31 20:30:55.123``), regardless of how it was parsed initially with :ref:`COPY FROM date parsers`. +For more information on the ``datetime`` format, see :ref:`sql_data_types_date`. Examples =========== +The **Examples** section shows the following examples: + +.. contents:: + :local: + :depth: 1 -Export table to a CSV without HEADER +Exporting a Table to a CSV File without a HEADER Row ------------------------------------ +The following is an example of exporting a table to a CSV file without a HEADER row: .. code-block:: psql @@ -130,8 +434,9 @@ Export table to a CSV without HEADER Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 Amir Johnson,Boston Celtics,90,PF,29,6-9,240,\N,12000000 -Export table to a CSV with a HEADER row +Exporting a Table to a CSV with a HEADER Row ----------------------------------------- +The following is an example of exporting a table to a CSV file with a HEADER row: .. code-block:: psql @@ -147,8 +452,9 @@ Export table to a CSV with a HEADER row R.J. Hunter,Boston Celtics,28,SG,22,6-5,185,Georgia State,1148640 Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 -Export table to a TSV with a header row +Exporting a Table to TSV with a HEADER Row ----------------------------------------- +The following is an example of exporting a table to a TSV file with a HEADER row: .. code-block:: psql @@ -164,8 +470,9 @@ Export table to a TSV with a header row R.J. Hunter Boston Celtics 28 SG 22 6-5 185 Georgia State 1148640 Jonas Jerebko Boston Celtics 8 PF 29 6-10 231 \N 5000000 -Use non-printable ASCII characters as delimiter +Using Non-Printable ASCII Characters as Delimiters ------------------------------------------------------- +The following is an example of using non-printable ASCII characters as delimiters: Non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. @@ -179,8 +486,9 @@ For example, ASCII character ``15``, known as "shift in", can be specified using COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\011'); -- 011 is a tab character -Exporting the result of a query to a CSV +Exporting the Result of a Query to CSV File -------------------------------------------- +The following is an example of exporting the result of a query to a CSV file: .. code-block:: psql @@ -195,40 +503,46 @@ Exporting the result of a query to a CSV Charlotte Hornets,5222728 Chicago Bulls,5785558 -Saving files to an authenticated S3 bucket +Saving Files to an Authenticated S3 Bucket -------------------------------------------- +The following is an example of saving files to an authenticated S3 bucket: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 's3://my_bucket/salaries/nba_export.csv', AWS_ID = 'my_aws_id', AWS_SECRET = 'my_aws_secret'); -Saving files to an HDFS path +Saving Files to an HDFS Path -------------------------------------------- +The following is an example of saving files to an HDFS path: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 'hdfs://pp_namenode:8020/nba_export.csv'); - -Export table to a parquet file +Exporting a Table to a Parquet File ------------------------------ +The following is an example of exporting a table to a Parquet file: .. code-block:: psql COPY nba TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/nba_export.parquet'); - -Export a query to a parquet file +Exporting a Query to a Parquet File -------------------------------- +The following is an example of exporting a query to a Parquet file: .. code-block:: psql COPY (select x,y from t where z=0) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); - -Export table to a ORC file +Exporting a Table to an ORC File ------------------------------ +The following is an example of exporting a table to an ORC file: .. code-block:: psql COPY nba TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/nba_export.orc'); + +Permissions +============= +The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. From 315d0c7895a5a3d03da00c9a133e0a1de35d82c6 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 6 Jul 2022 16:04:20 +0300 Subject: [PATCH 0094/1892] Updated with Slavi --- operational_guides/hardware_guide.rst | 83 +++++++++++++++++++++------ 1 file changed, 65 insertions(+), 18 deletions(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index d66797223..571d6a6a3 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -3,9 +3,7 @@ *********************** Hardware Guide *********************** - -This guide describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. - +The **Hardware Guide** describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. .. rubric:: Need help? @@ -15,20 +13,22 @@ Visit `SQream's support portal Date: Wed, 6 Jul 2022 16:19:35 +0300 Subject: [PATCH 0095/1892] Update hardware_guide.rst From 8127a478798529ae4ae830ecf2f272dedb4fb1a9 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Wed, 6 Jul 2022 16:23:57 +0300 Subject: [PATCH 0096/1892] Update hardware_guide.rst --- operational_guides/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index 571d6a6a3..252b71fc2 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -78,7 +78,7 @@ The following table shows SQream's recommended hardware specifications: .. list-table:: :widths: 15 65 - :header-rows: 2 + :header-rows: 1 * - Component - Type From 9eb8a69c627052e3d887030fbd173a8b2dbed647 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 17:08:18 +0300 Subject: [PATCH 0097/1892] https://sqream.atlassian.net/browse/TPD-168 --- operational_guides/external_data.rst | 15 +- operational_guides/hdfs.rst | 252 +++++++++++++++++++++++++++ operational_guides/s3.rst | 26 +-- 3 files changed, 272 insertions(+), 21 deletions(-) create mode 100644 operational_guides/hdfs.rst diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index 576e50ea4..8bf51f108 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -3,12 +3,23 @@ ********************************** Working with External Data ********************************** - -SQream DB supports external data sources for use with :ref:`external_tables`, :ref:`copy_from`, and :ref:`copy_to`. +SQream supports the following external data sources: .. toctree:: :maxdepth: 1 :titlesonly: s3 + hdfs + +For more information, see the following: + +* :ref:`external_tables` + + :: + +* :ref:`copy_from` + + :: +* :ref:`copy_to` \ No newline at end of file diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst new file mode 100644 index 000000000..a6ffe0ead --- /dev/null +++ b/operational_guides/hdfs.rst @@ -0,0 +1,252 @@ +.. _hdfs: + +.. _back_to_top_hdfs: + +Using SQream in an HDFS Environment +======================================= + +.. _configuring_an_hdfs_environment_for_the_user_sqream: + +Configuring an HDFS Environment for the User **sqream** +---------------------------------------------------------- + +This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. + +**To configure an HDFS environment for the user sqream:** + +1. Open your **bash_profile** configuration file for editing: + + .. code-block:: console + + $ vim /home/sqream/.bash_profile + +.. + Comment: - see below; do we want to be a bit more specific on what changes we're talking about? + + .. code-block:: console + + $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin + + $ #export PATH + + $ # PS1 + $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') + $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +2. Verify that the edits have been made: + + .. code-block:: console + + source /home/sqream/.bash_profile + +3. Check if you can access Hadoop from your machine: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +.. + Comment: - + **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos `_ + + +4. Verify that an HDFS environment exists for SQream services: + + .. code-block:: console + + $ ls -l /etc/sqream/sqream_env.sh + +.. _step_6: + + +5. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): + + .. code-block:: console + + $ #!/bin/bash + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +:ref:`Back to top ` + + +.. _authenticate_hadoop_servers_that_require_kerberos: + +Authenticating Hadoop Servers that Require Kerberos +--------------------------------------------------- + +If your Hadoop server requires Kerberos authentication, do the following: + +1. Create a principal for the user **sqream**. + + .. code-block:: console + + $ kadmin -p root/admin@SQ.COM + $ addprinc sqream@SQ.COM + +2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: + + .. code-block:: console + + $ kadmin.local + + Running **kadmin.local** does not require a password. + +3. If a password is not required, change your password to **sqream@SQ.COM**. + + .. code-block:: console + + $ change_password sqream@SQ.COM + +4. Connect to the hadoop name node using ssh: + + .. code-block:: console + + $ cd /var/run/cloudera-scm-agent/process + +5. Check the most recently modified content of the directory above: + + .. code-block:: console + + $ ls -lrt + +6. Look for a recently updated folder containing the text **hdfs**. + +The following is an example of the correct folder name: + + .. code-block:: console + + cd -hdfs- + + This folder should contain a file named **hdfs.keytab** or another similar .keytab file. + + + +.. + Comment: - Does "something" need to be replaced with "file name" + + +7. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. + +8. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: + + * core-site.xml + * hdfs-site.xml + +9. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: + + .. code-block:: console + + $ sudo chown sqream:sqream /home/sqream/hdfs.keytab + $ sudo chmod 600 /home/sqream/hdfs.keytab + +10. Log into the sqream server. + +11. Log in as the user **sqream**. + +12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: + + .. code-block:: console + + $ klist -kt hdfs.keytab + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream@Host-121 ~ $ klist -kt hdfs.keytab + $ Keytab name: FILE:hdfs.keytab + $ KVNO Timestamp Principal + $ ---- ------------------- ------------------------------------------------------ + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + +13. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. + +14. Run the following: + + .. code-block:: console + + $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM + +15. Check the output: + + .. code-block:: console + + $ klist + + The following is an example of the correct output: + + .. code-block:: console + + $ Ticket cache: FILE:/tmp/krb5cc_1000 + $ Default principal: sqream@SQ.COM + $ + $ Valid starting Expires Service principal + $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM + +16. List the files located at the defined server name or IP address: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +17. Do one of the following: + + * If the list below is output, continue with Step 16. + * If the list is not output, verify that your environment has been set up correctly. + +If any of the following are empty, verify that you followed :ref:`Step 6 ` in the **Configuring an HDFS Environment for the User sqream** section above correctly: + + .. code-block:: console + + $ echo $JAVA_HOME + $ echo $SQREAM_HOME + $ echo $CLASSPATH + $ echo $HADOOP_COMMON_LIB_NATIVE_DIR + $ echo $LD_LIBRARY_PATH + $ echo $PATH + +18. Verify that you copied the correct keytab file. + +19. Review this procedure to verify that you have followed each step. + +:ref:`Back to top ` \ No newline at end of file diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst index 699f35401..f8bb2dab6 100644 --- a/operational_guides/s3.rst +++ b/operational_guides/s3.rst @@ -1,9 +1,8 @@ .. _s3: *********************** -Amazon S3 +Inserting Data Using Amazon S3 *********************** - SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. The **Amazon S3** describes the following topics: @@ -13,12 +12,10 @@ The **Amazon S3** describes the following topics: S3 Configuration ============================== - Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. S3 URI Format =============== - With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. The following is an example of the general S3 syntax: @@ -29,12 +26,10 @@ The following is an example of the general S3 syntax: Authentication ================= - SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples ========== - Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. The **Examples** section includes the following examples: @@ -42,12 +37,8 @@ The **Examples** section includes the following examples: .. contents:: :local: :depth: 1 - - - Planning for Data Staging -------------------------------- - The examples in this section are based on a CSV file, as shown in the following table: .. csv-table:: nba.csv @@ -59,21 +50,20 @@ The file is stored on Amazon S3, and this bucket is public and listable. To crea Creating a Foreign Table ----------------------------- - Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres CREATE FOREIGN TABLE nba ( - Name text(40), - Team text(40), + Name varchar(40), + Team varchar(40), Number tinyint, - Position text(2), + Position varchar(2), Age tinyint, - Height text(4), + Height varchar(4), Weight real, - College text(40), + College varchar(40), Salary float ) WRAPPER csv_fdw @@ -93,7 +83,6 @@ For more information, see the following: Querying Foreign Tables ------------------------------ - The following shows the data in the foreign table: .. code-block:: psql @@ -114,7 +103,6 @@ The following shows the data in the foreign table: Bulk Loading a File from a Public S3 Bucket ---------------------------------------------- - The ``COPY FROM`` command can also be used to load data without staging it first. .. note:: The bucket must be publicly available and objects can be listed. @@ -135,4 +123,4 @@ The following is an example of loading fles from an authenticated S3 bucket: COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; + AWS_SECRET 'super_secretive_secret'; \ No newline at end of file From 2b2b6b90a15652d1625f7a19d4a2765ad5bc588d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 17:23:22 +0300 Subject: [PATCH 0098/1892] TPD-221 --- operational_guides/hardware_guide.rst | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/operational_guides/hardware_guide.rst b/operational_guides/hardware_guide.rst index 252b71fc2..5337db9cd 100644 --- a/operational_guides/hardware_guide.rst +++ b/operational_guides/hardware_guide.rst @@ -126,27 +126,6 @@ The following table shows SQream's recommended metadata server specifications: * - Operating System - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux -Web User Interface Specifications -~~~~~~~~~~~~~~~~~~~~~~~~~ -The following table shows SQream's recommended web user interface server specifications: - -.. list-table:: - :widths: 15 90 - :header-rows: 1 - - * - Component - - Type - * - Processors - - One Intel i7 16C processor or similar - * - RAM - - 64 GB DDR4 RAM 2x32 GB RDIMM or similar - * - Discs - - 256 GB SATA 6Gb SSD drive or similar - * - Network Card (Corporate) - - Two 1 GbE cards or similar - * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux - .. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. SQream Studio Server Example @@ -246,4 +225,4 @@ For clustered scale-out installations, SQream relies on NAS/SAN storage. For sta SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream Reference Architecture `_ document. +Download the full `SQream Reference Architecture `_ document. \ No newline at end of file From 3e5001a32c650f5189080787903707661cc7f10f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 6 Jul 2022 18:26:42 +0300 Subject: [PATCH 0099/1892] Update index.rst --- third_party_tools/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party_tools/client_drivers/index.rst b/third_party_tools/client_drivers/index.rst index eebeeb003..d0c60d804 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/third_party_tools/client_drivers/index.rst @@ -1,7 +1,7 @@ .. _client_drivers: ************************************ -Client Drivers for |latest_version| +Client Drivers for 2022.1 ************************************ The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. From 711ae8192c2def0e86346b295e1eeb75916e7db2 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 7 Jul 2022 15:43:23 +0300 Subject: [PATCH 0100/1892] Updated the following: Delete Guide: improvements SQL Statements > Index: improved tables SQL Statements: created get_extents_file_list_for_chunk page (in review) SQL Statements: created get_metadata_chunk_key page (in review) --- operational_guides/delete_guide.rst | 272 +++++++++++------- reference/sql/sql_statements/index.rst | 84 +++--- .../get_extents_file_list_for_chunk.rst | 60 ++++ .../get_metadata_chunk_key.rst | 59 ++++ 4 files changed, 325 insertions(+), 150 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index 24ab5a218..c24079f8c 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -3,144 +3,183 @@ *********************** Deleting Data *********************** +The **Deleting Data** page describes how the **Delete** statement works and how to maintain data that you delete: -SQream DB supports deleting data, but it's important to understand how this works and how to maintain deleted data. +.. contents:: + :local: + :depth: 1 -How does deleting in SQream DB work? +Overview ======================================== +Deleting data typically refers to deleting rows, but can refer to deleting other table content as well. The general workflow for deleting data is to delete data followed by triggering a cleanup operation. The cleanup operation reclaims the space occupied by the deleted rows, discussed further below. -In SQream DB, when you run a delete statement, any rows that match the delete predicate will no longer be returned when running subsequent queries. -Deleted rows are tracked in a separate location, in *delete predicates*. +The **DELETE** statement deletes rows defined by a predicate that you have specified, preventing them from appearing in subsequent queries. -After the delete statement, a separate process can be used to reclaim the space occupied by these rows, and to remove the small overhead that queries will have until this is done. +For example, the predicate below defines and deletes rows containing animals heavier than 1000 weight units: -Some benefits to this design are: - -#. Delete transactions complete quickly +.. code-block:: psql -#. The total disk footprint overhead at any time for a delete transaction or cleanup process is small and bounded (while the system still supports low overhead commit, rollback and recovery for delete transactions). + farm=> DELETE FROM cool_animals WHERE weight > 1000; +The major benefit of the DELETE statement is that it deletes transactions simply and quickly. -Phase 1: Delete ---------------------------- +The Deletion Process +========== +Deleting rows occurs in the following two phases: -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? +* **Phase 1 - Deletion** - All rows you mark for deletion are ignored when you run any query. These rows are not deleted until the clean-up phase. -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them + :: -When a :ref:`delete` statement is run, SQream DB records the delete predicates used. These predicates will be used to filter future statements on this table until all this delete predicate's matching rows have been physically cleaned up. +* **Phase 2 - Clean-up** - The rows you marked for deletion in Phase 1 are physically deleted. The clean-up phase is not automated, letting users or DBAs control when to activate it. The files you marked for deletion during Phase 1 are removed from disk, which you do by by sequentially running the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. -This filtering process takes full advantage of SQream's zone map feature. +.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? -Phase 2: Clean-up --------------------- +.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them. -The cleanup process is not automatic. This gives control to the user or DBA, and gives flexibility on when to run the clean up. +Usage Notes +===================== +The **Usage Notes** section includes important information about the DELETE statement: -Files marked for deletion during the logical deletion stage are removed from disk. This is achieved by calling both utility function commands: ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` sequentially. +.. contents:: + :local: + :depth: 1 + +General Notes +---------------- +This section describes the general notes applicable when deleting rows: -.. note:: - * :ref:`alter_table` and other DDL operations are blocked on tables that require clean-up. See more in the :ref:`concurrency_and_locks` guide. - * If the estimated time for a cleanup processs is beyond a threshold, you will get an error message about it. The message will explain how to override this limitation and run the process anywhere. +* The :ref:`alter_table` command and other DDL operations are locked on tables that require clean-up. If the estimated clean-up time exceeds the permitted threshold, an error message is displayed describing how to override the threshold limitation. For more information, see :ref:`concurrency_and_locks`. -Notes on data deletion -========================================= + :: -.. note:: - * If the number of deleted records crosses the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation will be aborted. - * This is intended to alert the user that the large number of deleted records may result in a large number of mixed chuncks. - * To circumvent this alert, replace XXX with the desired number of records before running the delete operation: +* If the number of deleted records exceeds the threshold defined by the ``mixedColumnChunksThreshold`` parameter, the delete operation is aborted. This alerts users that the large number of deleted records may result in a large number of mixed chunks. To circumvent this alert, use the following syntax (replacing ``XXX`` with the desired number of records) before running the delete operation: -.. code-block:: postgres + .. code-block:: postgres - set mixedColumnChunksThreshold=XXX; + set mixedColumnChunksThreshold=XXX; - -Deleting data does not free up space +Deleting Data does not Free Space ----------------------------------------- +With the exception of running a full table delete, deleting data does not free unused disk space. To free unused disk space you must trigger the clean-up process. -With the exception of a full table delete (:ref:`TRUNCATE`), deleting data does not free up disk space. To free up disk space, trigger the cleanup process. - -``SELECT`` performance on deleted rows ----------------------------------------- - -Queries on tables that have deleted rows may have to scan data that hasn't been cleaned up. -In some cases, this can cause queries to take longer than expected. To solve this issue, trigger the cleanup process. +For more information on running a full table delete, see :ref:`TRUNCATE`. -Use ``TRUNCATE`` instead of ``DELETE`` ---------------------------------------- -For tables that are frequently emptied entirely, consider using :ref:`truncate` rather than :ref:`delete`. TRUNCATE removes the entire content of the table immediately, without requiring a subsequent cleanup to free up disk space. + :: + +For more information on freeing disk space, see :ref:`Triggering a Clean-Up`. -Cleanup is I/O intensive +Clean-Up Operations Are I/O Intensive ------------------------------- +The clean-up process reduces table size by removing all unused space from column chunks. While this reduces query time, it is a time-costly operation occupying disk space for the new copy of the table until the operation is complete. -The cleanup process actively compacts tables by writing a complete new version of column chunks with no dead space. This minimizes the size of the table, but can take a long time. It also requires extra disk space for the new copy of the table, until the operation completes. - -Cleanup operations can create significant I/O load on the database. Consider this when planning the best time for the cleanup process. +.. tip:: Because clean-up operations can create significant I/O load on your database, consider using them sparingly during ideal times. If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. - -Example +Examples ============= +The **Examples** section includes the following examples: -Deleting values from a table +.. contents:: + :local: + :depth: 1 + +Deleting Rows from a Table ------------------------------ +The following example shows how to delete rows from a table. -.. code-block:: psql +1. Display the table: + + .. code-block:: psql - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N + farm=> SELECT * FROM cool_animals; - 6 rows + The following table is displayed: + + .. code-block:: psql + + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed +2. Delete rows from the table: + + .. code-block:: psql + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + +3. Display the table: + + .. code-block:: psql + + farm=> SELECT * FROM cool_animals; - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N + The following table is displayed: + + .. code-block:: psql + + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N - 4 rows - -Deleting values based on more complex predicates +Deleting Values Based on Complex Predicates --------------------------------------------------- +The following example shows how to delete values based on complex predicates. -.. code-block:: psql +1. Display the table: + + .. code-block:: psql - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N + farm=> SELECT * FROM cool_animals; - 6 rows + The following table is displayed: + + .. code-block:: psql + + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 4,Elephant ,6500 + 5,Rhinoceros ,2100 + 6,\N,\N - farm=> DELETE FROM cool_animals WHERE weight > 1000; - executed +2. Delete rows from the table: + + .. code-block:: psql + + farm=> DELETE FROM cool_animals WHERE weight > 1000; + +3. Display the table: + + .. code-block:: psql + + farm=> SELECT * FROM cool_animals; - farm=> SELECT * FROM cool_animals; - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N + The following table is displayed: + + .. code-block:: psql + + 1,Dog ,7 + 2,Possum ,3 + 3,Cat ,5 + 6,\N,\N - 4 rows - -Identifying and cleaning up tables +Identifying and Cleaning Up Tables --------------------------------------- +The **Identifying and Cleaning Up Tables** section includes the following examples: -List tables that haven't been cleaned up +.. contents:: + :local: + :depth: 1 + +Listing Tables that Have Not Been Cleaned Up ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following example shows how to list tables that have not been cleaned up: .. code-block:: psql @@ -152,8 +191,9 @@ List tables that haven't been cleaned up 1 row -Identify predicates for clean-up +Identifying Predicates for Clean-Up ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following example shows how to identify predicates for clean-up: .. code-block:: psql @@ -164,42 +204,55 @@ Identify predicates for clean-up weight > 1000 1 row + +.. _trigger_cleanup: -Triggering a cleanup +Triggering a Clean-Up ^^^^^^^^^^^^^^^^^^^^^^ +The following example shows how to trigger a clean-up: -.. code-block:: psql +1. Run the chunk ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: + + .. code-block:: psql + + farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - -- Chunk reorganization (aka SWEEP) - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); - executed +2. Run the ``CLEANUP_EXTENTS`` command (also known as ``VACUUM``) to delete the leftover files: - -- Delete leftover files (aka VACUUM) - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - executed + .. code-block:: psql + farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; +3. Display the table: + + .. code-block:: psql - 0 rows + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + +Best Practices +===================================== +This section includes the best practices when deleting rows: +* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after running large ``DELETE`` operations. + :: -Best practices for data deletion -===================================== +* When you delete large segments of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, renaming, and dropping the original table. -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after large ``DELETE`` operations. + :: -* When deleting large proportions of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, then rename and drop the original table. +* Avoid killing ``CLEANUP_EXTENTS`` operations in progress. -* Avoid killing ``CLEANUP_EXTENTS`` operations after they've started. + :: -* SQream DB is optimised for time-based data. When data is naturally ordered by a date or timestamp, deleting based on those columns will perform best. For more information, see our :ref:`time based data management guide`. +* SQream is optimized for time-based data, which is data naturally ordered according to date or timestamp. Deleting rows based on such columns leads to increased performance. + :: +For more information, see `Time-Based Data Management `_. .. soft update concept @@ -210,5 +263,4 @@ Best practices for data deletion .. when does delete use the metadata effectively -.. more examples - +.. more examples \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index d0a6c04c8..67c9db172 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -9,81 +9,81 @@ The **SQL Statements** page describes the following commands: :local: :depth: 1 -SQream DB supports commands from ANSI SQL. +SQream supports commands from ANSI SQL. .. _ddl_commands_list: Data Definition Commands (DDL) ================================ +The following table shows the Data Definition commands: -.. list-table:: DDL Commands - :widths: auto +.. list-table:: + :widths: 10 100 :header-rows: 1 :name: ddl_commands * - Command - Usage - * - :ref:`add_column` + * - :ref:`ADD_COLUMN` - Add a new column to a table - * - :ref:`alter_default_schema` + * - :ref:`ALTER_DEFAULT_SCHEMA` - Change the default schema for a role - * - :ref:`alter_table` + * - :ref:`ALTER_TABLE` - Change the schema of a table - * - :ref:`cluster_by` + * - :ref:`CLUSTER_BY` - Change clustering keys in a table - * - :ref:`create_database` + * - :ref:`CREATE_DATABASE` - Create a new database - * - :ref:`create_external_table` - - Create a new external table in the database (deprecated) - * - :ref:`create_foreign_table` + * - :ref:`CREATE_FOREIGN_TABLE` - Create a new foreign table in the database - * - :ref:`create_function` + * - :ref:`CREATE_FUNCTION` - Create a new user defined function in the database - * - :ref:`create_schema` + * - :ref:`CREATE_SCHEMA` - Create a new schema in the database - * - :ref:`create_table` + * - :ref:`CREATE_TABLE` - Create a new table in the database - * - :ref:`create_table_as` + * - :ref:`CREATE_TABLE_AS` - Create a new table in the database using results from a select query - * - :ref:`create_view` + * - :ref:`CREATE_VIEW` - Create a new view in the database - * - :ref:`drop_clustering_key` + * - :ref:`DROP_CLUSTERING_KEY` - Drops all clustering keys in a table - * - :ref:`drop_column` + * - :ref:`DROP_COLUMN` - Drop a column from a table - * - :ref:`drop_database` + * - :ref:`DROP_DATABASE` - Drop a database and all of its objects - * - :ref:`drop_function` + * - :ref:`DROP_FUNCTION` - Drop a function - * - :ref:`drop_schema` + * - :ref:`DROP_SCHEMA` - Drop a schema - * - :ref:`drop_table` + * - :ref:`DROP_TABLE` - Drop a table and its contents from a database - * - :ref:`drop_view` + * - :ref:`DROP_VIEW` - Drop a view - * - :ref:`rename_column` + * - :ref:`RENAME_COLUMN` - Rename a column - * - :ref:`rename_table` + * - :ref:`RENAME_TABLE` - Rename a table + Data Manipulation Commands (DML) ================================ +The following table shows the Data Manipulation commands: -.. list-table:: DML Commands - :widths: auto +.. list-table:: + :widths: 10 100 :header-rows: 1 :name: dml_commands - * - Command - Usage - * - :ref:`CREATE TABLE AS` + * - :ref:`CREATE_TABLE_AS` - Create a new table in the database using results from a select query * - :ref:`DELETE` - Delete specific rows from a table - * - :ref:`COPY FROM` + * - :ref:`COPY_FROM` - Bulk load CSV data into an existing table - * - :ref:`COPY TO` + * - :ref:`COPY_TO` - Export a select query or entire table to CSV files * - :ref:`INSERT` - Insert rows into a table @@ -98,15 +98,20 @@ Data Manipulation Commands (DML) Utility Commands ================== +The following table shows the Utility commands: -.. list-table:: Utility Commands - :widths: auto +.. list-table:: + :widths: 10 100 :header-rows: 1 * - Command - Usage * - :ref:`EXPLAIN` - Returns a static query plan, which can be used to debug query plans + * - :ref:`GET_EXTENTS_FILE_FOR_CHUNK` + - Points to all files that contain data related to a specific chunk + * - :ref:`GET_METADATA_CHUNK_KEY` + - Returns a list of metadata key values for the chunks that you specify * - :ref:`SELECT GET_LICENSE_INFO` - View a user's license information * - :ref:`SELECT GET_DDL` @@ -132,14 +137,12 @@ Utility Commands * - :ref:`STOP STATEMENT` - Stops or aborts an active statement - - - Workload Management ====================== +The following table shows the Workload Management commands: -.. list-table:: Workload Management - :widths: auto +.. list-table:: + :widths: 10 100 :header-rows: 1 * - Command @@ -153,9 +156,10 @@ Workload Management Access Control Commands ================================ +The following table shows the Access Control commands: -.. list-table:: Access Control Commands - :widths: auto +.. list-table:: + :widths: 10 100 :header-rows: 1 * - Command diff --git a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst new file mode 100644 index 000000000..2f872812a --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst @@ -0,0 +1,60 @@ +.. _get_extents_file_list_for_chunk: + +******************** +GET_EXTENTS_FILE_FOR_CHUNK +******************** +The ``GET_EXTENTS_FILE_FOR_CHUNK`` command points to all files that contain data related to a specific chunk. This command is used for debugging purposes. + +This reference page includes the following information: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the syntax for the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: + +.. code-block:: postgres + + select get_extents_file_list_for_chunk(database_name, " + "table_id, chunk_id);" + +Output +========== +The following is an example of the output generated by the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: + +.. code-block:: postgres + + EXAMPLE NEEDED + +Parameters +============ +The following table shows the ``GET_EXTENTS_FILE_FOR_CHUNK`` parameters: + +.. list-table:: + :widths: 10 100 + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The name of the database where the chunk is located. + * - ``table_id`` + - The ID of the table where the chunk is located. + * - ``chunk_id`` + - The ID of the chunk. + +Examples +=========== +The following is an example of the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: + +.. code-block:: postgres + + Example - pending from Eyal W. + +Permissions +============= +The ``GET_EXTENTS_FILE_FOR_CHUNK`` requires no special permissions. + +**Comment** - *Does it require any special permissions?* \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst new file mode 100644 index 000000000..2ccc59132 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -0,0 +1,59 @@ +.. _get_metadata_chunk_key: + +******************** +GET_METADATA_CHUNK_KEY +******************** +The ``GET_METADATA_CHUNK_KEY`` command returns specific metadata key values for user-specified chunks. + +This reference page includes the following information: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the syntax for the ``GET_METADATA_CHUNK_KEY`` command: + +.. code-block:: postgres + + get_metadata_chunk_key(database_name, table_id, chunk_id); + +Output +========== +The following is an example of the output generated by the ``GET_METADATA_CHUNK_KEY`` command: + +.. code-block:: postgres + + EXAMPLE NEEDED + +Parameters +============ +The following table shows the ``GET_METADATA_CHUNK_KEY`` parameters: + +.. list-table:: + :widths: 10 100 + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The name of the database where the chunk is located. + * - ``table_id`` + - The ID of the table where the chunk is located. + * - ``chunk_id`` + - The ID of the chunk. + +Examples +=========== +The following is an example of the ``GET_METADATA_CHUNK_KEY`` command: + +.. code-block:: postgres + + Example - pending from Eyal W. + +Permissions +============= +The ``GET_METADATA_CHUNK_KEY`` requires no special permissions. + +**Comment** - *Does it require any special permissions?* \ No newline at end of file From f9eed2503c2e2281f3b861f394aed69ad83f7e49 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 7 Jul 2022 15:52:41 +0300 Subject: [PATCH 0101/1892] Removed link to uncreated page. This uncreated page is related to Flexible Data Clustering, which is not released yet. The content for Flexible Data Clustering is saved locally for future use. --- operational_guides/delete_guide.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index c24079f8c..0d6c4a41c 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -250,10 +250,6 @@ This section includes the best practices when deleting rows: * SQream is optimized for time-based data, which is data naturally ordered according to date or timestamp. Deleting rows based on such columns leads to increased performance. - :: - -For more information, see `Time-Based Data Management `_. - .. soft update concept .. delete cleanup and it's properties. automatic/manual, in transaction or background From f9a3e9586fe5082fda571f47eace77207331eba0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 7 Jul 2022 16:22:53 +0300 Subject: [PATCH 0102/1892] Prepared for 2022.1 release --- _static/images/New_Dark_Gray.png | Bin 0 -> 1073 bytes _static/images/new_2022.1.png | Bin 882 -> 1085 bytes operational_guides/foreign_tables.rst | 10 +++++----- reference/sql/sql_statements/index.rst | 12 ++++++++++-- .../get_extents_file_list_for_chunk.rst | 6 +++++- .../get_metadata_chunk_key.rst | 6 +++++- releases/2022.1.rst | 12 +++++++++++- 7 files changed, 36 insertions(+), 10 deletions(-) create mode 100644 _static/images/New_Dark_Gray.png diff --git a/_static/images/New_Dark_Gray.png b/_static/images/New_Dark_Gray.png new file mode 100644 index 0000000000000000000000000000000000000000..34ac016ebccc01827492455680537addf4b08c9e GIT binary patch literal 1073 zcmV-11kU@3P)m00001b5ch_0Itp) z=>Px#1ZP1_K>z@;j|==^1poj532;bRa{vGqB>(^xB>_oNB=7(L1I9^2K~z{r?O3gH zB0&&t)+M!X5E~+>JOO7Am=J@CJ-3m;#36Ap8yVbLR7^G|0&_e8g@D*R!EJ%u`?_al znO&BdP^37jE??D9^Vc)e|Gm`yESFh0?hy?dl)goDYzTX&L__X1i59;pJzL5A|Ag@5 zgXl+{=rW-+Zectos&$BxjMCPM0@*Ntl=^p?L|=yXVO-YIwB-mwX1=tJ;3q00M3V33nT5BngE;kAx>Bwd~HlM0ZK z$|Uo5C~=C8?WQ)a?v*!I#PmY4HK8M(t`*1buB}(_3fGTtt8J0b*c)~Apa^D6EE5(g z=SxDbxRXO&!4M$qjtOV}JgPhoo$i&In6p62z@2bT7FZb@^dbx)A=j?A2jM4B!Tr zz*2;n5kgdpLx2{ztDrg*OaWsX#YHJ@3BV8=`^C8$8dTBS@U4Fl0tpii*xo3fQvisi z{8ynZZ$>eB1;rs$7bsnv#icP9R9iynA)vlLVMOIzROfdhE!dIgeU2aS$~w{5O0VHt z-xZQKBk010u4e*Cn6Ao+VZ4#8(ZGbuN)OeLJxB<*P^2lISV&WhN1)v`Ph7FmOF3Fs zcDs0VE?}#Q%u&VH1Bb+Zo?o5xfNPzjk`!iE(dR=>WAQD~%{WySH?yo6XZ+8NX<0;Q zNpWrwXBoEJ^OyuJ=6F7DQIU?%=lLWn(G>SpwJeD?-^K^o_gU-tn!c;5<$P>3yc188 zJ+3=E^xk#DzkMdld&_?H9!*n_{hHSrU#dP%tF7uA#|f!=wcY~x80F6hySn?v@x!Vq rRCUUQ%ivME-#C8AUwb`MQxN?HAc-16j1ijA00000NkvXXu0mjfU~=nV literal 0 HcmV?d00001 diff --git a/_static/images/new_2022.1.png b/_static/images/new_2022.1.png index 4861ba76a5b6c7d35703267596db1f4c0a8c9fb5..27b2d285af4bee0337de2888e4bfcf8dbbcc77b1 100644 GIT binary patch delta 1025 zcmV+c1pfQ-2E7Q783+ad000;Y^Td%MHGk4cL_t(oN9|a>YAQh#KJMm40x^Z;3A~U} zh-s|S-fjg6BuzTYbZIOkV7jzcX|jT4;Q9n&p+a87W$$;+%#O3`IukK?g_{pXc4qd> znK?h-9Ji7JG-?w))+qV7rDH?bIU#!Cr#jK%4<)CGjQ>vv!%w1LRicZSlII5cV}GJb zlPFG!u80DnB^(GVb?>x@GF*6q)`zeK8Sh|$10nqE!-4F)l#gm4mGfn-a3(fd zcxla_bo7jZSKc$f4a)9$U1dm;22l@oc^gSTpyfN!B%-8IVxapc{qT>lnBnK*TeDB1 zxH>~ntfbMRhd^oO1GbH*Cyaxnq<=*(a4G@{@X3E^{Q_8qovj$hfg0~i(CMNi(kaqIey@EBx69c34)ymiojSGi#oE=MLS{t(nK#Ki#9tb!hdlmCu2kI z!X`F3xmR+UlAJn42lS3JI>R#zzY}!!)0yfD#9*+K!w>r)c}CVc>X9Tll`Yv2N@btV zmvG_~4|bZ`xO!08SiT-bqV>dH8^WUQ?^MCNrLWRJXvq6f0P9!HAtcVTy0(|p(1NIE~%-bLlz}fin zxEaxMm*Qj(*5>ZIYsZ~k<= zJkSqr$R2**BM?yamDL0u_~iFp--{aTKb^ygK1epg8BeMb$^+xo3V+JotbyA#?MMLJ zKnWs64l_i7(qIbE26q)yhk`C(ILi&r3%n)3fjHRDZH@)X|0jZ|co$W9pE#(^oXa_Wa8~w-##VU^ z-~6tSd-E2)u%YXjKz}YwSLMXWvXP@PLq?aS8LA=g;6iA_ky-J?Mw+5OgzT>O#1%W8 z*Ryo$%5Im8HU_q;NQ1I-JuxMA&Hd_>2VC>aN>Z3vMV}8w#;Q$(-Lj-gd-XJ}_tMpB zWm+1cWQgMY*rKOO32PjKkToTSZc$#2*XQv#Ey(2GD{E;SZEo(37qazP^JY%#Dr@E( z8x8x!*5n?-KHRa{1 vyB{1steT?234Y8Uz<;m_`Lt&~fD`=%VF?q}GPb_U00000NkvXXu0mjfk%{+R delta 821 zcmV-51Iqlp2=WGy83+OZ005V0WRsC0HGc<5L_t(oN9~tAa_TS;$N%^&K*4YVa{@?1 zmG*U_Oqz5l)1@&bK0+#**e8fjz))b{#cx+y%aXA2!6TV@Gx?1QX|>4O)vi{cB?{H1 z8FzjXg%;G(widyENZqDrRiXO@o1?qrQ$1nigfTU93?+&D?0VGMzj~8bFsBl1Pk);u zQ%Yn+Oh3BL8SEKnLB{oI+h(chCum+#DJ3tW~MlW#m*acZ#|Lt&oK`(rDT>0Zc3Hid4Ki>cy(WwOS`No zvP}Pq9)Q%sDopr0bZr^de|MeWWfH6Vy+dR;_?B|)Fi+y(XC#s4e1q2MU0~FPY%qjx zDeXSf0$)3O>2V+G((IdQXsMWfbRFNP?DumWBJinfctq>!cklb9;FnK8F9+?(L|1L6 z&i-;SUHuqQ$nwklX(D#vCH;#)|4>$->|f$9Q>c)1B;vX600000NkvXXu0mjf_%54Y diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 739652bfa..74c476331 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -53,14 +53,14 @@ Based on the source file structure, we we :ref:`create an external table` - Returns a static query plan, which can be used to debug query plans * - :ref:`GET_EXTENTS_FILE_FOR_CHUNK` - - Points to all files that contain data related to a specific chunk + - Points to all files that contain data related to a specific chunk |icon-new_2022.1| * - :ref:`GET_METADATA_CHUNK_KEY` - - Returns a list of metadata key values for the chunks that you specify + - Returns a list of metadata key values for the chunks that you specify |icon-New_Dark_Gray| * - :ref:`SELECT GET_LICENSE_INFO` - View a user's license information * - :ref:`SELECT GET_DDL` @@ -137,6 +137,14 @@ The following table shows the Utility commands: * - :ref:`STOP STATEMENT` - Stops or aborts an active statement +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png + :align: middle + :width: 110 + +.. |icon-New_Dark_Gray| image:: /_static/images/New_Dark_Gray.png + :align: middle + :width: 110 + Workload Management ====================== The following table shows the Workload Management commands: diff --git a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst index 2f872812a..5679e508e 100644 --- a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst +++ b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst @@ -3,7 +3,11 @@ ******************** GET_EXTENTS_FILE_FOR_CHUNK ******************** -The ``GET_EXTENTS_FILE_FOR_CHUNK`` command points to all files that contain data related to a specific chunk. This command is used for debugging purposes. +The ``GET_EXTENTS_FILE_FOR_CHUNK`` |icon-new_2022.1| command points to all files that contain data related to a specific chunk. This command is used for debugging purposes. + +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png + :align: middle + :width: 110 This reference page includes the following information: diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst index 2ccc59132..ee641e3b1 100644 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -3,7 +3,11 @@ ******************** GET_METADATA_CHUNK_KEY ******************** -The ``GET_METADATA_CHUNK_KEY`` command returns specific metadata key values for user-specified chunks. +The ``GET_METADATA_CHUNK_KEY`` |icon-new_2022.1| command returns specific metadata key values for user-specified chunks. + +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png + :align: middle + :width: 110 This reference page includes the following information: diff --git a/releases/2022.1.rst b/releases/2022.1.rst index a98a397f8..dbf061797 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -45,6 +45,16 @@ SQream now supports ingesting data from Avro files. For more information, see `Inserting Data from Avro `_. +New Utility Commands +************ +The following two new utility commands have been created: + +* `GET EXTENTS FILE FOR CHUNK `_ - points to all files that contain data related to a specific chunk. This command is used for debugging purposes. + + :: + +* `GET_METADATA_CHUNK_KEY `_ - returns specific metadata key values for user-specified chunks. + Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1: @@ -76,7 +86,7 @@ Deprecated Features ------- In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. ``VARCHAR`` will be maintained in all previous versions until migration to ``TEXT`` is complete, at which point it will be deprecated in all earlier versions. -If you are using an earlier version of SQream, see `Using Legacy String Literals `_. +If you are using an earlier version of SQream, see `Using Legacy String Literals `_. An automated process is being used to facilitate migration from ``VARCHAR`` to ``TEXT``. For more information, contact SQream. From 482a45f7b6fd7a5415888ebb7426ef05c160ef02 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Fri, 8 Jul 2022 17:46:17 +0300 Subject: [PATCH 0103/1892] Two New Utility Commands --- .../get_extents_file_list_for_chunk.rst | 71 +++++++++-- .../get_metadata_chunk_key.rst | 110 ++++++++++++++++-- 2 files changed, 159 insertions(+), 22 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst index 5679e508e..3c05a48fe 100644 --- a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst +++ b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst @@ -23,15 +23,7 @@ The following is the syntax for the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: select get_extents_file_list_for_chunk(database_name, " "table_id, chunk_id);" - -Output -========== -The following is an example of the output generated by the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: - -.. code-block:: postgres - - EXAMPLE NEEDED - + Parameters ============ The following table shows the ``GET_EXTENTS_FILE_FOR_CHUNK`` parameters: @@ -47,15 +39,70 @@ The following table shows the ``GET_EXTENTS_FILE_FOR_CHUNK`` parameters: * - ``table_id`` - The ID of the table where the chunk is located. * - ``chunk_id`` - - The ID of the chunk. + - The ID of the chunk. -Examples +Example =========== The following is an example of the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: .. code-block:: postgres - Example - pending from Eyal W. + master=> select get_extents_file_list_for_chunk('master', 0, 3); + +Output +========== +The following table describes the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: + +Database name. table name, table id, column id, chunk id, file path + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Parameter + - Description + - Type + - Example + + * - ``database_name`` + - The name of the database where the chunk is located. + - Text + - ``master`` + + * - ``table_name`` + - The ID of the table where the chunk is located. + - Numeric + - ``0`` + + * - ``table_id`` + - The ID of the column. + - Numeric + - ``0`` + + * - ``column_id`` + - The status of the chunk. + - **Comment** - *What is the type?* + - ``1`` + + * - ``chunk_id`` + - Describes the state of the chunk. + - **Comment** - *What is the type?* + - ``chunk_state::`` + + * - ``file_path`` + - Shows the path of the file. + - Text + - **Comment** - *Provide example + +The following is an example of the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: + +.. code-block:: postgres + + master,public.t_1,0,0,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/0/0-2 + master,public.t_1,0,1,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/1/1-2 + master,public.t_1,0,2,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/2/2-2 + master,public.t_1,0,3,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/3/3-2 + master,public.t_1,0,4,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/4/4-2 Permissions ============= diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst index ee641e3b1..c43775de7 100644 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -23,14 +23,6 @@ The following is the syntax for the ``GET_METADATA_CHUNK_KEY`` command: get_metadata_chunk_key(database_name, table_id, chunk_id); -Output -========== -The following is an example of the output generated by the ``GET_METADATA_CHUNK_KEY`` command: - -.. code-block:: postgres - - EXAMPLE NEEDED - Parameters ============ The following table shows the ``GET_METADATA_CHUNK_KEY`` parameters: @@ -48,13 +40,111 @@ The following table shows the ``GET_METADATA_CHUNK_KEY`` parameters: * - ``chunk_id`` - The ID of the chunk. -Examples +Example =========== The following is an example of the ``GET_METADATA_CHUNK_KEY`` command: .. code-block:: postgres - Example - pending from Eyal W. + master=> select get_metadata_chunk_key('master', 0, 1); + +Output +========== +The following table describes the output generated from the ``GET_METADATA_CHUNK_KEY`` command: + +.. list-table:: + :widths: 25 25 25 25 + :header-rows: 1 + + * - Parameter + - Description + - Type + - Example + + * - ``database_name`` + - The name of the database where the chunk is located. + - Text + - ``master`` + + * - ``table_id`` + - The ID of the table where the chunk is located. + - Numeric + - ``0`` + + * - ``column_id`` + - The ID of the column. + - Numeric + - ``0`` + + * - ``chunk_status`` + - The status of the chunk. + - **Comment** - *What is the type?* + - ``1`` + + * - ``chunk_aligned`` + - Describes the state of the chunk. + - **Comment** - *What is the type?* + - ``chunk_state::`` + + * - ``offset_in_file`` + - Shows the file's offset setting. + - Numeric + - ``-1`` + + * - ``compressed_size`` + - Shows the file's compressed size. + - Numeric + - ``0`` + + * - ``uncompressed_size`` + - Shows the file's uncompressed size. + - Numeric + - ``2`` + + * - ``compression_type`` + - Shows the file's compression type. + - Numeric + - ``2`` + + * - ``min_long`` + - **Comment** - What is it? + - **Comment** - What is it? + - ``flat`` + + * - ``max_long`` + - **Comment** - What is it? + - **Comment** - What is it? + - **Comment** - What is it? + + * - ``min_string_max_string`` + - **Comment** - What is it? + - **Comment** - What is it? + - **Comment** - What is it? + + * - ``min_numeric`` + - **Comment** - What is it? + - **Comment** - What is it? + - **Comment** - What is it? + + * - ``max_numeric`` + - **Comment** - What is it? + - **Comment** - What is it? + - **Comment** - What is it? + + * - ``column_aligned`` + - **Comment** - What is it? + - **Comment** - What is it? + - **Comment** - What is it? + +The following is an example of the output generated from the ``GET_METADATA_CHUNK_KEY`` command: + +.. code-block:: postgres + + master,0,0,1,chunk_state::clean,1,0,2,2,flat,0,0,,,0x7f722ffb7c60,0x7f722ffb7c70,1 + master,0,1,1,chunk_state::clean,1,0,8,8,flat,1,2,,,0x7f722ffb7c60,0x7f722ffb7c70,1 + master,0,2,1,chunk_state::clean,1,0,2,2,flat,0,0,,,0x7f722ffb7c60,0x7f722ffb7c70,1 + master,0,3,1,chunk_state::clean,1,0,8,8,flat,3,3,,,0x7f722ffb7c60,0x7f722ffb7c70,1 + master,0,4,1,chunk_state::clean,1,0,16,16,flat,0,0,abc,dfg,0x7f722ffb7c60,0x7f722ffb7c70,1 Permissions ============= From b37d0c0ce6d30e461ae2b63cdba66c969063d9e4 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 13:10:10 +0300 Subject: [PATCH 0104/1892] Updated Replaced External Tables with Foreign Tables Finalized VARCHAR deprecation text --- operational_guides/foreign_tables.rst | 35 ++++++++++++++------------- releases/2022.1.rst | 27 +++------------------ 2 files changed, 21 insertions(+), 41 deletions(-) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 74c476331..bc8c401a6 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -4,18 +4,18 @@ Foreign Tables *********************** Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. -SQream DB supports read only external tables, so you can query from external tables, but you cannot insert to them, or run deletes or updates on them. +SQream DB supports read only foreign tables, so you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. -Although external tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on an external table can be used to insert data into SQream using the full power of the query engine to perform ETL. +Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. .. contents:: In this topic: :local: Supported Data Formats ===================================== -SQream DB supports external tables over: +SQream DB supports foreign tables over: * Text files (e.g. CSV, PSV, TSV) * ORC @@ -29,9 +29,9 @@ SQream can stage data from: * :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) -Using External Tables +Using Foreign Tables ============================================== -Use an external table to stage data before loading from CSV, Parquet or ORC files. +Use a foreign table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging -------------------------------- @@ -45,13 +45,13 @@ For the following examples, we will want to interact with a CSV file. Here's a p The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. -Creating an External Table +Creating a Foreign Table ----------------------------- -Based on the source file structure, we we :ref:`create an external table` with the appropriate structure, and point it to the file. +Based on the source file structure, we we :ref:`create a foreign table` with the appropriate structure, and point it to the file. .. code-block:: postgres - CREATE EXTERNAL TABLE nba + CREATE foreign table nba ( Name varchar, Team varchar, @@ -68,12 +68,13 @@ Based on the source file structure, we we :ref:`create an external table SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for an external table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against an external table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file +* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index dbf061797..ac180206c 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -16,6 +16,7 @@ The 2022.1 Release Notes describes the following: * Enhanced security features. * New data manipulation command. * Additional data ingestion format. +* New utility commands. New Features ---------- @@ -84,31 +85,9 @@ No relevant naming changes were made. Deprecated Features ------- -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. ``VARCHAR`` will be maintained in all previous versions until migration to ``TEXT`` is complete, at which point it will be deprecated in all earlier versions. +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. -If you are using an earlier version of SQream, see `Using Legacy String Literals `_. - -An automated process is being used to facilitate migration from ``VARCHAR`` to ``TEXT``. For more information, contact SQream. - -**Comment** - *Below is the original text of the VARCHAR deprecation email. I don't think that we need to necessarily expose our logic to our customers, but focus on certain aspects of it (see the first paragraph above). However, I can use more/all of this content if deemed necessary.* - -* SQream has decided to deprecated support in varchar data type, the decision made out of SQream effort to enhance its core functionalities and with respect to ever changing eco system requirements. - - :: - -* For new customers Varchar data type is not supported - - :: - -* The supported data type that will replace this data type is text as all different functionalities encapsulated within this data type - - :: - -* SQream will maintain varchar data type support until the last customer will be fully migrated - - :: - -* In order to enhance the conversion mechanism to be as fast as possible SQream will provide an automated and secured tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. Known Issues and Limitations -------- From 1e77017a98e3734dcf60ab1a4d6eeac6494d5006 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 17:33:10 +0300 Subject: [PATCH 0105/1892] Added Loading and Unloading Data section to menu Modified menu. Added links to Performing Basic SQream Operations page. --- .../performing_basic_sqream_operations.rst | 9 +++-- index.rst | 15 ++++---- loading_and_unloading_data/index.rst | 36 +++++++++++++++++++ 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 loading_and_unloading_data/index.rst diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst index 1b0f60ba3..0808c22dd 100644 --- a/getting_started/performing_basic_sqream_operations.rst +++ b/getting_started/performing_basic_sqream_operations.rst @@ -11,10 +11,13 @@ After installing SQream you can perform the operations described on this page: running_the_sqream_sql_client creating_your_first_table - creating_a_database - querying_data listing_tables inserting_rows running_queries deleting_rows - saving_query_results_to_a_csv_or_psv_file \ No newline at end of file + saving_query_results_to_a_csv_or_psv_file + +For more information on other basic SQream operations, see the following: + +* `Creating a Database `_ +* :ref:`data_ingestion` \ No newline at end of file diff --git a/index.rst b/index.rst index 29ea038b0..72731e378 100644 --- a/index.rst +++ b/index.rst @@ -10,7 +10,7 @@ The **v2022.1** branch is a private branch designed for internal use only until .. tip:: Want to read this offline? - `Download the documentation as a single PDF `_ . + `Download the documentation as a single PDF `_ . .. only:: pdf or latex @@ -35,7 +35,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + `Getting Started `_ :ref:`sql_feature_support` @@ -47,7 +47,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + `Setting up SQream `_ :ref:`Best practices` @@ -59,7 +59,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`2021.2<2021.2>` + :ref:`2021.2<2021.2>` :ref:`2021.1<2021.1>` @@ -103,7 +103,8 @@ If you're looking for an older version of the documentation, versions 1.10 throu getting_started/index installation_guides/index data_ingestion/index - third_party_tools/index + connecting_to_sqream/index + loading_and_unloading/index feature_guides/index operational_guides/index sqream_studio_5.4.3/index @@ -116,9 +117,9 @@ If you're looking for an older version of the documentation, versions 1.10 throu glossary .. - Indices and tables + Indices and Tables ================== * :ref:`genindex` * :ref:`modindex` - * :ref:`search` + * :ref:`search` \ No newline at end of file diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst new file mode 100644 index 000000000..ae5c506bb --- /dev/null +++ b/loading_and_unloading_data/index.rst @@ -0,0 +1,36 @@ +.. _loading_and_unloading_data: + +*********************** +Loading and Unloading Data +*********************** +The **Loading Data** section describes concepts and operations related to importing data into your SQream database: + +* `Overview of loading data `_ - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. + +* `Alternatives to loading data (foreign tables) `_ - Useful for running queries directly on external data without importing into your SQream database. + +* `Supported data types `_ - Overview of supported data types, including descriptions, examples, and relevant aliases. + +* `Ingesting data from external sources `_ - List of data ingestion sources that SQream supports. + +* `Inserting data from external tables `_ - Inserts one or more rows into a table. + +* `Ingesting data from third party client platforms `_ - Gives you direct access to a variety of drivers, connectors, tools, vizualisers, and utilities.. + +* `Using the COPY FROM statement `_ - Used for loading data from files located on a filesystem into SQream tables. + +* `Importing data using Studio `_ - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. + +* `Loading data using Amazon S3 `_ - Used for loading data from Amazon S3. + +* Troubleshooting - Describes troubleshooting solutions related to importing data from the following: + + * `SAS Viya `_ + + * `Tableau `_ + +The **Unloading Data** section describes concepts and operations related to exporting data from your SQream database: + +* `Overview of unloading data `_ - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. + +* `The COPY TO statement `_ - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file From 5889fbaa833656f3bd364d7c011c2574831f7144 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 17:45:18 +0300 Subject: [PATCH 0106/1892] Corrected the menu --- .../client_drivers/index.rst | 166 +++--- .../client_drivers/jdbc/index.rst | 342 ++++++------ .../client_drivers/jdbc/sample.java | 132 ++--- .../client_drivers/odbc/index.rst | 114 ++-- .../odbc/install_configure_odbc_linux.rst | 506 +++++++++--------- .../odbc/install_configure_odbc_windows.rst | 268 +++++----- .../connectivity_ecosystem.jpg | Bin .../index.rst | 32 +- index.rst | 2 +- 9 files changed, 781 insertions(+), 781 deletions(-) rename {third_party_tools => connecting_to_sqream}/client_drivers/index.rst (97%) rename {third_party_tools => connecting_to_sqream}/client_drivers/jdbc/index.rst (97%) rename {third_party_tools => connecting_to_sqream}/client_drivers/jdbc/sample.java (97%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/index.rst (96%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/install_configure_odbc_linux.rst (96%) rename {third_party_tools => connecting_to_sqream}/client_drivers/odbc/install_configure_odbc_windows.rst (97%) rename {third_party_tools => connecting_to_sqream}/connectivity_ecosystem.jpg (100%) rename {third_party_tools => connecting_to_sqream}/index.rst (95%) diff --git a/third_party_tools/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst similarity index 97% rename from third_party_tools/client_drivers/index.rst rename to connecting_to_sqream/client_drivers/index.rst index d0c60d804..79d1fd176 100644 --- a/third_party_tools/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -1,84 +1,84 @@ -.. _client_drivers: - -************************************ -Client Drivers for 2022.1 -************************************ - -The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. - -Client Driver Downloads -============================= - -All Operating Systems ---------------------------- -The following are applicable to all operating systems: - -.. _jdbc: - -* **JDBC** - recommended installation via ``mvn``: - - * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) - * `JDBC driver `_ - -.. _tableau_connector: - -* **Tableau**: - - * `Tableau connector `_ - SQream (.taco) - * `Tableau manual installation `_ - - -.. _powerbi_connector: - -* **Power BI**: - - * `Power BI PowerQuery connector `_ - SQream (.mez) - * `Power BI manual installation `_ - - -Windows --------------- -The following are applicable to Windows: - -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `SSream represenative `_ for this installer. - - For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. - -* **Net driver** - `SQream .Net driver v3.0.2 `_ - - - -Linux --------------- -The following are applicable to Linux: - -* `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines - - :: - -* `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines - - :: - -* ODBC Installer - Please contact your SQream representative for this installer. - - -.. toctree:: - :maxdepth: 4 - :caption: Client Driver Documentation: - :titlesonly: - - jdbc/index - odbc/index - - - -.. rubric:: Need help? - -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal `_ for additional support. - -.. rubric:: Looking for older drivers? - +.. _client_drivers: + +************************************ +Client Drivers for 2022.1 +************************************ + +The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. + +Client Driver Downloads +============================= + +All Operating Systems +--------------------------- +The following are applicable to all operating systems: + +.. _jdbc: + +* **JDBC** - recommended installation via ``mvn``: + + * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC driver `_ + +.. _tableau_connector: + +* **Tableau**: + + * `Tableau connector `_ - SQream (.taco) + * `Tableau manual installation `_ + + +.. _powerbi_connector: + +* **Power BI**: + + * `Power BI PowerQuery connector `_ - SQream (.mez) + * `Power BI manual installation `_ + + +Windows +-------------- +The following are applicable to Windows: + +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `SSream represenative `_ for this installer. + + For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. + +* **Net driver** - `SQream .Net driver v3.0.2 `_ + + + +Linux +-------------- +The following are applicable to Linux: + +* `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines + + :: + +* `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines + + :: + +* ODBC Installer - Please contact your SQream representative for this installer. + + +.. toctree:: + :maxdepth: 4 + :caption: Client Driver Documentation: + :titlesonly: + + jdbc/index + odbc/index + + + +.. rubric:: Need help? + +If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal `_ for additional support. + +.. rubric:: Looking for older drivers? + If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. \ No newline at end of file diff --git a/third_party_tools/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst similarity index 97% rename from third_party_tools/client_drivers/jdbc/index.rst rename to connecting_to_sqream/client_drivers/jdbc/index.rst index 4c35c3eff..832987efa 100644 --- a/third_party_tools/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -1,171 +1,171 @@ -.. _java_jdbc: - -************************* -JDBC -************************* -The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. - -The JDBC page includes the following sections: - -.. contents:: - :local: - :depth: 1 - -Installing the JDBC Driver -================================== -The **Installing the JDBC Driver** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Prerequisites ----------------- -The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: - -* **Oracle Java** - Download and install `Java 8 `_ from Oracle for your platform. - - :: - -* **OpenJDK** - Install `OpenJDK `_ - - :: - -* **Windows** - SQream recommends installing `Zulu 8 `_ - -Getting the JAR file ---------------------- -SQream provides the JDBC driver as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can be integrated into your Java-based applications or projects. - -Extracting the ZIP Archive -------------------------- -Run the following command to extract the JAR file from the ZIP archive: - -.. code-block:: console - - $ unzip sqream-jdbc-4.3.0.zip - -Setting Up the Class Path ----------------------------- -To use the driver, you must include the JAR named ``sqream-jdbc-.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. - -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: - -.. code-block:: console - - $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH - $ java my_java_app - -Alternatively, you can pass ``-classpath`` to the Java executable file: - -.. code-block:: console - - $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app - -Connecting to SQream Using a JDBC Application -============================================== -You can connect to SQream using one of the following JDBC applications: - -.. contents:: - :local: - :depth: 1 - -Driver Class --------------- -Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. - -Connection String --------------------- -JDBC drivers rely on a connection string. - -The following is the syntax for SQream: - -.. code-block:: text - - jdbc:Sqream:///;user=;password=sqream;[; ...] - -Connection Parameters -^^^^^^^^^^^^^^^^^^^^^^^^ -The following table shows the connection string parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Item - - State - - Default - - Description - * - ```` - - Mandatory - - None - - Hostname and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` - * - ```` - - Mandatory - - None - - Database name to connect to. For example, ``master`` - * - ``username=`` - - Mandatory - - None - - Username of a role to use for connection. For example, ``username=rhendricks`` - * - ``password=`` - - Mandatory - - None - - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` - * - ``service=`` - - Optional - - ``sqream`` - - Specifices service queue to use. For example, ``service=etl`` - * - ```` - - Optional - - ``false`` - - Specifies SSL for this connection. For example, ``ssl=true`` - * - ```` - - Optional - - ``true`` - - Connect via load balancer (use only if exists, and check port). - * - ```` - - Optional - - ``true`` - - Enables on-demand loading, and defines double buffer size for result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the fetchSize is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. - * - ```` - - Optional - - ``true`` - - Defines the bytes size for inserting a buffer before flushing data to the server. Clients running a parameterized insert (network insert) can define the amount of data to collect before flushing the buffer. - * - ```` - - Optional - - ``true`` - - Defines the logger level as either ``debug`` or ``trace``. - * - ```` - - Optional - - ``true`` - - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. - -Connection String Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following is an example of a SQream cluster with load balancer and no service queues (with SSL): - -.. code-block:: text - - jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true - -The following is a minimal example for a local standalone SQream database: - -.. code-block:: text - - jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 - -The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` - -.. code-block:: text - - jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl - -Sample Java Program --------------------- -You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. - -.. literalinclude:: sample.java - :language: java - :caption: JDBC Application Sample - :linenos: +.. _java_jdbc: + +************************* +JDBC +************************* +The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. + +The JDBC page includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Installing the JDBC Driver +================================== +The **Installing the JDBC Driver** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Prerequisites +---------------- +The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: + +* **Oracle Java** - Download and install `Java 8 `_ from Oracle for your platform. + + :: + +* **OpenJDK** - Install `OpenJDK `_ + + :: + +* **Windows** - SQream recommends installing `Zulu 8 `_ + +Getting the JAR file +--------------------- +SQream provides the JDBC driver as a zipped JAR file, available for download from the :ref:`client drivers download page`. This JAR file can be integrated into your Java-based applications or projects. + +Extracting the ZIP Archive +------------------------- +Run the following command to extract the JAR file from the ZIP archive: + +.. code-block:: console + + $ unzip sqream-jdbc-4.3.0.zip + +Setting Up the Class Path +---------------------------- +To use the driver, you must include the JAR named ``sqream-jdbc-.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. + +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: + +.. code-block:: console + + $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH + $ java my_java_app + +Alternatively, you can pass ``-classpath`` to the Java executable file: + +.. code-block:: console + + $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app + +Connecting to SQream Using a JDBC Application +============================================== +You can connect to SQream using one of the following JDBC applications: + +.. contents:: + :local: + :depth: 1 + +Driver Class +-------------- +Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. + +Connection String +-------------------- +JDBC drivers rely on a connection string. + +The following is the syntax for SQream: + +.. code-block:: text + + jdbc:Sqream:///;user=;password=sqream;[; ...] + +Connection Parameters +^^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the connection string parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - State + - Default + - Description + * - ```` + - Mandatory + - None + - Hostname and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` + * - ```` + - Mandatory + - None + - Database name to connect to. For example, ``master`` + * - ``username=`` + - Mandatory + - None + - Username of a role to use for connection. For example, ``username=rhendricks`` + * - ``password=`` + - Mandatory + - None + - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` + * - ``service=`` + - Optional + - ``sqream`` + - Specifices service queue to use. For example, ``service=etl`` + * - ```` + - Optional + - ``false`` + - Specifies SSL for this connection. For example, ``ssl=true`` + * - ```` + - Optional + - ``true`` + - Connect via load balancer (use only if exists, and check port). + * - ```` + - Optional + - ``true`` + - Enables on-demand loading, and defines double buffer size for result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the fetchSize is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. + * - ```` + - Optional + - ``true`` + - Defines the bytes size for inserting a buffer before flushing data to the server. Clients running a parameterized insert (network insert) can define the amount of data to collect before flushing the buffer. + * - ```` + - Optional + - ``true`` + - Defines the logger level as either ``debug`` or ``trace``. + * - ```` + - Optional + - ``true`` + - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. + +Connection String Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following is an example of a SQream cluster with load balancer and no service queues (with SSL): + +.. code-block:: text + + jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true + +The following is a minimal example for a local standalone SQream database: + +.. code-block:: text + + jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 + +The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` + +.. code-block:: text + + jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl + +Sample Java Program +-------------------- +You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. + +.. literalinclude:: sample.java + :language: java + :caption: JDBC Application Sample + :linenos: diff --git a/third_party_tools/client_drivers/jdbc/sample.java b/connecting_to_sqream/client_drivers/jdbc/sample.java similarity index 97% rename from third_party_tools/client_drivers/jdbc/sample.java rename to connecting_to_sqream/client_drivers/jdbc/sample.java index 1b7af5804..3ff670747 100644 --- a/third_party_tools/client_drivers/jdbc/sample.java +++ b/connecting_to_sqream/client_drivers/jdbc/sample.java @@ -1,67 +1,67 @@ -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.Statement; -import java.sql.ResultSet; - -import java.io.IOException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.sql.SQLException; - - - -public class SampleTest { - - // Replace with your connection string - static final String url = "jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true"; - - // Allocate objects for result set and metadata - Connection conn = null; - Statement stmt = null; - ResultSet rs = null; - DatabaseMetaData dbmeta = null; - - int res = 0; - - public void testJDBC() throws SQLException, IOException { - - // Create a connection - conn = DriverManager.getConnection(url,"rhendricks","Tr0ub4dor&3"); - - // Create a table with a single integer column - String sql = "CREATE TABLE test (x INT)"; - stmt = conn.createStatement(); // Prepare the statement - stmt.execute(sql); // Execute the statement - stmt.close(); // Close the statement handle - - // Insert some values into the newly created table - sql = "INSERT INTO test VALUES (5),(6)"; - stmt = conn.createStatement(); - stmt.execute(sql); - stmt.close(); - - // Get values from the table - sql = "SELECT * FROM test"; - stmt = conn.createStatement(); - rs = stmt.executeQuery(sql); - // Fetch all results one-by-one - while(rs.next()) { - res = rs.getInt(1); - System.out.println(res); // Print results to screen - } - rs.close(); // Close the result set - stmt.close(); // Close the statement handle - } - - - public static void main(String[] args) throws SQLException, KeyManagementException, NoSuchAlgorithmException, IOException, ClassNotFoundException{ - - // Load SQream DB JDBC driver - Class.forName("com.sqream.jdbc.SQDriver"); - - // Create test object and run - SampleTest test = new SampleTest(); - test.testJDBC(); - } +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.DriverManager; +import java.sql.Statement; +import java.sql.ResultSet; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.sql.SQLException; + + + +public class SampleTest { + + // Replace with your connection string + static final String url = "jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true"; + + // Allocate objects for result set and metadata + Connection conn = null; + Statement stmt = null; + ResultSet rs = null; + DatabaseMetaData dbmeta = null; + + int res = 0; + + public void testJDBC() throws SQLException, IOException { + + // Create a connection + conn = DriverManager.getConnection(url,"rhendricks","Tr0ub4dor&3"); + + // Create a table with a single integer column + String sql = "CREATE TABLE test (x INT)"; + stmt = conn.createStatement(); // Prepare the statement + stmt.execute(sql); // Execute the statement + stmt.close(); // Close the statement handle + + // Insert some values into the newly created table + sql = "INSERT INTO test VALUES (5),(6)"; + stmt = conn.createStatement(); + stmt.execute(sql); + stmt.close(); + + // Get values from the table + sql = "SELECT * FROM test"; + stmt = conn.createStatement(); + rs = stmt.executeQuery(sql); + // Fetch all results one-by-one + while(rs.next()) { + res = rs.getInt(1); + System.out.println(res); // Print results to screen + } + rs.close(); // Close the result set + stmt.close(); // Close the statement handle + } + + + public static void main(String[] args) throws SQLException, KeyManagementException, NoSuchAlgorithmException, IOException, ClassNotFoundException{ + + // Load SQream DB JDBC driver + Class.forName("com.sqream.jdbc.SQDriver"); + + // Create test object and run + SampleTest test = new SampleTest(); + test.testJDBC(); + } } \ No newline at end of file diff --git a/third_party_tools/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst similarity index 96% rename from third_party_tools/client_drivers/odbc/index.rst rename to connecting_to_sqream/client_drivers/odbc/index.rst index 7623b4e99..3ee093692 100644 --- a/third_party_tools/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -1,58 +1,58 @@ -.. _odbc: - -************************* -ODBC -************************* - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :hidden: - - install_configure_odbc_windows - install_configure_odbc_linux - -SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Platform - - Versions supported - - * - Windows - - * Windows 7 (64 bit) - * Windows 8 (64 bit) - * Windows 10 (64 bit) - * Windows Server 2008 R2 (64 bit) - * Windows Server 2012 - * Windows Server 2016 - * Windows Server 2019 - - * - Linux - - * Red Hat Enterprise Linux (RHEL) 7 - * CentOS 7 - * Ubuntu 16.04 - * Ubuntu 18.04 - -Other distributions may also work, but are not officially supported by SQream. - -.. contents:: In this topic: - :local: - -Downloading the ODBC driver -================================== - -The SQream DB ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support `_ or contact your SQream account manager to get the driver. - -The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. -After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: - -Install and configure the ODBC driver -======================================= - -Continue based on your platform: - -* :ref:`install_odbc_windows` +.. _odbc: + +************************* +ODBC +************************* + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :hidden: + + install_configure_odbc_windows + install_configure_odbc_linux + +SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Platform + - Versions supported + + * - Windows + - * Windows 7 (64 bit) + * Windows 8 (64 bit) + * Windows 10 (64 bit) + * Windows Server 2008 R2 (64 bit) + * Windows Server 2012 + * Windows Server 2016 + * Windows Server 2019 + + * - Linux + - * Red Hat Enterprise Linux (RHEL) 7 + * CentOS 7 + * Ubuntu 16.04 + * Ubuntu 18.04 + +Other distributions may also work, but are not officially supported by SQream. + +.. contents:: In this topic: + :local: + +Downloading the ODBC driver +================================== + +The SQream DB ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support `_ or contact your SQream account manager to get the driver. + +The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. +After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: + +Install and configure the ODBC driver +======================================= + +Continue based on your platform: + +* :ref:`install_odbc_windows` * :ref:`install_odbc_linux` \ No newline at end of file diff --git a/third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst similarity index 96% rename from third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst rename to connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index 737768756..61919f161 100644 --- a/third_party_tools/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -1,253 +1,253 @@ -.. _install_odbc_linux: - -**************************************** -Install and configure ODBC on Linux -**************************************** - -.. toctree:: - :maxdepth: 1 - :titlesonly: - :hidden: - - -The ODBC driver for Windows is provided as a shared library. - -This tutorial shows how to install and configure ODBC on Linux. - -.. contents:: In this topic: - :local: - :depth: 2 - -Prerequisites -============== - -.. _unixODBC: - -unixODBC ------------- - -The ODBC driver requires a driver manager to manage the DSNs. SQream DB's driver is built for unixODBC. - -Verify unixODBC is installed by running: - -.. code-block:: console - - $ odbcinst -j - unixODBC 2.3.4 - DRIVERS............: /etc/odbcinst.ini - SYSTEM DATA SOURCES: /etc/odbc.ini - FILE DATA SOURCES..: /etc/ODBCDataSources - USER DATA SOURCES..: /home/rhendricks/.odbc.ini - SQLULEN Size.......: 8 - SQLLEN Size........: 8 - SQLSETPOSIROW Size.: 8 - -Take note of the location of ``.odbc.ini`` and ``.odbcinst.ini``. In this case, ``/etc``. If ``odbcinst`` is not installed, follow the instructions for your platform below: - -.. contents:: Install unixODBC on: - :local: - :depth: 1 - -Install unixODBC on RHEL 7 / CentOS 7 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: console - - $ yum install -y unixODBC unixODBC-devel - -Install unixODBC on Ubuntu -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: console - - $ sudo apt-get install unixodbc unixodbc-dev - - -Install the ODBC driver with a script -======================================= - -Use this method if you have never used ODBC on your machine before. If you have existing DSNs, see the manual install process below. - -#. Unpack the tarball - Copy the downloaded file to any directory, and untar it to a new directory: - - .. code-block:: console - - $ mkdir -p sqream_odbc64 - $ tar xf sqream_2019.2.1_odbc_3.0.0_x86_64_linux.tar.gz -C sqream_odbc64 - -#. Run the first-time installer. The installer will create an editable DSN. - - .. code-block:: console - - $ cd sqream_odbc64 - ./odbc_install.sh --install - - -#. Edit the DSN created by editing ``/etc/.odbc.ini``. See the parameter explanation in the section :ref:`ODBC DSN Parameters `. - - -Install the ODBC driver manually -======================================= - -Use this method when you have existing ODBC DSNs on your machine. - -#. Unpack the tarball - Copy the file you downloaded to the directory where you want to install it, and untar it: - - .. code-block:: console - - $ tar xf sqream_2019.2.1_odbc_3.0.0_x86_64_linux.tar.gz -C sqream_odbc64 - - Take note of the directory where the driver was unpacked. For example, ``/home/rhendricks/sqream_odbc64`` - -#. Locate the ``.odbc.ini`` and ``.odbcinst.ini`` files, using ``odbcinst -j``. - - #. In ``.odbcinst.ini``, add the following lines to register the driver (change the highlighted paths to match your specific driver): - - .. code-block:: ini - :emphasize-lines: 6,7 - - [ODBC Drivers] - SqreamODBCDriver=Installed - - [SqreamODBCDriver] - Description=Driver DSII SqreamODBC 64bit - Driver=/home/rhendricks/sqream_odbc64/sqream_odbc64.so - Setup=/home/rhendricks/sqream_odbc64/sqream_odbc64.so - APILevel=1 - ConnectFunctions=YYY - DriverODBCVer=03.80 - SQLLevel=1 - IconvEncoding=UCS-4LE - - #. In ``.odbc.ini``, add the following lines to configure the DSN (change the highlighted parameters to match your installation): - - .. code-block:: ini - :emphasize-lines: 6,7,8,9,10,11,12,13,14 - - [ODBC Data Sources] - MyTest=SqreamODBCDriver - - [MyTest] - Description=64-bit Sqream ODBC - Driver=/home/rhendricks/sqream_odbc64/sqream_odbc64.so - Server="127.0.0.1" - Port="5000" - Database="raviga" - Service="" - User="rhendricks" - Password="Tr0ub4dor&3" - Cluster=false - Ssl=false - - Parameters are in the form of ``parameter = value``. For details about the parameters that can be set for each DSN, see the section :ref:`ODBC DSN Parameters `. - - - #. Create a file called ``.sqream_odbc.ini`` for managing the driver settings and logging. - This file should be created alongside the other files, and add the following lines (change the highlighted parameters to match your installation): - - .. code-block:: ini - :emphasize-lines: 5,7 - - # Note that this default DriverManagerEncoding of UTF-32 is for iODBC. unixODBC uses UTF-16 by default. - # If unixODBC was compiled with -DSQL_WCHART_CONVERT, then UTF-32 is the correct value. - # Execute 'odbc_config --cflags' to determine if you need UTF-32 or UTF-16 on unixODBC - [Driver] - DriverManagerEncoding=UTF-16 - DriverLocale=en-US - ErrorMessagesPath=/home/rhendricks/sqream_odbc64/ErrorMessages - LogLevel=0 - LogNamespace= - LogPath=/tmp/ - ODBCInstLib=libodbcinst.so - - -Install the driver dependencies -================================== - -Add the ODBC driver path to ``LD_LIBRARY_PATH``: - -.. code-block:: console - - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/rhendricks/sqream_odbc64/lib - -You can also add this previous command line to your ``~/.bashrc`` file in order to keep this installation working between reboots without re-entering the command manually - -Testing the connection -======================== - -Test the driver using ``isql``. - -If the DSN created is called ``MyTest`` as the example, run isql in this format: - -.. code-block:: console - - $ isql MyTest - - -.. _dsn_params: - -ODBC DSN Parameters -======================= - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Item - - Default - - Description - * - Data Source Name - - None - - An easily recognizable name that you'll use to reference this DSN. - * - Description - - None - - A description of this DSN for your convenience. This field can be left blank - * - User - - None - - Username of a role to use for connection. For example, ``User="rhendricks"`` - * - Password - - None - - Specifies the password of the selected role. For example, ``User="Tr0ub4dor&3"`` - * - Database - - None - - Specifies the database name to connect to. For example, ``Database="master"`` - * - Service - - ``sqream`` - - Specifices :ref:`service queue` to use. For example, ``Service="etl"``. Leave blank (``Service=""``) for default service ``sqream``. - * - Server - - None - - Hostname of the SQream DB worker. For example, ``Server="127.0.0.1"`` or ``Server="sqream.mynetwork.co"`` - * - Port - - None - - TCP port of the SQream DB worker. For example, ``Port="5000"`` or ``Port="3108"`` for the load balancer - * - Cluster - - ``false`` - - Connect via load balancer (use only if exists, and check port). For example, ``Cluster=true`` - * - Ssl - - ``false`` - - Specifies SSL for this connection. For example, ``Ssl=true`` - * - DriverManagerEncoding - - ``UTF-16`` - - Depending on how unixODBC is installed, you may need to change this to ``UTF-32``. - * - ErrorMessagesPath - - None - - Location where the driver was installed. For example, ``ErrorMessagePath=/home/rhendricks/sqream_odbc64/ErrorMessages``. - * - LogLevel - - 0 - - Set to 0-6 for logging. Use this setting when instructed to by SQream Support. For example, ``LogLevel=1`` - - .. hlist:: - :columns: 3 - - * 0 = Disable tracing - * 1 = Fatal only error tracing - * 2 = Error tracing - * 3 = Warning tracing - * 4 = Info tracing - * 5 = Debug tracing - * 6 = Detailed tracing - - - +.. _install_odbc_linux: + +**************************************** +Install and configure ODBC on Linux +**************************************** + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :hidden: + + +The ODBC driver for Windows is provided as a shared library. + +This tutorial shows how to install and configure ODBC on Linux. + +.. contents:: In this topic: + :local: + :depth: 2 + +Prerequisites +============== + +.. _unixODBC: + +unixODBC +------------ + +The ODBC driver requires a driver manager to manage the DSNs. SQream DB's driver is built for unixODBC. + +Verify unixODBC is installed by running: + +.. code-block:: console + + $ odbcinst -j + unixODBC 2.3.4 + DRIVERS............: /etc/odbcinst.ini + SYSTEM DATA SOURCES: /etc/odbc.ini + FILE DATA SOURCES..: /etc/ODBCDataSources + USER DATA SOURCES..: /home/rhendricks/.odbc.ini + SQLULEN Size.......: 8 + SQLLEN Size........: 8 + SQLSETPOSIROW Size.: 8 + +Take note of the location of ``.odbc.ini`` and ``.odbcinst.ini``. In this case, ``/etc``. If ``odbcinst`` is not installed, follow the instructions for your platform below: + +.. contents:: Install unixODBC on: + :local: + :depth: 1 + +Install unixODBC on RHEL 7 / CentOS 7 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + $ yum install -y unixODBC unixODBC-devel + +Install unixODBC on Ubuntu +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + $ sudo apt-get install unixodbc unixodbc-dev + + +Install the ODBC driver with a script +======================================= + +Use this method if you have never used ODBC on your machine before. If you have existing DSNs, see the manual install process below. + +#. Unpack the tarball + Copy the downloaded file to any directory, and untar it to a new directory: + + .. code-block:: console + + $ mkdir -p sqream_odbc64 + $ tar xf sqream_2019.2.1_odbc_3.0.0_x86_64_linux.tar.gz -C sqream_odbc64 + +#. Run the first-time installer. The installer will create an editable DSN. + + .. code-block:: console + + $ cd sqream_odbc64 + ./odbc_install.sh --install + + +#. Edit the DSN created by editing ``/etc/.odbc.ini``. See the parameter explanation in the section :ref:`ODBC DSN Parameters `. + + +Install the ODBC driver manually +======================================= + +Use this method when you have existing ODBC DSNs on your machine. + +#. Unpack the tarball + Copy the file you downloaded to the directory where you want to install it, and untar it: + + .. code-block:: console + + $ tar xf sqream_2019.2.1_odbc_3.0.0_x86_64_linux.tar.gz -C sqream_odbc64 + + Take note of the directory where the driver was unpacked. For example, ``/home/rhendricks/sqream_odbc64`` + +#. Locate the ``.odbc.ini`` and ``.odbcinst.ini`` files, using ``odbcinst -j``. + + #. In ``.odbcinst.ini``, add the following lines to register the driver (change the highlighted paths to match your specific driver): + + .. code-block:: ini + :emphasize-lines: 6,7 + + [ODBC Drivers] + SqreamODBCDriver=Installed + + [SqreamODBCDriver] + Description=Driver DSII SqreamODBC 64bit + Driver=/home/rhendricks/sqream_odbc64/sqream_odbc64.so + Setup=/home/rhendricks/sqream_odbc64/sqream_odbc64.so + APILevel=1 + ConnectFunctions=YYY + DriverODBCVer=03.80 + SQLLevel=1 + IconvEncoding=UCS-4LE + + #. In ``.odbc.ini``, add the following lines to configure the DSN (change the highlighted parameters to match your installation): + + .. code-block:: ini + :emphasize-lines: 6,7,8,9,10,11,12,13,14 + + [ODBC Data Sources] + MyTest=SqreamODBCDriver + + [MyTest] + Description=64-bit Sqream ODBC + Driver=/home/rhendricks/sqream_odbc64/sqream_odbc64.so + Server="127.0.0.1" + Port="5000" + Database="raviga" + Service="" + User="rhendricks" + Password="Tr0ub4dor&3" + Cluster=false + Ssl=false + + Parameters are in the form of ``parameter = value``. For details about the parameters that can be set for each DSN, see the section :ref:`ODBC DSN Parameters `. + + + #. Create a file called ``.sqream_odbc.ini`` for managing the driver settings and logging. + This file should be created alongside the other files, and add the following lines (change the highlighted parameters to match your installation): + + .. code-block:: ini + :emphasize-lines: 5,7 + + # Note that this default DriverManagerEncoding of UTF-32 is for iODBC. unixODBC uses UTF-16 by default. + # If unixODBC was compiled with -DSQL_WCHART_CONVERT, then UTF-32 is the correct value. + # Execute 'odbc_config --cflags' to determine if you need UTF-32 or UTF-16 on unixODBC + [Driver] + DriverManagerEncoding=UTF-16 + DriverLocale=en-US + ErrorMessagesPath=/home/rhendricks/sqream_odbc64/ErrorMessages + LogLevel=0 + LogNamespace= + LogPath=/tmp/ + ODBCInstLib=libodbcinst.so + + +Install the driver dependencies +================================== + +Add the ODBC driver path to ``LD_LIBRARY_PATH``: + +.. code-block:: console + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/rhendricks/sqream_odbc64/lib + +You can also add this previous command line to your ``~/.bashrc`` file in order to keep this installation working between reboots without re-entering the command manually + +Testing the connection +======================== + +Test the driver using ``isql``. + +If the DSN created is called ``MyTest`` as the example, run isql in this format: + +.. code-block:: console + + $ isql MyTest + + +.. _dsn_params: + +ODBC DSN Parameters +======================= + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - Default + - Description + * - Data Source Name + - None + - An easily recognizable name that you'll use to reference this DSN. + * - Description + - None + - A description of this DSN for your convenience. This field can be left blank + * - User + - None + - Username of a role to use for connection. For example, ``User="rhendricks"`` + * - Password + - None + - Specifies the password of the selected role. For example, ``User="Tr0ub4dor&3"`` + * - Database + - None + - Specifies the database name to connect to. For example, ``Database="master"`` + * - Service + - ``sqream`` + - Specifices :ref:`service queue` to use. For example, ``Service="etl"``. Leave blank (``Service=""``) for default service ``sqream``. + * - Server + - None + - Hostname of the SQream DB worker. For example, ``Server="127.0.0.1"`` or ``Server="sqream.mynetwork.co"`` + * - Port + - None + - TCP port of the SQream DB worker. For example, ``Port="5000"`` or ``Port="3108"`` for the load balancer + * - Cluster + - ``false`` + - Connect via load balancer (use only if exists, and check port). For example, ``Cluster=true`` + * - Ssl + - ``false`` + - Specifies SSL for this connection. For example, ``Ssl=true`` + * - DriverManagerEncoding + - ``UTF-16`` + - Depending on how unixODBC is installed, you may need to change this to ``UTF-32``. + * - ErrorMessagesPath + - None + - Location where the driver was installed. For example, ``ErrorMessagePath=/home/rhendricks/sqream_odbc64/ErrorMessages``. + * - LogLevel + - 0 + - Set to 0-6 for logging. Use this setting when instructed to by SQream Support. For example, ``LogLevel=1`` + + .. hlist:: + :columns: 3 + + * 0 = Disable tracing + * 1 = Fatal only error tracing + * 2 = Error tracing + * 3 = Warning tracing + * 4 = Info tracing + * 5 = Debug tracing + * 6 = Detailed tracing + + + diff --git a/third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst similarity index 97% rename from third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst rename to connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst index 7749b44ab..4972e3057 100644 --- a/third_party_tools/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst @@ -1,134 +1,134 @@ -.. _install_odbc_windows: - -**************************************** -Install and Configure ODBC on Windows -**************************************** - -The ODBC driver for Windows is provided as a self-contained installer. - -This tutorial shows you how to install and configure ODBC on Windows. - -.. contents:: In this topic: - :local: - :depth: 2 - -Installing the ODBC Driver -================================== - -Prerequisites ----------------- - -.. _vcredist: - -Visual Studio 2015 Redistributables -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To install the ODBC driver you must first install Microsoft's **Visual C++ Redistributable for Visual Studio 2015**. To install Visual C++ Redistributable for Visual Studio 2015, see the `Install Instructions `_. - -Administrator Privileges -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The SQream DB ODBC driver requires administrator privileges on your computer to add the DSNs (data source names). - - -1. Run the Windows installer ------------------------------- - -Install the driver by following the on-screen instructions in the easy-to-follow installer. - -.. image:: /_static/images/odbc_windows_installer_screen1.png - -.. note:: The installer will install the driver in ``C:\Program Files\SQream Technologies\ODBC Driver`` by default. This path is changable during the installation. - -2. Selecting Components -^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The installer includes additional components, like JDBC and Tableau customizations. - -.. image:: /_static/images/odbc_windows_installer_screen2.png - -You can deselect items you don't want to install, but the items named **ODBC Driver DLL** and **ODBC Driver Registry Keys** must remain selected for a complete installation of the ODBC driver. - -Once the installer finishes, you will be ready to configure the DSN for connection. - -.. _create_windows_odbc_dsn: - -3. Configuring the ODBC Driver DSN -====================================== - -ODBC driver configurations are done via DSNs. Each DSN represents one SQream DB database. - -#. Open up the Windows menu by clicking the Windows button on your keyboard (:kbd:`⊞ Win`) or pressing the Windows button with your mouse. - -#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. Click the item to open up the setup window. - - .. image:: /_static/images/odbc_windows_startmenu.png - -#. The installer has created a sample User DSN named **SQreamDB** - - You can modify this DSN, or create a new one (:menuselection:`Add --> SQream ODBC Driver --> Next`) - - .. image:: /_static/images/odbc_windows_dsns.png - -#. Enter your connection parameters. See the reference below for a description of the parameters. - - .. image:: /_static/images/odbc_windows_dsn_config.png - -#. When completed, save the DSN by selecting :menuselection:`OK` - -.. tip:: Test the connection by clicking :menuselection:`Test` before saving. A successful test looks like this: - - .. image:: /_static/images/odbc_windows_dsn_test.png - -#. You can now use this DSN in ODBC applications like :ref:`Tableau `. - - - -Connection Parameters ------------------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Item - - Description - * - Data Source Name - - An easily recognizable name that you'll use to reference this DSN. Once you set this, it can not be changed. - * - Description - - A description of this DSN for your convenience. You can leave this blank. - * - User - - Username of a role to use for connection. For example, ``rhendricks`` - * - Password - - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` - * - Database - - Specifies the database name to connect to. For example, ``master`` - * - Service - - Specifices :ref:`service queue` to use. For example, ``etl``. Leave blank for default service ``sqream``. - * - Server - - Hostname of the SQream DB worker. For example, ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - TCP port of the SQream DB worker. For example, ``5000`` or ``3108`` - * - User server picker - - Connect via load balancer (use only if exists, and check port) - * - SSL - - Specifies SSL for this connection - * - Logging options - - Use this screen to alter logging options when tracing the ODBC connection for possible connection issues. - - -Troubleshooting -================== - -Solving "Code 126" ODBC errors ---------------------------------- - -After installing the ODBC driver, you may experience the following error: - -.. code-block:: none - - The setup routines for the SQreamDriver64 ODBC driver could not be loaded due to system error - code 126: The specified module could not be found. - (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) - -This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. +.. _install_odbc_windows: + +**************************************** +Install and Configure ODBC on Windows +**************************************** + +The ODBC driver for Windows is provided as a self-contained installer. + +This tutorial shows you how to install and configure ODBC on Windows. + +.. contents:: In this topic: + :local: + :depth: 2 + +Installing the ODBC Driver +================================== + +Prerequisites +---------------- + +.. _vcredist: + +Visual Studio 2015 Redistributables +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To install the ODBC driver you must first install Microsoft's **Visual C++ Redistributable for Visual Studio 2015**. To install Visual C++ Redistributable for Visual Studio 2015, see the `Install Instructions `_. + +Administrator Privileges +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The SQream DB ODBC driver requires administrator privileges on your computer to add the DSNs (data source names). + + +1. Run the Windows installer +------------------------------ + +Install the driver by following the on-screen instructions in the easy-to-follow installer. + +.. image:: /_static/images/odbc_windows_installer_screen1.png + +.. note:: The installer will install the driver in ``C:\Program Files\SQream Technologies\ODBC Driver`` by default. This path is changable during the installation. + +2. Selecting Components +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The installer includes additional components, like JDBC and Tableau customizations. + +.. image:: /_static/images/odbc_windows_installer_screen2.png + +You can deselect items you don't want to install, but the items named **ODBC Driver DLL** and **ODBC Driver Registry Keys** must remain selected for a complete installation of the ODBC driver. + +Once the installer finishes, you will be ready to configure the DSN for connection. + +.. _create_windows_odbc_dsn: + +3. Configuring the ODBC Driver DSN +====================================== + +ODBC driver configurations are done via DSNs. Each DSN represents one SQream DB database. + +#. Open up the Windows menu by clicking the Windows button on your keyboard (:kbd:`⊞ Win`) or pressing the Windows button with your mouse. + +#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. Click the item to open up the setup window. + + .. image:: /_static/images/odbc_windows_startmenu.png + +#. The installer has created a sample User DSN named **SQreamDB** + + You can modify this DSN, or create a new one (:menuselection:`Add --> SQream ODBC Driver --> Next`) + + .. image:: /_static/images/odbc_windows_dsns.png + +#. Enter your connection parameters. See the reference below for a description of the parameters. + + .. image:: /_static/images/odbc_windows_dsn_config.png + +#. When completed, save the DSN by selecting :menuselection:`OK` + +.. tip:: Test the connection by clicking :menuselection:`Test` before saving. A successful test looks like this: + + .. image:: /_static/images/odbc_windows_dsn_test.png + +#. You can now use this DSN in ODBC applications like :ref:`Tableau `. + + + +Connection Parameters +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - Description + * - Data Source Name + - An easily recognizable name that you'll use to reference this DSN. Once you set this, it can not be changed. + * - Description + - A description of this DSN for your convenience. You can leave this blank. + * - User + - Username of a role to use for connection. For example, ``rhendricks`` + * - Password + - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` + * - Database + - Specifies the database name to connect to. For example, ``master`` + * - Service + - Specifices :ref:`service queue` to use. For example, ``etl``. Leave blank for default service ``sqream``. + * - Server + - Hostname of the SQream DB worker. For example, ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - TCP port of the SQream DB worker. For example, ``5000`` or ``3108`` + * - User server picker + - Connect via load balancer (use only if exists, and check port) + * - SSL + - Specifies SSL for this connection + * - Logging options + - Use this screen to alter logging options when tracing the ODBC connection for possible connection issues. + + +Troubleshooting +================== + +Solving "Code 126" ODBC errors +--------------------------------- + +After installing the ODBC driver, you may experience the following error: + +.. code-block:: none + + The setup routines for the SQreamDriver64 ODBC driver could not be loaded due to system error + code 126: The specified module could not be found. + (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) + +This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables ` section above. diff --git a/third_party_tools/connectivity_ecosystem.jpg b/connecting_to_sqream/connectivity_ecosystem.jpg similarity index 100% rename from third_party_tools/connectivity_ecosystem.jpg rename to connecting_to_sqream/connectivity_ecosystem.jpg diff --git a/third_party_tools/index.rst b/connecting_to_sqream/index.rst similarity index 95% rename from third_party_tools/index.rst rename to connecting_to_sqream/index.rst index ee581e337..a790f085d 100644 --- a/third_party_tools/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,17 +1,17 @@ -.. _third_party_tools: - -************************* -Third Party Tools -************************* -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. - -This section provides information about the following third party tools: - -.. toctree:: - :maxdepth: 2 - :glob: - :titlesonly: - - client_drivers/index - +.. _third_party_tools: + +************************* +Connecting to SQream +************************* +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. + +This section provides information about the following third party tools: + +.. toctree:: + :maxdepth: 2 + :glob: + :titlesonly: + + client_drivers/index + If you need a tool that SQream does not support, contact SQream Support or your SQream account manager for more information. \ No newline at end of file diff --git a/index.rst b/index.rst index 72731e378..db8e0fa2a 100644 --- a/index.rst +++ b/index.rst @@ -104,7 +104,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu installation_guides/index data_ingestion/index connecting_to_sqream/index - loading_and_unloading/index + loading_and_unloading_data/index feature_guides/index operational_guides/index sqream_studio_5.4.3/index From 5c18f92de9ad9a0f7427c43a33ff3f0124d40daf Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 17:50:53 +0300 Subject: [PATCH 0107/1892] Corrected links. --- loading_and_unloading_data/index.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst index ae5c506bb..bc515f023 100644 --- a/loading_and_unloading_data/index.rst +++ b/loading_and_unloading_data/index.rst @@ -5,32 +5,32 @@ Loading and Unloading Data *********************** The **Loading Data** section describes concepts and operations related to importing data into your SQream database: -* `Overview of loading data `_ - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. +* `Overview of loading data `_ - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. -* `Alternatives to loading data (foreign tables) `_ - Useful for running queries directly on external data without importing into your SQream database. +* `Alternatives to loading data (foreign tables) `_ - Useful for running queries directly on external data without importing into your SQream database. -* `Supported data types `_ - Overview of supported data types, including descriptions, examples, and relevant aliases. +* `Supported data types `_ - Overview of supported data types, including descriptions, examples, and relevant aliases. -* `Ingesting data from external sources `_ - List of data ingestion sources that SQream supports. +* `Ingesting data from external sources `_ - List of data ingestion sources that SQream supports. -* `Inserting data from external tables `_ - Inserts one or more rows into a table. +* `Inserting data from external tables `_ - Inserts one or more rows into a table. -* `Ingesting data from third party client platforms `_ - Gives you direct access to a variety of drivers, connectors, tools, vizualisers, and utilities.. +* `Ingesting data from third party client platforms `_ - Gives you direct access to a variety of drivers, connectors, tools, vizualisers, and utilities.. -* `Using the COPY FROM statement `_ - Used for loading data from files located on a filesystem into SQream tables. +* `Using the COPY FROM statement `_ - Used for loading data from files located on a filesystem into SQream tables. -* `Importing data using Studio `_ - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. +* `Importing data using Studio `_ - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. -* `Loading data using Amazon S3 `_ - Used for loading data from Amazon S3. +* `Loading data using Amazon S3 `_ - Used for loading data from Amazon S3. * Troubleshooting - Describes troubleshooting solutions related to importing data from the following: - * `SAS Viya `_ + * `SAS Viya `_ - * `Tableau `_ + * `Tableau `_ The **Unloading Data** section describes concepts and operations related to exporting data from your SQream database: -* `Overview of unloading data `_ - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. +* `Overview of unloading data `_ - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. -* `The COPY TO statement `_ - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file +* `The COPY TO statement `_ - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file From 97c150d3d44aaadc2f7585f52887673b0b6dced8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 10 Jul 2022 18:54:57 +0300 Subject: [PATCH 0108/1892] Update inserting_data.rst --- data_ingestion/inserting_data.rst | 196 ++++++++++++++++-------------- 1 file changed, 103 insertions(+), 93 deletions(-) diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/inserting_data.rst index 42ac36ceb..e20e37920 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/inserting_data.rst @@ -3,138 +3,161 @@ *************************** Inserting Data Overview *************************** +The **Inserting Data Overview** page provides basic information useful when ingesting data into SQream from a variety of sources and locations, and describes the following: -The **Inserting Data Overview** page describes how to insert data into SQream, specifically how to insert data from a variety of sources and locations. - -.. contents:: In this topic: +.. contents:: :local: - - + :depth: 1 + Getting Started ================================ +SQream supports ingesting data using the following methods: -SQream supports importing data from the following sources: +* Executing the ``INSERT`` statement using a client driver. -* Using :ref:`insert` with :ref:`a client driver` -* Using :ref:`copy_from`: + :: + +* Executing the ``COPY FROM`` statement or ingesting data from foreign tables: - - Local filesystem and locally mounted network filesystems - - :ref:`s3` - - :ref:`hdfs` + * Local filesystem and locally mounted network filesystems + * Inserting Data using the Amazon S3 object storage service + * Inserting Data using an HDFS data storage system -* Using :ref:`external_tables`: +SQream supports loading files from the following formats: - - Local filesystem and locally mounted network filesystems - - :ref:`s3` - - :ref:`hdfs` +* Text - CSV, TSV, and PSV +* Parquet +* ORC +For more information, see the following: -SQream DB supports loading files in the following formats: +* Using the ``INSERT`` statement - :ref:`insert` -* Text - CSV, TSV, PSV -* Parquet -* ORC +* Using client drivers - :ref:`Client drivers` + +* Using the ``COPY FROM`` statement - :ref:`copy_from` + +* Using the Amazon S3 object storage service - :ref:`s3` + +* Using the HDFS data storage system - :ref:`hdfs` + +* Loading data from foreign tables - :ref:`foreign_tables` Data Loading Considerations ================================ +The **Data Loading Considerations** section describes the following: +.. contents:: + :local: + :depth: 1 + Verifying Data and Performance after Loading ----------------------------------------- +Like many RDBMSs, SQream recommends its own set of best practices for table design and query optimization. When using SQream, verify the following: -Like other RDBMSs, SQream DB has its own set of best practcies for table design and query optimization. - -SQream therefore recommends: +* That your data is structured as you expect (row counts, data types, formatting, content). -* Verify that the data is as you expect it (e.g. row counts, data types, formatting, content) +* That your query performance is adequate. -* The performance of your queries is adequate +* That you followed the table design best practices (:ref:`Optimization and Best Practices`). -* :ref:`Best practices` were followed for table design +* That you've tested and verified that your applications work (such as :ref:`Tableau`). -* Applications such as :ref:`Tableau` and others have been tested, and work +* That your data types have not been not over-provisioned. File Soure Location when Loading -------------------------------- +While you are loading data, you can use the ``COPY FROM`` command to let statements run on any worker. If you are running multiple nodes, verify that all nodes can see the source the same. Loading data from a local file that is only on one node and not on shared storage may cause it to fail. If required, you can also control which node a statement runs on using the Workload Manager). -During loading using :ref:`copy_from`, the statement can run on any worker. If you are running multiple nodes, make sure that all nodes can see the source the same. If you load from a local file which is only on 1 node and not on shared storage, it will fail some of the time. (If you need to, you can also control which node a statement runs on using the :ref:`workload_manager`). +For more information, see the following: -Supported load methods +* :ref:`copy_from` + +* :ref:`workload_manager` + +Supported Load Methods ------------------------------- +You can use the ``COPY FROM`` syntax to load CSV files. -SQream DB's :ref:`COPY FROM` syntax can be used to load CSV files, but can't be used for Parquet and ORC. +.. note:: The ``COPY FROM`` cannot be used for loading data from Parquet and ORC files. -:ref:`FOREIGN TABLE` can be used to load text files, Parquet, and ORC files, and can also transform the data prior to materialization as a full table. +You can use foreign tables to load text files, Parquet, and ORC files, and to transform your data before generating a full table, as described in the following table: .. list-table:: :widths: auto :header-rows: 1 :stub-columns: 1 - * - Method / File type + * - Method/File Type - Text (CSV) - Parquet - ORC - - Streaming data - * - :ref:`copy_from` + - Streaming Data + * - COPY FROM - Supported - Not supported - Not supported - Not supported - * - :ref:`external_tables` + * - Foreign tables - Supported - Supported - Supported - Not supported - * - :ref:`insert` + * - INSERT - Not supported - Not supported - Not supported - Supported (Python, JDBC, Node.JS) + +For more information, see the following: -Unsupported Data Types ------------------------------ +* :ref:`COPY FROM` + +* :ref:`Foreign tables` -SQream DB doesn't support the entire set of features that some other database systems may have, such as ``ARRAY``, ``BLOB``, ``ENUM``, ``SET``, etc. +* :ref:`INSERT` -These data types will have to be converted before load. For example, ``ENUM`` can often be stored as a ``TEXT``. +Unsupported Data Types +----------------------------- +SQream does not support certain features that are supported by other databases, such as ``ARRAY``, ``BLOB``, ``ENUM``, and ``SET``. You must convert these data types before loading them. For example, you can store ``ENUM`` as ``TEXT``. Handing Extended Errors ---------------------------- +While you can use foreign tables to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options and extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. -While :ref:`external tables` can be used to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options, as well as extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. +For more information, see :ref:`foreign tables`. Best Practices for CSV ------------------------------ +Text files, such as CSV, rarely conform to `RFC 4180 `_ , so you may need to make the following modifications: -Text files like CSV rarely conform to `RFC 4180 `_ , so alterations may be required: - -* Use ``OFFSET 2`` for files containing header rows +* Use ``OFFSET 2`` for files containing header rows. -* Failed rows can be captured in a log file for later analysis, or just to skip them. See :ref:`capturing_rejected_rows` for information on skipping rejected rows. +* You can capture failed rows in a log file for later analysis, or skip them. See :ref:`capturing_rejected_rows` for information on skipping rejected rows. -* Record delimiters (new lines) can be modified with the :ref:`RECORD DELIMITER` syntax. +* You can modify record delimiters (new lines) using the :ref:`RECORD DELIMITER` syntax. -* If the date formats differ from ISO 8601, refer to the :ref:`copy_date_parsers` section to see how to override default parsing. +* If the date formats deviate from ISO 8601, refer to the :ref:`copy_date_parsers` section for overriding the default parsing. -* - Fields in a CSV can be optionally quoted with double-quotes (``"``). However, any field containing a newline or another double-quote character must be quoted. +* *(Optional)* You can quote fields in a CSV using double-quotes (``"``). - If a field is quoted, any double quote that appears must be double-quoted (similar to the :ref:`string literals quoting rules`. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. +.. note:: You must quote any field containing a new line or another double-quote character. -* Field delimiters don't have a to be a displayable ASCII character. See :ref:`field_delimiters` for all options. +* If a field is quoted, you must double quote any double quote, similar to the **string literals quoting rules**. For example, to encode ``What are "birds"?``, the field should appear as ``"What are ""birds""?"``. For more information, see :ref:`string literals quoting rules`. +* Field delimiters do not have to be a displayable ASCII character. For all supported field delimiters, see :ref:`field_delimiters`. Best Practices for Parquet -------------------------------- +The following list shows the best practices when inserting data from Parquet files: -* Parquet files are loaded through :ref:`external_tables`. The destination table structure has to match in number of columns between the source files. +* You must load Parquet files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. -* Parquet files support predicate pushdown. When a query is issued over Parquet files, SQream DB uses row-group metadata to determine which row-groups in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of rows. +* Parquet files support **predicate pushdown**. When a query is issued over Parquet files, SQream uses row-group metadata to determine which row-groups in a file must be read for a particular query and the row indexes can narrow the search to a particular set of rows. -Type Support and Behavior Notes +Supported Types and Behavior Notes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* Unlike ORC, the column types should match the data types exactly (see table below). +Unlike the ORC format, the column types should match the data types exactly, as shown in the table below: .. list-table:: :widths: auto @@ -155,7 +178,7 @@ Type Support and Behavior Notes - ``DATE`` - ``DATETIME`` * - ``BOOLEAN`` - - ✓ + - Supported - - - @@ -168,7 +191,7 @@ Type Support and Behavior Notes * - ``INT16`` - - - - ✓ + - Supported - - - @@ -180,7 +203,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -192,7 +215,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -204,7 +227,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -216,7 +239,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - - @@ -228,7 +251,7 @@ Type Support and Behavior Notes - - - - - ✓ + - Supported - - * - ``INT96`` [#f3]_ @@ -241,31 +264,34 @@ Type Support and Behavior Notes - - - - - ✓ [#f4]_ + - Supported [#f4]_ -* If a Parquet file has an unsupported type like ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. +If a Parquet file has an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the table does not reference this data (i.e., the data does not appear in the :ref:`SELECT` query), the statement will succeed. If the table **does** reference a column, an error will be displayed explaining that the type is not supported, but the column may be omitted. Best Practices for ORC -------------------------------- +The following list shows the best practices when inserting data from ORC files: -* ORC files are loaded through :ref:`external_tables`. The destination table structure has to match in number of columns between the source files. +* You must load ORC files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. -* ORC files support predicate pushdown. When a query is issued over ORC files, SQream DB uses ORC metadata to determine which stripes in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of 10,000 rows. +* ORC files support **predicate pushdown**. When a query is issued over ORC files, SQream uses ORC metadata to determine which stripes in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of 10,000 rows. Type Support and Behavior Notes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +You must load ORC files through foreign table. Note that the destination table structure must be identical to the number of columns between the source files. -* ORC files are loaded through :ref:`external_tables`. The destination table structure has to match in number of columns between the source files. +For more information, see :ref:`foreign_tables`. -* The types should match to some extent within the same "class" (see table below). +The types should match to some extent within the same "class", as shown in the following table: .. list-table:: - :widths: 5 5 70 70 70 70 5 5 5 5 5 + :widths: auto :header-rows: 1 + :stub-columns: 1 - * - SQream DB type → + * - SQream DB Type → - ORC source + ORC Source - ``BOOL`` - ``TINYINT`` - ``SMALLINT`` @@ -273,7 +299,7 @@ Type Support and Behavior Notes - ``BIGINT`` - ``REAL`` - ``DOUBLE`` - - ``Text`` [#f0]_ + - Text [#f0]_ - ``DATE`` - ``DATETIME`` * - ``boolean`` @@ -353,7 +379,7 @@ Type Support and Behavior Notes - - - - * - ``string`` / ``char`` / ``text`` + * - ``string`` / ``char`` / ``varchar`` - - - @@ -432,31 +458,15 @@ Type Support and Behavior Notes Further Reading and Migration Guides ======================================= - -.. toctree:: - :caption: Data loading guides - :titlesonly: - - migration/csv - migration/parquet - migration/orc - -.. toctree:: - :caption: Migration guides - :titlesonly: - - migration/oracle - - -.. rubric:: See also: +For more information, see the following: * :ref:`copy_from` * :ref:`insert` -* :ref:`external_tables` +* :ref:`foreign_tables` .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT`` +.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` .. [#f2] With UTF8 annotation @@ -468,4 +478,4 @@ Further Reading and Migration Guides .. [#f6] Will succeed if all values are 0, 1 -.. [#f7] Will succeed if all values fit the destination type +.. [#f7] Will succeed if all values fit the destination type \ No newline at end of file From 00aeb5eed444ba49cdeea40ce957d88c05abc4e9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 12 Jul 2022 18:21:00 +0300 Subject: [PATCH 0109/1892] SQ-10818 --- reference/sql/sql_statements/index.rst | 8 +- .../get_role_database_ddl.rst | 61 +++++++++++++++ .../utility_commands/get_role_global_ddl.rst | 61 +++++++++++++++ .../utility_commands/get_role_permissions.rst | 74 +++++++++++++++++++ 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_role_permissions.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index e3ebf5aae..1a075f69e 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -168,7 +168,7 @@ The following table shows the Access Control commands: .. list-table:: :widths: 10 100 - :header-rows: 1 + :header-rows: 1 * - Command - Usage @@ -180,6 +180,12 @@ The following table shows the Access Control commands: - Creates a roles, which lets a database administrator control permissions on tables and databases * - :ref:`drop_role` - Removes roles + * - :ref:`get_role_permissions` + - Returns all permissions granted to a role in table format + * - :ref:`get_role_global_ddl` + - Returns the definition of a global role in DDL format + * - :ref:`get_role_database_ddl` + - Returns the definition of a database role in DDL format * - :ref:`get_statement_permissions` - Returns a list of permissions required to run a statement or query * - :ref:`grant` diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst new file mode 100644 index 000000000..e6b806244 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -0,0 +1,61 @@ +.. _get_role_database_ddl: + +******************** +GET_ROLE_DATABASE_DDL +******************** +The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a global role in DDL format. + +The ``GET_ROLE_DATABASE_DDL`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_DATABASE_DDL`` statement: + +.. code-block:: postgres + + select get_role_database_ddl(<'role_name'>) + +Example +=========== +The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: psql + + select get_role_global_ddl('public'); + +Parameters +============ +The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``role_name`` + - The definition of the database role in DDL format. + +Output +========== +The following is an example of the output of the ``GET_ROLE_DATABASE_DDL`` statement: + +.. code-block:: postgres + + grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl to creator_role ; + +Permissions +============= +Using the ``GET_ROLE_DATABASE_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_global_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst new file mode 100644 index 000000000..3ba0255d3 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst @@ -0,0 +1,61 @@ +.. _get_role_global_ddl: + +******************** +GET_ROLE_GLOBAL_DDL +******************** +The ``GET_ROLE_GLOBAL_DDL`` statement returns the definition of a global role in DDL format. + +The ``GET_ROLE_GLOBAL_DDL`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + select get_role_global_ddl(<'role_name'>) + +Example +=========== +The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: psql + + select get_role_global_ddl('public'); + +Parameters +============ +The following table shows the ``GET_ROLE_GLOBAL_DDL`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``role_name`` + - The definition of the global role in DDL format. + +Output +========== +The following is an example of the output of the ``GET_ROLE_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + create role "public"; + +Permissions +============= +Using the ``GET_ROLE_GLOBAL_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_database_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst new file mode 100644 index 000000000..8723f98c8 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst @@ -0,0 +1,74 @@ +.. _get_role_permissions: + +******************** +GET_ROLE_PERMISSIONS +******************** +The ``GET_ROLE_PERMISSIONS`` statement returns all permissions granted to a role in table format. + +The ``GET_ROLE_PERMISSIONS`` page describes the following: + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ROLE_PERMISSIONS`` statement: + +.. code-block:: postgres + + select get_role_permissions() + +Example +=========== +The following is an example of using the ``GET_ROLE_PERMISSIONS`` statement: + +.. code-block:: psql + + select get_role_permissions(); + +Parameters +============ +The following table shows the ``GET_ROLE_PERMISSIONS`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``()`` + - The permissions belonging to the role. + +Output +========== +The following is an example of the output of the ``GET_ROLE_PERMISSIONS`` statement: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Example + * - ``permission_type`` + - The permission type granted to the role. + - SUPERUSER + * - ``object_type`` + - The data object type. + - table + * - ``object_name`` + - The name of the object. + - master.public.nba + +Permissions +============= +Using the ``GET_ROLE_PERMISSIONS`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_role_database_ddl` + + :: + +* :ref:`get_role_global_ddl` \ No newline at end of file From 90d7637f7116d0399b99fecfb07d00c662936c7f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 13 Jul 2022 08:11:03 +0300 Subject: [PATCH 0110/1892] Update create_table.rst --- .../sql_statements/ddl_commands/create_table.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 51f46582b..eb25baa8a 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may be a literal, which is evaluated at the time the row is created. +The value may either be a literal, **GETDATE()**, or Null, which is evaluated at the time the row is created. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. @@ -141,7 +141,7 @@ The following is an example of the syntax used to create a standard table: CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL ); @@ -155,7 +155,7 @@ The following is an example of the syntax used to create a table with default va CREATE TABLE cool_animals ( id INT NOT NULL, - name varchar(30) NOT NULL, + name text(30) NOT NULL, weight FLOAT, is_agressive BOOL DEFAULT false NOT NULL ); @@ -171,8 +171,8 @@ The following is an example of the syntax used to create a table with an identit CREATE TABLE users ( id BIGINT IDENTITY(0,1) NOT NULL , -- Start with 0, increment by 1 - name VARCHAR(30) NOT NULL, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + name TEXT(30) NOT NULL, + country TEXT(30) DEFAULT 'Unknown' NOT NULL ); .. note:: @@ -203,9 +203,9 @@ The following is an example of the syntax used to create a table with a clusteri .. code-block:: postgres CREATE TABLE users ( - name VARCHAR(30) NOT NULL, + name TEXT(30) NOT NULL, start_date datetime not null, - country VARCHAR(30) DEFAULT 'Unknown' NOT NULL + country TEXT(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; For more information on data clustering, see :ref:`data_clustering`. From 012d0e9f4debe6c5f58e70ac04ba64916e36b7e0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 14 Jul 2022 11:56:35 +0300 Subject: [PATCH 0111/1892] Update 2021.2.1.rst Added Resolved Issues and Known Issues for minor patches: 2021.2.1.1 and 2021.2.1.23. NOTE: These bugs have NOT YET been filtered for external vs internal, which Eyal W is working on now. This means that I will remove some of these bugs once he's created the filter. THIS IS NOT PUBLISHED. --- releases/2021.2.1.rst | 57 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index f17bdd516..063143529 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -45,7 +45,6 @@ For more information, see `Deleting Values that Contain Multi-Table Conditions < For more information, see :ref:`regexp_replace`. - Performance Enhancements ------ The **Performance Enhancements** section is not relevant to Version 2021.2.1. @@ -61,13 +60,65 @@ The following table lists the issues that were resolved in Version 2021.2.1: * - SQ No. - Description * - SQ-8267 - - A method has been provided for including the ``GROUP BY`` and ``DISTINCT COUNT`` statements. - + - A method has been provided for including the ``GROUP BY`` and ``DISTINCT COUNT`` statements. + +The following table lists the issues that were resolved in Version 2021.2.1.1: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-9114 + - `cleanup_extents` on empty texts results in a missing file + * - SQ-8849 + - Unclear "Map:at" error for invalid column mapping of Parquet files + +The following table lists the issues that were resolved in Version 2021.2.1.23: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-10703 + - it implements a FILTER on delete statements which means that delete statements would not scan the entire metadata but only according to the filter Known Issues ------ The **Known Issues** section is not relevant to 2021.2.1. +The following table lists the issues that were resolved in Version 2021.2.1.1: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-9003 + - Insert as Select with Order By - Internal Runtime Error + * - SQ-9121 + - Support cleanup_extents with empty text columns for cloud environment + * - SQ-8954 + - GCP one worker crash when copying a table using 8 workers + * - SQ-5485 + - The compiler has an issue with count being used as an alias and in the select list + * - SQ-7732 + - Fail to read numeric (38,0) from parquet + * - SQ-7800 + - AWS - Creating 4,000,000 chunks in leveldb by a copy operation causes segmentation fault in leveldb + * - SQ-7903 + - Filters and metadata_filters doesn't work well for numeric/float literals without an explicit cast + * - SQ-7931 + - Difference to Postgres when comparing literal float4 and float8 + * - SQ-8274 + - Cast to numeric with default precision doesn't work + +The **Known Issues** section is not relevant to Version 2021.2.1.23. + Naming Convention Modifications ------ The **Naming Convention Modifications** section is not relevant to Version 2021.2.1. From 4e85d0bb5994f907e74d6927ec3bf69f257c5226 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 14 Jul 2022 13:59:38 +0300 Subject: [PATCH 0112/1892] Made release table on all index pages Improved menu functionality (by adding toctree at bottom of each page to relevant pages) --- releases/2020.1.rst | 9 +++++- releases/2020.2.rst | 7 +++++ releases/2020.3.1.rst | 9 +++++- releases/2020.3.2.1.rst | 9 +++++- releases/2020.3.rst | 7 +++++ releases/2020.3_index.rst | 17 ++++++----- releases/2021.1.1.rst | 9 +++++- releases/2021.1.2.rst | 9 +++++- releases/2021.1.rst | 7 +++++ releases/2021.1_index.rst | 17 ++++++----- releases/2021.2.1.1.rst | 28 ++++++++++++++++++ releases/2021.2.1.23.rst | 26 ++++++++++++++++ releases/2021.2.1.rst | 62 +++++---------------------------------- releases/2021.2.rst | 9 +++++- releases/2021.2_index.rst | 17 +++++++---- releases/2022.1.rst | 9 +++++- releases/2022.1_index.rst | 19 ++++++++++++ releases/index.rst | 39 ++++++++++++------------ 18 files changed, 208 insertions(+), 101 deletions(-) create mode 100644 releases/2021.2.1.1.rst create mode 100644 releases/2021.2.1.23.rst create mode 100644 releases/2022.1_index.rst diff --git a/releases/2020.1.rst b/releases/2020.1.rst index e4928855e..86b619d54 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -185,4 +185,11 @@ Upgrading to v2020.1 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. +Contact your account manager to get the latest release of SQream. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2020.1 \ No newline at end of file diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 3dc25b78a..917d80800 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -113,3 +113,10 @@ Upgrading to Version 2020.2 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. Contact your account manager to get the latest release of SQream. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2020.2 \ No newline at end of file diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst index 0667306d7..b66454c75 100644 --- a/releases/2020.3.1.rst +++ b/releases/2020.3.1.rst @@ -69,4 +69,11 @@ Upgrading to v2020.3.1 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. \ No newline at end of file +Contact your account manager to get the latest release of SQream. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2020.3.1 \ No newline at end of file diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst index 3c551b636..8fef047f6 100644 --- a/releases/2020.3.2.1.rst +++ b/releases/2020.3.2.1.rst @@ -28,4 +28,11 @@ Upgrading to v2020.3.2.1 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. -Contact your account manager to get the latest release of SQream DB. \ No newline at end of file +Contact your account manager to get the latest release of SQream. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2020.3.2.1 \ No newline at end of file diff --git a/releases/2020.3.rst b/releases/2020.3.rst index d072b15da..b51a9955d 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -100,3 +100,10 @@ Upgrading to v2020.3 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. Contact your account manager to get the latest release of SQream. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2020.3 diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst index b13340b52..19bf3bd79 100644 --- a/releases/2020.3_index.rst +++ b/releases/2020.3_index.rst @@ -3,16 +3,19 @@ ************************** Release Notes 2020.3 ************************** -The 2020.3 Release Notes describe the following releases: +SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -.. contents:: - :local: - :depth: 1 ++---------------------------------+----------------------------------+------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :glob: + :hidden: - 2020.3.2.1 + 2020.3 2020.3.1 - 2020.3 \ No newline at end of file + 2020.3.2.1 \ No newline at end of file diff --git a/releases/2021.1.1.rst b/releases/2021.1.1.rst index 8e6417a43..992b2f850 100644 --- a/releases/2021.1.1.rst +++ b/releases/2021.1.1.rst @@ -61,4 +61,11 @@ The following list describes the resolved issues: * The Decimal column was not supported when inserting data from Parquet files. This was fixed. * Values in Parquet Numeric columns were not being converted correctly. This was fixed. * Converting ``string`` data type to ``datetime`` was not working correctly. This was fixed. -* Casting ``datetime`` to ``text`` truncated the time. This was fixed. \ No newline at end of file +* Casting ``datetime`` to ``text`` truncated the time. This was fixed. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.1.1 \ No newline at end of file diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index 43ce6db7d..448b047df 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -58,4 +58,11 @@ The following list describes the resolved issues: * In Parquet files, ``float`` columns could not be mapped to SQream ``double`` columns. This was fixed. * The ``REPLACE`` function only supported constant values as arguments. This was fixed. -* The ``LIKE`` function did not check for incorrect patterns or handle escape characters. This was fixed. \ No newline at end of file +* The ``LIKE`` function did not check for incorrect patterns or handle escape characters. This was fixed. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.1.2 \ No newline at end of file diff --git a/releases/2021.1.rst b/releases/2021.1.rst index b2b0dcfd8..15824d5d5 100644 --- a/releases/2021.1.rst +++ b/releases/2021.1.rst @@ -211,3 +211,10 @@ The the list below describes the following known issues and limitations: Upgrading to v2021.1 ------- Due to the known issue of a limitation on the amount of access requests that can be simultaneously sent to AWS, deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.1 \ No newline at end of file diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst index 64b06e1d1..5ba66f511 100644 --- a/releases/2021.1_index.rst +++ b/releases/2021.1_index.rst @@ -3,16 +3,19 @@ ************************** Release Notes 2021.1 ************************** -The 2021.1 Release Notes describe the following releases: +SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -.. contents:: - :local: - :depth: 1 ++---------------------------------+----------------------------------+------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :glob: + :hidden: - 2021.1.2 + 2021.1 2021.1.1 - 2021.1 \ No newline at end of file + 2021.1.2 \ No newline at end of file diff --git a/releases/2021.2.1.1.rst b/releases/2021.2.1.1.rst new file mode 100644 index 000000000..a1137e418 --- /dev/null +++ b/releases/2021.2.1.1.rst @@ -0,0 +1,28 @@ +.. _2021.2.1.1: + +****************************** +Release Notes 2021.2.1.1 +****************************** +The 2021.2.1.1 release notes is a patch version released on 9/12/2021. + +The following table lists the issues that were resolved in Version 2021.2.1.1: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-9114 + - `cleanup_extents` on empty texts results in a missing file + * - SQ-8849 + - `Unclear "Map:at" error for invalid column mapping of Parquet files + +Version 2021.2.1.1 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.1 \ No newline at end of file diff --git a/releases/2021.2.1.23.rst b/releases/2021.2.1.23.rst new file mode 100644 index 000000000..ca5e2dcbe --- /dev/null +++ b/releases/2021.2.1.23.rst @@ -0,0 +1,26 @@ +.. _2021.2.1.23: + +****************************** +Release Notes 2021.2.1.23 +****************************** +The 2021.2.1.23 release notes is a patch version released on 27/6/2022. + +The following table lists the issues that were resolved in Version 2021.2.1.23: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-10703 + - When the clause is specified, all existing permissions granted on source_table_name are granted on table_name as well. + +Version 2021.2.1.23 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.23 \ No newline at end of file diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index 063143529..3afba3093 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -62,63 +62,10 @@ The following table lists the issues that were resolved in Version 2021.2.1: * - SQ-8267 - A method has been provided for including the ``GROUP BY`` and ``DISTINCT COUNT`` statements. -The following table lists the issues that were resolved in Version 2021.2.1.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-9114 - - `cleanup_extents` on empty texts results in a missing file - * - SQ-8849 - - Unclear "Map:at" error for invalid column mapping of Parquet files - -The following table lists the issues that were resolved in Version 2021.2.1.23: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-10703 - - it implements a FILTER on delete statements which means that delete statements would not scan the entire metadata but only according to the filter - Known Issues ------ The **Known Issues** section is not relevant to 2021.2.1. -The following table lists the issues that were resolved in Version 2021.2.1.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-9003 - - Insert as Select with Order By - Internal Runtime Error - * - SQ-9121 - - Support cleanup_extents with empty text columns for cloud environment - * - SQ-8954 - - GCP one worker crash when copying a table using 8 workers - * - SQ-5485 - - The compiler has an issue with count being used as an alias and in the select list - * - SQ-7732 - - Fail to read numeric (38,0) from parquet - * - SQ-7800 - - AWS - Creating 4,000,000 chunks in leveldb by a copy operation causes segmentation fault in leveldb - * - SQ-7903 - - Filters and metadata_filters doesn't work well for numeric/float literals without an explicit cast - * - SQ-7931 - - Difference to Postgres when comparing literal float4 and float8 - * - SQ-8274 - - Cast to numeric with default precision doesn't work - -The **Known Issues** section is not relevant to Version 2021.2.1.23. - Naming Convention Modifications ------ The **Naming Convention Modifications** section is not relevant to Version 2021.2.1. @@ -129,4 +76,11 @@ The **End of Support** section is not relevant to Version 2021.2.1. Deprecated Features ------ -The **Deprecated Components** section is not relevant to Version 2021.2.1. \ No newline at end of file +The **Deprecated Components** section is not relevant to Version 2021.2.1. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1 \ No newline at end of file diff --git a/releases/2021.2.rst b/releases/2021.2.rst index ec4773669..1bd6c6223 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -169,4 +169,11 @@ Configuring Your Instance of SQream ************ A new configuration method is used starting with Version 2021.2. -For more information about configuring your instance of SQream, see :ref:`configuration`. \ No newline at end of file +For more information about configuring your instance of SQream, see :ref:`configuration`. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2 \ No newline at end of file diff --git a/releases/2021.2_index.rst b/releases/2021.2_index.rst index 77a22b0ae..6e207ee73 100644 --- a/releases/2021.2_index.rst +++ b/releases/2021.2_index.rst @@ -3,15 +3,20 @@ ************************** Release Notes 2021.2 ************************** -The 2021.2 Release Notes describe the following releases: +SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -.. contents:: - :local: - :depth: 1 ++---------------------------------+---------------------------------+------------------------------------------------------------------+ +| **Major Release** | **Minor Release** | ++---------------------------------+---------------------------------+--------------------------------+---------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.23<2021.2.1.23>` | ++---------------------------------+---------------------------------+--------------------------------+---------------------------------+ .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :glob: + :hidden: + 2021.2 2021.2.1 - 2021.2 \ No newline at end of file + 2021.2.1.1 + 2021.2.1.23 \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index ac180206c..52a6722e5 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -138,4 +138,11 @@ Upgrading to v2022.1 $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. \ No newline at end of file + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst new file mode 100644 index 000000000..c40867102 --- /dev/null +++ b/releases/2022.1_index.rst @@ -0,0 +1,19 @@ +.. _2022.1_index: + +************************** +Release Notes 2022.1 +************************** +The 2022.1 Release Notes describe the following releases: + ++---------------------------------+----------------------------------+------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2022.1<2022.1>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index e23036f7a..d68e0b55b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -3,27 +3,26 @@ ********** Release Notes ********** +SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. + ++---------------------------------+----------------------------------+------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2022.1<2022.1>` | | | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.23<2021.2.1.23>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2020.2<2020.2>` | | | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +| :ref:`2020.1<2020.1>` | | | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Version - - Release Date - * - :ref:`2022.1` - - MM DD, YYYY - * - :ref:`2021.2` - - September 13, 2021 - * - :ref:`2021.1` - - June 13, 2021 - * - :ref:`2020.3` - - October 8, 2020 - * - :ref:`2020.2` - - July 22, 2020 - * - :ref:`2020.1` - - January 15, 2020 + @@ -32,7 +31,7 @@ Release Notes :glob: :hidden: - 2022.1 + 2022.1_index 2021.2_index 2021.1_index 2020.3_index From 3cc5089a27da69132444777c105a7f3e5d41132d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 14 Jul 2022 16:04:36 +0300 Subject: [PATCH 0113/1892] Update index.rst --- releases/index.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index d68e0b55b..17fdbb529 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -8,17 +8,17 @@ SQream releases notes are specific to each version of the application. Select yo +---------------------------------+----------------------------------+------------------------------------------------------------------+ | **Major Release** | **Minor Releases** | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2022.1<2022.1>` | | | | +| :ref:`2022.1<2022.1>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ | :ref:`2021.2<2021.2>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.23<2021.2.1.23>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | | +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | | +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.2<2020.2>` | | | | +| :ref:`2020.2<2020.2>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.1<2020.1>` | | | | +| :ref:`2020.1<2020.1>` | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+ From 708d6676e6db6437a5e751e548832dfb1e07f2c8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Fri, 15 Jul 2022 01:11:17 +0300 Subject: [PATCH 0114/1892] Added all bugs (not filtered) --- releases/2021.2.1.22.rst | 26 ++++++ releases/2022.1.rst | 195 ++++++++++++++++++++++++++++++++++++--- releases/index.rst | 30 +++--- 3 files changed, 222 insertions(+), 29 deletions(-) create mode 100644 releases/2021.2.1.22.rst diff --git a/releases/2021.2.1.22.rst b/releases/2021.2.1.22.rst new file mode 100644 index 000000000..029ad0178 --- /dev/null +++ b/releases/2021.2.1.22.rst @@ -0,0 +1,26 @@ +.. _2021.2.1.22: + +****************************** +Release Notes 2021.2.1.22 +****************************** +The 2021.2.1.22 release notes is a patch version released on 27/6/2022. + +The following table lists the issues that were resolved in Version 2021.2.1.23: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-10776 + - Out Of Memory invoked during copy from with multiple files. + +Version 2021.2.1.23 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.22 \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 52a6722e5..74e568fad 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -60,20 +60,187 @@ Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1: -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-xxxx - - Text - * - SQ-xxxx - - Text - * - SQ-xxxx - - Text - -**Comment** - *The table above will be updated regarding which resolved issues to include.* +**Comment** - *The items in the table below must be filtered according to external and internal bugs. We CANNOT expose internal bugs to external users.* + ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-7490 | Native Avro file access via a dedicated FDW | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-7718 | Certify LTS Ubuntu versions (18.04 & 20.04) for production usage | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-7732 | Fail to read numeric columns from an external generated parquet file | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-8163 | Performance degradation - tpch1t_external_table_parquet - cases #6079 & #6105 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-8182 | Encryption Function | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-8984 | Update statement MVP: literal assignment | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9221 | [Mobicom] PBI - External Tables are not shown on the tables list. | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9611 | Create a WIN-874 to UTF-8 conversion function | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9634 | identifier not found | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9644 | [ACL] Incomplete logs query causing Internal Runtime Error | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9671 | Trying to read Thai UTF-8 csv file in TEXT column and it not shows Thai | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9764 | No error when create a foreign table with difference in the column numbers in the table and the file | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9790 | Encryption - MVP scope | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9808 | Allowing to set deferredValueIOThresholdFactor flag not in developer Mode=true | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9823 | [AIS] The user can't use literals when using sqream with Thai varchar | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9889 | [AIS] Internal runtime Error receive | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9952 | Removing temp files takes too long - timeout issue at LGU+ | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9988 | Find a proper solution for data lost during copy from parquet - without reverting previous optimization | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9990 | Merge v2021.2.1_stable into develop | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10005 | Go / No Go approvals | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10011 | Delete filter optimization chicken flag | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10055 | [SamsungDisplay] Slow loading of sqream after backup compacting | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10061 | compiler side - Implement MVP scope | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10071 | error on exists subqueries with text and varchar equality condition | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10111 | Parquet numeric - Sqream can't import parquet numeric columns from other sources | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10191 | [LGE] ALTER DEFAULT SCHEMA command has a problem. | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10216 | Performance degradation - tpch1t_1mchunk - case #1326 #1345 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10242 | socket 11 error from "Create as Select~" | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10269 | cleanup_chunk error with text(X) column | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10314 | Unable to load avro file to sqream v1 + v2 from s3 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10319 | Error on copy from avro file with numeric data | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10425 | Lot of time in copy from, external table parquet file | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10428 | [LGU] Can not execute cleanup_extents on table because there are mixed chunks | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10470 | count distinct on 0 rows doesn't return any value | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10478 | get_ddl disregards encrypted columns | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10479 | create a table with more than three encrypted column with no error | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10492 | Wrong values when select from table have encrypted column and regular column | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10494 | No “encrypted” label when read from table with encrypted column | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10496 | Not able to insert data to encrypted column after performing delete on the column | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10514 | No error when create table with encrypted column for the unsupported data types | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10515 | Run time error when decrypt 1 million rows | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10518 | create foreign table with encrypted column with no error | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10532 | Get Read time out error when try to read avro to wrong ddl (Frozen client) | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10534 | Wrong error message when copy null values from avro file to not null ddl (Overflow case instead null to not null) | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10551 | No error when add encrypt column to already existing table | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10585 | [V1] ORC Numeric reading - Overflow error | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10586 | SQream crashed when encrypt 1 billion rows | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10593 | Seg fault when inserting AVRO non-decimal value to Numeric type | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10594 | Some of configuration flags are displaced in default config | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10613 | Samsung test fail on branch v2022.1_stable | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10629 | Different join type between SELECT (Left) vs INSERT INTO SELECT (Left cross) | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10631 | Performance degradation - copies - copy_nvarchar40.sql - case #4556 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10632 | Performance degradation - insert_as_select - insert_as_select_parquet_int.sql - case #4971 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10655 | Performance degradation- some queries that perform COPY FROM - case #4624 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10656 | Performance degradation - insert_as_select - #4971 & #4984 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10659 | [SDC] Compile Error when using comment | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10665 | AWS V2 - Files are not deleted from S3 storage after DROP database and DROP table | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10667 | Log file not created when execute copy from avro | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10677 | Different results between subquery and physical table | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10692 | Internal Runtime Error when decrypt 1 million rows of text data type | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10695 | when ingest 100 million data into table with 3 encrypted column it took time more than expected | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10716 | Error on copy from avro (Expected auto cast) | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10734 | nvarchar_backward_comp1 failed in regression on branch v2022.1_stable | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10735 | numeric_upgrade_storage has failed in regression on v2022.1_stable | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10738 | Sqream worker on GPU id 1 consume also from GPU id 0 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10745 | compiler_tests failed in regression on v2022.1_stable | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10776 | Out Of Memory invoked during copy from with multiple files | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10813 | Copy To - The statement doesn't working when I use with 'Avro' format for location='s3....' | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10823 | window_functions_part1 failed in regression in develop | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10855 | CLONE - UF - list all files related to chunk id, Get specific chunk key values | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10869 | Enable/Disable encryption by default | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10871 | Copy To - Getting an error when missing file_name in the end of the path at the location field(This happen only at Avro format) | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10877 | Avro not implemented on stable version v2022 s3 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10885 | Filter on Delete - should be tested | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10889 | v2022.1_stable => Internal compiler error: Bad encryption type | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10895 | [AIS] behavior is not consistent when the user using Literals with Thai varchar WIN-874 or Thai text UTF-8 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10902 | test_copy_null_to_not_null[all_types-parquet] (from Generic Copy From) crashes sqreamd | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10916 | [AIS] varcharEncoding": "WINDOWS-874" Flag should work NOT ONLY in Developer mode | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10938 | REGEXP_REPLACE is not supported in 2022 version | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10962 | Using Thai Literals on v2022 with Text type output shows bad results ONLY ON Clientcmd | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10987 | [AIS] The system not allowing to control the update permissions - Grant update permission | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10999 | File tracker error logs on Sqream with MD - insert & select queries | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11043 | correlated_subqueries_v1 test failed | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11063 | Migration of Varchar to Text - keep the size of Varchar after the migration to the text type. | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11101 | Show locks test failed in regression for v2022.1 | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11109 | User can't change his own password using the UI | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11168 | Migration script on 1B rows table and 8 columns output with Internal run time error. | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11170 | Create a tool for migrating a Varchar table to Text | ++------------+-------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes -------- diff --git a/releases/index.rst b/releases/index.rst index 17fdbb529..d07b22632 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -5,21 +5,21 @@ Release Notes ********** SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -+---------------------------------+----------------------------------+------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2022.1<2022.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.23<2021.2.1.23>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.2<2020.2>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.1<2020.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ ++---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ +| :ref:`2022.1<2022.1>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ +| :ref:`2020.2<2020.2>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ +| :ref:`2020.1<2020.1>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ From c9207316e925b96f08bfbe0ac8cd483c97546038 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Fri, 15 Jul 2022 16:41:58 +0300 Subject: [PATCH 0115/1892] Started adding all patches --- releases/2021.1.1.1.rst | 32 +++++++++++++++++++++++++++++++ releases/2021.1_index.rst | 11 ++++++----- releases/2021.2.0.1.rst | 40 +++++++++++++++++++++++++++++++++++++++ releases/2021.2.1.24.rst | 26 +++++++++++++++++++++++++ releases/2021.2.1.25.rst | 26 +++++++++++++++++++++++++ releases/index.rst | 31 +++++++++++++++--------------- 6 files changed, 145 insertions(+), 21 deletions(-) create mode 100644 releases/2021.1.1.1.rst create mode 100644 releases/2021.2.0.1.rst create mode 100644 releases/2021.2.1.24.rst create mode 100644 releases/2021.2.1.25.rst diff --git a/releases/2021.1.1.1.rst b/releases/2021.1.1.1.rst new file mode 100644 index 000000000..2e562c858 --- /dev/null +++ b/releases/2021.1.1.1.rst @@ -0,0 +1,32 @@ +.. _2021.1.1.1: + +************************** +Release Notes 2021.1.1.1 +************************** +The 2021.1.1.1 release notes is a patch version released on 27/6/2022. + +The following table lists the issues that were resolved in Version 2021.1.1.1: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-7045 + - Replace function doesn't support column value + * - SQ-7640 + - Some dates can't be recognized as a standard date format + * - SQ-7658 + - Can't perform "=" function between varchar(1) and text argument + * - SQ-7588 + - A thread that removes stuck open snapshots + +Version 2021.1.1.1 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.1.1.1 \ No newline at end of file diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst index 5ba66f511..0e9960d99 100644 --- a/releases/2021.1_index.rst +++ b/releases/2021.1_index.rst @@ -5,11 +5,11 @@ Release Notes 2021.1 ************************** SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -+---------------------------------+----------------------------------+------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ ++---------------------------------+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.24<2021.2.1.24>` | :ref:`2021.2.1.25<2021.2.1.25>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ .. toctree:: :maxdepth: 2 @@ -18,4 +18,5 @@ SQream releases notes are specific to each version of the application. Select yo 2021.1 2021.1.1 + 2021.1.1.1 2021.1.2 \ No newline at end of file diff --git a/releases/2021.2.0.1.rst b/releases/2021.2.0.1.rst new file mode 100644 index 000000000..41cbd96d3 --- /dev/null +++ b/releases/2021.2.0.1.rst @@ -0,0 +1,40 @@ +.. _2021.2.0.1: + +************************** +Release Notes 2021.2.0.1 +************************** +The 2021.2.0.1 release notes were released on x/x/xxxx and describe the following: + +The following table lists the issues that were resolved in Version 2021.2.0.1: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-8345 + - Studio-How does a publicUser connect to a specified service? + * - SQ-8343 + - Running SQream from docker does not show configuration extended info + * - SQ-8294 + - Quote qualifier is not present in exported file thus file cannot be reloaded + * - SQ-8288 + - Support parameter TEXT casts + * - SQ-8272 + - `cleanup_chunk` creates garbage metadata, potentially leading to wrong results + * - SQ-8271 + - Saved query parameters of type text are not supported + * - SQ-8266 + - [LGE] Data loading issue depending to column order. // bad syntax (datetime type) + * - SQ-8266 + - [LGE] Data loading issue depending to column order. // bad syntax (datetime type) + +Version 2021.2.0.1 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.0.1 \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst new file mode 100644 index 000000000..8f0f9d26b --- /dev/null +++ b/releases/2021.2.1.24.rst @@ -0,0 +1,26 @@ +.. _2021.2.1.24: + +****************************** +Release Notes 2021.2.1.24 +****************************** +The 2021.2.1.24 release notes is a patch version released on xxxxxxxxxxxx. + +The following table lists the issues that were resolved in Version 2021.2.1.24.rst: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-xxxxx + - Description + +Version 2021.2.1.24 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.24 \ No newline at end of file diff --git a/releases/2021.2.1.25.rst b/releases/2021.2.1.25.rst new file mode 100644 index 000000000..6b6e1db03 --- /dev/null +++ b/releases/2021.2.1.25.rst @@ -0,0 +1,26 @@ +.. _2021.2.1.25: + +****************************** +Release Notes 2021.2.1.25 +****************************** +The 2021.2.1.25 release notes is a patch version released on xxxxxxxxxxxx. + +The following table lists the issues that were resolved in Version 2021.2.1.25.rst: + +.. list-table:: + :widths: 17 200 + :header-rows: 1 + + * - SQ No. + - Description + * - SQ-xxxxx + - Description + +Version 2021.2.1.25 has no unresolved issues. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.25 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index d07b22632..8f8933ce4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -5,22 +5,21 @@ Release Notes ********** SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -+---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ -| :ref:`2022.1<2022.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ -| :ref:`2020.2<2020.2>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ -| :ref:`2020.1<2020.1>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+ - ++---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| :ref:`2022.1<2022.1>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.24<2021.2.1.24>` | :ref:`2021.2.1.25<2021.2.1.25>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | | | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ +| :ref:`2020.2<2020.2>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ +| :ref:`2020.1<2020.1>` | ++---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ From 1b201a083e4358af66d7a53d034424e104a74158 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 18 Jul 2022 13:08:45 +0300 Subject: [PATCH 0116/1892] Preparing for 2022.1 Built table for all minor patches (2022.1, 2021.1, and 2021.2) --- releases/2021.1_index.rst | 4 +- releases/2021.2.0.1.rst | 2 +- releases/2021.2.1.1.rst | 2 +- releases/2021.2.1.22.rst | 8 ++-- releases/2021.2.1.24.rst | 47 ++++++++++++++++++++---- releases/2021.2.1.25.rst | 26 ------------- releases/2021.2_index.rst | 12 +++--- releases/2022.1.1.rst | 77 +++++++++++++++++++++++++++++++++++++++ releases/2022.1_index.rst | 15 ++++---- releases/index.rst | 41 +++++++++++---------- 10 files changed, 161 insertions(+), 73 deletions(-) delete mode 100644 releases/2021.2.1.25.rst create mode 100644 releases/2022.1.1.rst diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst index 0e9960d99..0fa9d6ccf 100644 --- a/releases/2021.1_index.rst +++ b/releases/2021.1_index.rst @@ -8,8 +8,8 @@ SQream releases notes are specific to each version of the application. Select yo +---------------------------------+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Major Release** | **Minor Releases** | +---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.24<2021.2.1.24>` | :ref:`2021.2.1.25<2021.2.1.25>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ .. toctree:: :maxdepth: 2 diff --git a/releases/2021.2.0.1.rst b/releases/2021.2.0.1.rst index 41cbd96d3..03edcad4e 100644 --- a/releases/2021.2.0.1.rst +++ b/releases/2021.2.0.1.rst @@ -33,7 +33,7 @@ The following table lists the issues that were resolved in Version 2021.2.0.1: Version 2021.2.0.1 has no unresolved issues. .. toctree:: - :maxdepth: 2 + :maxdepth: 3 :glob: :hidden: diff --git a/releases/2021.2.1.1.rst b/releases/2021.2.1.1.rst index a1137e418..65cf1b8a1 100644 --- a/releases/2021.2.1.1.rst +++ b/releases/2021.2.1.1.rst @@ -21,7 +21,7 @@ The following table lists the issues that were resolved in Version 2021.2.1.1: Version 2021.2.1.1 has no unresolved issues. .. toctree:: - :maxdepth: 2 + :maxdepth: 3 :glob: :hidden: diff --git a/releases/2021.2.1.22.rst b/releases/2021.2.1.22.rst index 029ad0178..62346a3c8 100644 --- a/releases/2021.2.1.22.rst +++ b/releases/2021.2.1.22.rst @@ -3,9 +3,9 @@ ****************************** Release Notes 2021.2.1.22 ****************************** -The 2021.2.1.22 release notes is a patch version released on 27/6/2022. +The 2021.2.1.22 release notes is a patch version released on 13/6/2022. -The following table lists the issues that were resolved in Version 2021.2.1.23: +The following table lists the issues that were resolved in Version 2021.2.1.22: .. list-table:: :widths: 17 200 @@ -16,10 +16,10 @@ The following table lists the issues that were resolved in Version 2021.2.1.23: * - SQ-10776 - Out Of Memory invoked during copy from with multiple files. -Version 2021.2.1.23 has no unresolved issues. +Version 2021.2.1.22 has no unresolved issues. .. toctree:: - :maxdepth: 2 + :maxdepth: 4 :glob: :hidden: diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 8f0f9d26b..cf4a2f391 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -7,14 +7,45 @@ The 2021.2.1.24 release notes is a patch version released on xxxxxxxxxxxx. The following table lists the issues that were resolved in Version 2021.2.1.24.rst: -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-xxxxx - - Description ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+==================================================================================================================================+ +| SQ-9721 | pysqream - not finishing query | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10071 | error on exists subqueries with text and varchar equality condition | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10606 | [ACL] Queries getting stuck in the queue for a long time (Executing status) | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10691 | DB Schema identifier causes an error running some queries from joins suite - v2021.2.1_stable | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10843 | When getting "illegal memory access was encountered" error message worker does not crash, but fails every query afterwards. | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10879 | Performance | degradations in insert as select from ORC files | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10902 | test_copy_null_to_not_null[all_types-parquet] (from Generic Copy From) crashes sqreamd | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10918 | [SDC] WLM only assings jobs sequentially and it causes delay on user sqls when they are assigned to a worker running a huge job | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10955 | No metadata filters when filtering by nullable date using dateadd (LGU+) | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10963 | Extract File Reaper Mechanism To Separated Process | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10975 | Merging ACL's open snapshot functionality from V2021.1.1 to V2021.2.1.x | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10976 | Merging all V2021.1.X fixes/features to V2021.2&V2022.1.X | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11000 | DROP DATABASE fails to remove database path under sqreamdb and following creation commands is stuck | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11043 | correlated_subqueries_v1 test failed | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11055 | performance degradation - tpch10t - cases #1299, #1315, #1307 & #1297 | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11088 | specific worker compiling causes low performance | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11090 | SQream keeps the configuration flags where the query compiled and use it when the query is executed on a different worker | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11159 | Redesign the heartbeat timers, worker and metadata. | ++-------------+----------------------------------------------------------------------------------------------------------------------------------+ Version 2021.2.1.24 has no unresolved issues. diff --git a/releases/2021.2.1.25.rst b/releases/2021.2.1.25.rst deleted file mode 100644 index 6b6e1db03..000000000 --- a/releases/2021.2.1.25.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _2021.2.1.25: - -****************************** -Release Notes 2021.2.1.25 -****************************** -The 2021.2.1.25 release notes is a patch version released on xxxxxxxxxxxx. - -The following table lists the issues that were resolved in Version 2021.2.1.25.rst: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-xxxxx - - Description - -Version 2021.2.1.25 has no unresolved issues. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2.1.25 \ No newline at end of file diff --git a/releases/2021.2_index.rst b/releases/2021.2_index.rst index 6e207ee73..98a256bc2 100644 --- a/releases/2021.2_index.rst +++ b/releases/2021.2_index.rst @@ -5,11 +5,11 @@ Release Notes 2021.2 ************************** SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -+---------------------------------+---------------------------------+------------------------------------------------------------------+ -| **Major Release** | **Minor Release** | -+---------------------------------+---------------------------------+--------------------------------+---------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.23<2021.2.1.23>` | -+---------------------------------+---------------------------------+--------------------------------+---------------------------------+ ++---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | ++---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ .. toctree:: :maxdepth: 2 @@ -17,6 +17,8 @@ SQream releases notes are specific to each version of the application. Select yo :hidden: 2021.2 + 2021.2.0.1 2021.2.1 2021.2.1.1 + 2021.2.1.22 2021.2.1.23 \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst new file mode 100644 index 000000000..081d608f2 --- /dev/null +++ b/releases/2022.1.1.rst @@ -0,0 +1,77 @@ +.. _2022.1.1: + +************************** +Release Notes 2022.1.1 +************************** +The 2022.1.1 release notes were released on x/x/xxxx and describe the following: + +The following table lists the issues that were resolved in Version 2022.1.1: + ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+==================================================================================================================================================+ +| SQ-6419 | Internal compiler error when casting numeric literal in aggregation function | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-9771 | The error returns different value when trying to insert date value without quotes. | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10100 | Implicit/Explicit cast from int/tinyint/bigint to bool is not working | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10741 | Got difference in execution time when ingesting data | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10772 | Internal Runtime Error when creating a text column with a limit characters size >= 1 and 30 zeros | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10790 | copy from with '*' (wildcard) from parquet is 3X slower than CSV | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10793 | Implement "Brute Force" Protection policy for the system login | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10816 | Data management on Big Table | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10838 | Repeat function throws an exception when entered a negative number | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10840 | UF - list all files related to chunk id, Get specific chunk key values | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10852 | Password Strength Check | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10863 | Performance | LGU | high SD in the duration of 'insert as select' query | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10873 | Inserting 100K bytes to a text column results in unclear error message | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10886 | Error in compilation process: : "Internal compiler error: | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10892 | Update || change error message when trying to run update on foreign table | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10899 | Cannot change the value of diskSpaceMinFreePercent - it is hard coded to 10% | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10919 | Automatic Foreign Table DDL Resolution | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10955 | No metadata filters when filtering by nullable date using dateadd (LGU+) | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10956 | Exception: "Could not read view.." - recompile and recreate doesn't help | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10963 | Extract File Reaper Mechanism To Separated Process | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10976 | Merging all V2021.1.X fixes/features to V2021.2&V2022.1.X | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10980 | sqream crashing when executing copy from avro (negative case copy file to unmatched column table) | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10988 | [SDC] stop_statement() doesn't work on jobs in queue | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11014 | Different float values between sqream and postgress | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11121 | Merging ACL's open snapshot functionality from V2021.1.1 to v2022.1.x code line | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11137 | CLONE - When getting "illegal memory access was encountered" error message worker does not crash, but fails every query afterwards. - AUTOMATIC | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11154 | After SQ-10980 fix, there is wrong error raised ("OVERFLOW exception") instead of "Tried inserting AVRO non-decimal" | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11158 | [ACL] Datediff doesn't work with specific dates - returns "Cast overflow" | ++-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ + +Version 2022.1.1 has no unresolved issues. + +.. toctree:: + :maxdepth: 3 + :glob: + :hidden: + + 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index c40867102..6393d5511 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -3,17 +3,18 @@ ************************** Release Notes 2022.1 ************************** -The 2022.1 Release Notes describe the following releases: +The 2022.1 Release Notes describe the following releases: -+---------------------------------+----------------------------------+------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2022.1<2022.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ ++---------------------------------+----------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+----------------------------------+ +| :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | ++---------------------------------+----------------------------------+ .. toctree:: :maxdepth: 2 :glob: :hidden: - 2022.1 \ No newline at end of file + 2022.1 + 2022.1.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 8f8933ce4..5e442a689 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -3,26 +3,29 @@ ********** Release Notes ********** -SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. - -+---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| :ref:`2022.1<2022.1>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.24<2021.2.1.24>` | :ref:`2021.2.1.25<2021.2.1.25>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | | | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ -| :ref:`2020.2<2020.2>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ -| :ref:`2020.1<2020.1>` | -+---------------------------------+----------------------------------+--------------------------------+-------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+ - - +SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Major Release** | **Minor Releases** | ++---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ +|:ref:`2021.1<2021.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ +| | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------------+ +|:ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` |:ref:`2021.2.0.3<2021.2.0.3>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.14<2021.2.1.14>` | :ref:`2021.2.1.16<2021.2.1.16>` | :ref:`2021.2.1.17<2021.2.1.17>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ +| |:ref:`2021.2.1.18<2021.2.1.18>` |:ref:`2021.2.1.19<2021.2.1.19>` | :ref:`2021.2.1.20<2021.2.1.20>` | :ref:`2021.2.1.21<2021.2.1.21>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.8<2021.2.1.8>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ +| | :ref:`2021.2.1.18<2021.2.1.18>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+---------------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | ++---------------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`2020.2<2020.2>` | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`2020.1<2020.1>` | ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ .. toctree:: From bae359b04c2840434300804e2b38661379233f70 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 18 Jul 2022 13:56:07 +0300 Subject: [PATCH 0117/1892] Corrected patch order --- releases/index.rst | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 5e442a689..acb32e800 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -9,17 +9,17 @@ SQream releases notes are specific to each version of the application. Select yo | **Major Release** | **Minor Releases** | +---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ -|:ref:`2021.1<2021.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ -| | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------------+ -|:ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` |:ref:`2021.2.0.3<2021.2.0.3>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.14<2021.2.1.14>` | :ref:`2021.2.1.16<2021.2.1.16>` | :ref:`2021.2.1.17<2021.2.1.17>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ -| |:ref:`2021.2.1.18<2021.2.1.18>` |:ref:`2021.2.1.19<2021.2.1.19>` | :ref:`2021.2.1.20<2021.2.1.20>` | :ref:`2021.2.1.21<2021.2.1.21>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | :ref:`2021.2.1.8<2021.2.1.8>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+---------------------------------------+ -| | :ref:`2021.2.1.18<2021.2.1.18>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+---------------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------+ +| :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1.7<2021.1.1.7>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ +| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` |:ref:`2021.2.0.3<2021.2.0.3>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.14<2021.2.1.14>` | :ref:`2021.2.1.16<2021.2.1.16>` | :ref:`2021.2.1.17<2021.2.1.17>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ +| | :ref:`2021.2.1.18<2021.2.1.18>` |:ref:`2021.2.1.19<2021.2.1.19>` | :ref:`2021.2.1.20<2021.2.1.20>` | :ref:`2021.2.1.21<2021.2.1.21>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ +| | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.2.1.8<2021.2.1.8>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | +---------------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`2020.2<2020.2>` | @@ -28,6 +28,7 @@ SQream releases notes are specific to each version of the application. Select yo +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + .. toctree:: :maxdepth: 2 :glob: From 3d355271ccd72d072a0ff399065fe1c754eb28f3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 18 Jul 2022 14:11:49 +0300 Subject: [PATCH 0118/1892] Realignment --- releases/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index acb32e800..19f447988 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -9,10 +9,10 @@ SQream releases notes are specific to each version of the application. Select yo | **Major Release** | **Minor Releases** | +---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+-------------------------------------------------------------------------------------------------------+ -| :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1.7<2021.1.1.7>` | :ref:`2021.1.2<2021.1.2>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ +| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | ++---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ +| | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1.7<2021.1.1.7>` | :ref:`2021.1.2<2021.1.2>` | +---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ | :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` |:ref:`2021.2.0.3<2021.2.0.3>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.14<2021.2.1.14>` | :ref:`2021.2.1.16<2021.2.1.16>` | :ref:`2021.2.1.17<2021.2.1.17>` | +---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ From 9695e6d138e6c3f5d517307beba45ec9d9eb6b1e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 19 Jul 2022 12:23:36 +0300 Subject: [PATCH 0119/1892] Add files via upload From abfd0bd98937971597d518df78ef719d5953724e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 12:27:49 +0300 Subject: [PATCH 0120/1892] Documented External Bugs for 2022.1 Reverted to original index table structure. Will reimplement new index table structure after filtering between external/internal bugs for 2021.1 and 2021.2. Need to filter and re-implement patch for 2022.1.1. All removed files saved in local folder: C:\Users\Yaniv\Desktop\Yaniv\Release Notes\2022.1\releases_new_structure_with_patches --- .../get_extents_file_list_for_chunk.rst | 22 +- .../get_metadata_chunk_key.rst | 4 +- releases/2020.3_index.rst | 17 +- releases/2021.1.1.1.rst | 32 --- releases/2021.1.1.rst | 71 ------ releases/2021.1_index.rst | 18 +- releases/2021.2.0.1.rst | 40 ---- releases/2021.2.1.1.rst | 28 --- releases/2021.2.1.22.rst | 26 --- releases/2021.2.1.23.rst | 26 --- releases/2021.2.1.24.rst | 57 ----- releases/2021.2_index.rst | 19 +- releases/2022.1.1.rst | 77 ------ releases/2022.1.rst | 221 +++--------------- releases/2022.1_index.rst | 20 -- releases/index.rst | 44 ++-- 16 files changed, 78 insertions(+), 644 deletions(-) delete mode 100644 releases/2021.1.1.1.rst delete mode 100644 releases/2021.1.1.rst delete mode 100644 releases/2021.2.0.1.rst delete mode 100644 releases/2021.2.1.1.rst delete mode 100644 releases/2021.2.1.22.rst delete mode 100644 releases/2021.2.1.23.rst delete mode 100644 releases/2021.2.1.24.rst delete mode 100644 releases/2022.1.1.rst delete mode 100644 releases/2022.1_index.rst diff --git a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst index 3c05a48fe..968c0655a 100644 --- a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst +++ b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst @@ -53,8 +53,6 @@ Output ========== The following table describes the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: -Database name. table name, table id, column id, chunk id, file path - .. list-table:: :widths: 25 25 25 25 :header-rows: 1 @@ -81,31 +79,29 @@ Database name. table name, table id, column id, chunk id, file path * - ``column_id`` - The status of the chunk. - - **Comment** - *What is the type?* + - Numeric - ``1`` * - ``chunk_id`` - Describes the state of the chunk. - - **Comment** - *What is the type?* + - Numeric - ``chunk_state::`` * - ``file_path`` - Shows the path of the file. - Text - - **Comment** - *Provide example + - /home/sqream_testing_temp/sqreamdb/databases/master/tables The following is an example of the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: .. code-block:: postgres - master,public.t_1,0,0,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/0/0-2 - master,public.t_1,0,1,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/1/1-2 - master,public.t_1,0,2,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/2/2-2 - master,public.t_1,0,3,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/3/3-2 - master,public.t_1,0,4,3,/home/eyalw/sqream_testing_temp/sqreamdb/databases/master/tables/0/4/4-2 + master,public.t_1,0,0,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables + master,public.t_1,0,1,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables + master,public.t_1,0,2,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables + master,public.t_1,0,3,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables + master,public.t_1,0,4,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables Permissions ============= -The ``GET_EXTENTS_FILE_FOR_CHUNK`` requires no special permissions. - -**Comment** - *Does it require any special permissions?* \ No newline at end of file +The ``GET_EXTENTS_FILE_FOR_CHUNK`` requires no special permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst index c43775de7..9c69d423f 100644 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -148,6 +148,4 @@ The following is an example of the output generated from the ``GET_METADATA_CHUN Permissions ============= -The ``GET_METADATA_CHUNK_KEY`` requires no special permissions. - -**Comment** - *Does it require any special permissions?* \ No newline at end of file +The ``GET_METADATA_CHUNK_KEY`` requires no special permissions. \ No newline at end of file diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst index 19bf3bd79..b13340b52 100644 --- a/releases/2020.3_index.rst +++ b/releases/2020.3_index.rst @@ -3,19 +3,16 @@ ************************** Release Notes 2020.3 ************************** -SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. +The 2020.3 Release Notes describe the following releases: -+---------------------------------+----------------------------------+------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+ +.. contents:: + :local: + :depth: 1 .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: - :hidden: - 2020.3 + 2020.3.2.1 2020.3.1 - 2020.3.2.1 \ No newline at end of file + 2020.3 \ No newline at end of file diff --git a/releases/2021.1.1.1.rst b/releases/2021.1.1.1.rst deleted file mode 100644 index 2e562c858..000000000 --- a/releases/2021.1.1.1.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _2021.1.1.1: - -************************** -Release Notes 2021.1.1.1 -************************** -The 2021.1.1.1 release notes is a patch version released on 27/6/2022. - -The following table lists the issues that were resolved in Version 2021.1.1.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-7045 - - Replace function doesn't support column value - * - SQ-7640 - - Some dates can't be recognized as a standard date format - * - SQ-7658 - - Can't perform "=" function between varchar(1) and text argument - * - SQ-7588 - - A thread that removes stuck open snapshots - -Version 2021.1.1.1 has no unresolved issues. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.1.1.1 \ No newline at end of file diff --git a/releases/2021.1.1.rst b/releases/2021.1.1.rst deleted file mode 100644 index 992b2f850..000000000 --- a/releases/2021.1.1.rst +++ /dev/null @@ -1,71 +0,0 @@ -.. _2021.1.1: - -************************** -Release Notes 2021.1.1 -************************** -The 2021.1.1 release notes were released on 7/27/2021 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features -------------- -The 2021.1.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Complete Ranking Function Support -************ -SQream now supports the following new ranking functions: - -.. list-table:: - :widths: 1 23 76 - :header-rows: 1 - - * - Function - - Return Type - - Description - * - first_value - - Same type as value - - Returns the value in the first row of a window. - * - last_value - - Same type as value - - Returns the value in the last row of a window. - * - nth_value - - Same type as value - - Returns the value in a specified (``n``) row of a window. if the specified row does not exist, this function returns ``NULL``. - * - dense_rank - - bigint - - Returns the rank of the current row with no gaps. - * - percent_rank - - double - - Returns the relative rank of the current row. - * - cume_dist - - double - - Returns the cumulative distribution of rows. - * - ntile(buckets) - - integer - - Returns an integer ranging between ``1`` and the argument value, dividing the partitions as equally as possible. - -For more information, navigate to Windows Functions and scroll to the `Ranking Functions table `_. - - -Resolved Issues -------------- -The following list describes the resolved issues: - -* SQream did not support exporting and reading **Int64** columns as **bigint** in Parquet. This was fixed. -* The Decimal column was not supported when inserting data from Parquet files. This was fixed. -* Values in Parquet Numeric columns were not being converted correctly. This was fixed. -* Converting ``string`` data type to ``datetime`` was not working correctly. This was fixed. -* Casting ``datetime`` to ``text`` truncated the time. This was fixed. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.1.1 \ No newline at end of file diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst index 0fa9d6ccf..64b06e1d1 100644 --- a/releases/2021.1_index.rst +++ b/releases/2021.1_index.rst @@ -3,20 +3,16 @@ ************************** Release Notes 2021.1 ************************** -SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. +The 2021.1 Release Notes describe the following releases: -+---------------------------------+----------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ +.. contents:: + :local: + :depth: 1 .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: - :hidden: - 2021.1 + 2021.1.2 2021.1.1 - 2021.1.1.1 - 2021.1.2 \ No newline at end of file + 2021.1 \ No newline at end of file diff --git a/releases/2021.2.0.1.rst b/releases/2021.2.0.1.rst deleted file mode 100644 index 03edcad4e..000000000 --- a/releases/2021.2.0.1.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. _2021.2.0.1: - -************************** -Release Notes 2021.2.0.1 -************************** -The 2021.2.0.1 release notes were released on x/x/xxxx and describe the following: - -The following table lists the issues that were resolved in Version 2021.2.0.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-8345 - - Studio-How does a publicUser connect to a specified service? - * - SQ-8343 - - Running SQream from docker does not show configuration extended info - * - SQ-8294 - - Quote qualifier is not present in exported file thus file cannot be reloaded - * - SQ-8288 - - Support parameter TEXT casts - * - SQ-8272 - - `cleanup_chunk` creates garbage metadata, potentially leading to wrong results - * - SQ-8271 - - Saved query parameters of type text are not supported - * - SQ-8266 - - [LGE] Data loading issue depending to column order. // bad syntax (datetime type) - * - SQ-8266 - - [LGE] Data loading issue depending to column order. // bad syntax (datetime type) - -Version 2021.2.0.1 has no unresolved issues. - -.. toctree:: - :maxdepth: 3 - :glob: - :hidden: - - 2021.2.0.1 \ No newline at end of file diff --git a/releases/2021.2.1.1.rst b/releases/2021.2.1.1.rst deleted file mode 100644 index 65cf1b8a1..000000000 --- a/releases/2021.2.1.1.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _2021.2.1.1: - -****************************** -Release Notes 2021.2.1.1 -****************************** -The 2021.2.1.1 release notes is a patch version released on 9/12/2021. - -The following table lists the issues that were resolved in Version 2021.2.1.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-9114 - - `cleanup_extents` on empty texts results in a missing file - * - SQ-8849 - - `Unclear "Map:at" error for invalid column mapping of Parquet files - -Version 2021.2.1.1 has no unresolved issues. - -.. toctree:: - :maxdepth: 3 - :glob: - :hidden: - - 2021.2.1.1 \ No newline at end of file diff --git a/releases/2021.2.1.22.rst b/releases/2021.2.1.22.rst deleted file mode 100644 index 62346a3c8..000000000 --- a/releases/2021.2.1.22.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _2021.2.1.22: - -****************************** -Release Notes 2021.2.1.22 -****************************** -The 2021.2.1.22 release notes is a patch version released on 13/6/2022. - -The following table lists the issues that were resolved in Version 2021.2.1.22: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-10776 - - Out Of Memory invoked during copy from with multiple files. - -Version 2021.2.1.22 has no unresolved issues. - -.. toctree:: - :maxdepth: 4 - :glob: - :hidden: - - 2021.2.1.22 \ No newline at end of file diff --git a/releases/2021.2.1.23.rst b/releases/2021.2.1.23.rst deleted file mode 100644 index ca5e2dcbe..000000000 --- a/releases/2021.2.1.23.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _2021.2.1.23: - -****************************** -Release Notes 2021.2.1.23 -****************************** -The 2021.2.1.23 release notes is a patch version released on 27/6/2022. - -The following table lists the issues that were resolved in Version 2021.2.1.23: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-10703 - - When the clause is specified, all existing permissions granted on source_table_name are granted on table_name as well. - -Version 2021.2.1.23 has no unresolved issues. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2.1.23 \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst deleted file mode 100644 index cf4a2f391..000000000 --- a/releases/2021.2.1.24.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. _2021.2.1.24: - -****************************** -Release Notes 2021.2.1.24 -****************************** -The 2021.2.1.24 release notes is a patch version released on xxxxxxxxxxxx. - -The following table lists the issues that were resolved in Version 2021.2.1.24.rst: - -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+==================================================================================================================================+ -| SQ-9721 | pysqream - not finishing query | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10071 | error on exists subqueries with text and varchar equality condition | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10606 | [ACL] Queries getting stuck in the queue for a long time (Executing status) | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10691 | DB Schema identifier causes an error running some queries from joins suite - v2021.2.1_stable | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10843 | When getting "illegal memory access was encountered" error message worker does not crash, but fails every query afterwards. | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10879 | Performance | degradations in insert as select from ORC files | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10902 | test_copy_null_to_not_null[all_types-parquet] (from Generic Copy From) crashes sqreamd | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10918 | [SDC] WLM only assings jobs sequentially and it causes delay on user sqls when they are assigned to a worker running a huge job | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10955 | No metadata filters when filtering by nullable date using dateadd (LGU+) | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10963 | Extract File Reaper Mechanism To Separated Process | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10975 | Merging ACL's open snapshot functionality from V2021.1.1 to V2021.2.1.x | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10976 | Merging all V2021.1.X fixes/features to V2021.2&V2022.1.X | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11000 | DROP DATABASE fails to remove database path under sqreamdb and following creation commands is stuck | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11043 | correlated_subqueries_v1 test failed | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11055 | performance degradation - tpch10t - cases #1299, #1315, #1307 & #1297 | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11088 | specific worker compiling causes low performance | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11090 | SQream keeps the configuration flags where the query compiled and use it when the query is executed on a different worker | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11159 | Redesign the heartbeat timers, worker and metadata. | -+-------------+----------------------------------------------------------------------------------------------------------------------------------+ - -Version 2021.2.1.24 has no unresolved issues. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2.1.24 \ No newline at end of file diff --git a/releases/2021.2_index.rst b/releases/2021.2_index.rst index 98a256bc2..77a22b0ae 100644 --- a/releases/2021.2_index.rst +++ b/releases/2021.2_index.rst @@ -3,22 +3,15 @@ ************************** Release Notes 2021.2 ************************** -SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. +The 2021.2 Release Notes describe the following releases: -+---------------------------------+----------------------------------+----------------------------------------------------------------------------------------------------+---------------------------------+---------------------------------+----------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+------------------------------------------------------------------------------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.1<2021.2.1.1>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | -+---------------------------------+----------------------------------+--------------------------------+---------------------------------+---------------------------------+---------------------------------+---------------------------------+----------------------------------+ +.. contents:: + :local: + :depth: 1 .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: - :hidden: - 2021.2 - 2021.2.0.1 2021.2.1 - 2021.2.1.1 - 2021.2.1.22 - 2021.2.1.23 \ No newline at end of file + 2021.2 \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst deleted file mode 100644 index 081d608f2..000000000 --- a/releases/2022.1.1.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. _2022.1.1: - -************************** -Release Notes 2022.1.1 -************************** -The 2022.1.1 release notes were released on x/x/xxxx and describe the following: - -The following table lists the issues that were resolved in Version 2022.1.1: - -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+==================================================================================================================================================+ -| SQ-6419 | Internal compiler error when casting numeric literal in aggregation function | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9771 | The error returns different value when trying to insert date value without quotes. | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10100 | Implicit/Explicit cast from int/tinyint/bigint to bool is not working | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10741 | Got difference in execution time when ingesting data | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10772 | Internal Runtime Error when creating a text column with a limit characters size >= 1 and 30 zeros | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10790 | copy from with '*' (wildcard) from parquet is 3X slower than CSV | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10793 | Implement "Brute Force" Protection policy for the system login | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10816 | Data management on Big Table | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10838 | Repeat function throws an exception when entered a negative number | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10840 | UF - list all files related to chunk id, Get specific chunk key values | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10852 | Password Strength Check | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10863 | Performance | LGU | high SD in the duration of 'insert as select' query | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10873 | Inserting 100K bytes to a text column results in unclear error message | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10886 | Error in compilation process: : "Internal compiler error: | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10892 | Update || change error message when trying to run update on foreign table | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10899 | Cannot change the value of diskSpaceMinFreePercent - it is hard coded to 10% | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10919 | Automatic Foreign Table DDL Resolution | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10955 | No metadata filters when filtering by nullable date using dateadd (LGU+) | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10956 | Exception: "Could not read view.." - recompile and recreate doesn't help | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10963 | Extract File Reaper Mechanism To Separated Process | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10976 | Merging all V2021.1.X fixes/features to V2021.2&V2022.1.X | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10980 | sqream crashing when executing copy from avro (negative case copy file to unmatched column table) | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10988 | [SDC] stop_statement() doesn't work on jobs in queue | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11014 | Different float values between sqream and postgress | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11121 | Merging ACL's open snapshot functionality from V2021.1.1 to v2022.1.x code line | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11137 | CLONE - When getting "illegal memory access was encountered" error message worker does not crash, but fails every query afterwards. - AUTOMATIC | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11154 | After SQ-10980 fix, there is wrong error raised ("OVERFLOW exception") instead of "Tried inserting AVRO non-decimal" | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11158 | [ACL] Datediff doesn't work with specific dates - returns "Cast overflow" | -+-------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ - -Version 2022.1.1 has no unresolved issues. - -.. toctree:: - :maxdepth: 3 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 74e568fad..b6ffdf9ef 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1 ************************** -The 2022.1 release notes were released on x/xx/2022 and describe the following: +The 2022.1 release notes were released on 7/19/2022 and describe the following: .. contents:: :local: @@ -56,191 +56,35 @@ The following two new utility commands have been created: * `GET_METADATA_CHUNK_KEY `_ - returns specific metadata key values for user-specified chunks. +Known Issues +--------- +The following table lists the known issues for Version 2022.1: + ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10071 | error on exists subqueries with text and varchar equality condition | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10629 | Inserting data into a table significantly slowed down running queries. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10659 | Using a comment generated a compile error. | ++-------------+-------------------------------------------------------------------------------------------+ + Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1: -**Comment** - *The items in the table below must be filtered according to external and internal bugs. We CANNOT expose internal bugs to external users.* - -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-7490 | Native Avro file access via a dedicated FDW | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-7718 | Certify LTS Ubuntu versions (18.04 & 20.04) for production usage | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-7732 | Fail to read numeric columns from an external generated parquet file | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-8163 | Performance degradation - tpch1t_external_table_parquet - cases #6079 & #6105 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-8182 | Encryption Function | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-8984 | Update statement MVP: literal assignment | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9221 | [Mobicom] PBI - External Tables are not shown on the tables list. | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9611 | Create a WIN-874 to UTF-8 conversion function | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9634 | identifier not found | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9644 | [ACL] Incomplete logs query causing Internal Runtime Error | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9671 | Trying to read Thai UTF-8 csv file in TEXT column and it not shows Thai | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9764 | No error when create a foreign table with difference in the column numbers in the table and the file | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9790 | Encryption - MVP scope | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9808 | Allowing to set deferredValueIOThresholdFactor flag not in developer Mode=true | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9823 | [AIS] The user can't use literals when using sqream with Thai varchar | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9889 | [AIS] Internal runtime Error receive | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9952 | Removing temp files takes too long - timeout issue at LGU+ | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9988 | Find a proper solution for data lost during copy from parquet - without reverting previous optimization | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-9990 | Merge v2021.2.1_stable into develop | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10005 | Go / No Go approvals | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10011 | Delete filter optimization chicken flag | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10055 | [SamsungDisplay] Slow loading of sqream after backup compacting | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10061 | compiler side - Implement MVP scope | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10071 | error on exists subqueries with text and varchar equality condition | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10111 | Parquet numeric - Sqream can't import parquet numeric columns from other sources | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10191 | [LGE] ALTER DEFAULT SCHEMA command has a problem. | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10216 | Performance degradation - tpch1t_1mchunk - case #1326 #1345 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10242 | socket 11 error from "Create as Select~" | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10269 | cleanup_chunk error with text(X) column | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10314 | Unable to load avro file to sqream v1 + v2 from s3 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10319 | Error on copy from avro file with numeric data | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10425 | Lot of time in copy from, external table parquet file | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10428 | [LGU] Can not execute cleanup_extents on table because there are mixed chunks | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10470 | count distinct on 0 rows doesn't return any value | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10478 | get_ddl disregards encrypted columns | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10479 | create a table with more than three encrypted column with no error | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10492 | Wrong values when select from table have encrypted column and regular column | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10494 | No “encrypted” label when read from table with encrypted column | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10496 | Not able to insert data to encrypted column after performing delete on the column | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10514 | No error when create table with encrypted column for the unsupported data types | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10515 | Run time error when decrypt 1 million rows | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10518 | create foreign table with encrypted column with no error | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10532 | Get Read time out error when try to read avro to wrong ddl (Frozen client) | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10534 | Wrong error message when copy null values from avro file to not null ddl (Overflow case instead null to not null) | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10551 | No error when add encrypt column to already existing table | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10585 | [V1] ORC Numeric reading - Overflow error | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10586 | SQream crashed when encrypt 1 billion rows | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10593 | Seg fault when inserting AVRO non-decimal value to Numeric type | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10594 | Some of configuration flags are displaced in default config | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10613 | Samsung test fail on branch v2022.1_stable | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10629 | Different join type between SELECT (Left) vs INSERT INTO SELECT (Left cross) | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10631 | Performance degradation - copies - copy_nvarchar40.sql - case #4556 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10632 | Performance degradation - insert_as_select - insert_as_select_parquet_int.sql - case #4971 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10655 | Performance degradation- some queries that perform COPY FROM - case #4624 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10656 | Performance degradation - insert_as_select - #4971 & #4984 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10659 | [SDC] Compile Error when using comment | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10665 | AWS V2 - Files are not deleted from S3 storage after DROP database and DROP table | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10667 | Log file not created when execute copy from avro | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10677 | Different results between subquery and physical table | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10692 | Internal Runtime Error when decrypt 1 million rows of text data type | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10695 | when ingest 100 million data into table with 3 encrypted column it took time more than expected | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10716 | Error on copy from avro (Expected auto cast) | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10734 | nvarchar_backward_comp1 failed in regression on branch v2022.1_stable | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10735 | numeric_upgrade_storage has failed in regression on v2022.1_stable | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10738 | Sqream worker on GPU id 1 consume also from GPU id 0 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10745 | compiler_tests failed in regression on v2022.1_stable | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10776 | Out Of Memory invoked during copy from with multiple files | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10813 | Copy To - The statement doesn't working when I use with 'Avro' format for location='s3....' | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10823 | window_functions_part1 failed in regression in develop | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10855 | CLONE - UF - list all files related to chunk id, Get specific chunk key values | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10869 | Enable/Disable encryption by default | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10871 | Copy To - Getting an error when missing file_name in the end of the path at the location field(This happen only at Avro format) | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10877 | Avro not implemented on stable version v2022 s3 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10885 | Filter on Delete - should be tested | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10889 | v2022.1_stable => Internal compiler error: Bad encryption type | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10895 | [AIS] behavior is not consistent when the user using Literals with Thai varchar WIN-874 or Thai text UTF-8 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10902 | test_copy_null_to_not_null[all_types-parquet] (from Generic Copy From) crashes sqreamd | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10916 | [AIS] varcharEncoding": "WINDOWS-874" Flag should work NOT ONLY in Developer mode | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10938 | REGEXP_REPLACE is not supported in 2022 version | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10962 | Using Thai Literals on v2022 with Text type output shows bad results ONLY ON Clientcmd | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10987 | [AIS] The system not allowing to control the update permissions - Grant update permission | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10999 | File tracker error logs on Sqream with MD - insert & select queries | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11043 | correlated_subqueries_v1 test failed | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11063 | Migration of Varchar to Text - keep the size of Varchar after the migration to the text type. | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11101 | Show locks test failed in regression for v2022.1 | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11109 | User can't change his own password using the UI | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11168 | Migration script on 1B rows table and 8 columns output with Internal run time error. | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11170 | Create a tool for migrating a Varchar table to Text | -+------------+-------------------------------------------------------------------------------------------------------------------------------------+ ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ Operations and Configuration Changes -------- @@ -256,20 +100,9 @@ In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and repla If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. -Known Issues and Limitations --------- -**Comment** - *TBD* - -The the list below describes the following known issues and limitations: - -* Text -* Text - End of Support ------- -**Comment** - *We need to know what to put here.* - -This section is not relevant to the 2022.1 release notes. +The End of Support section is not relevant to Version 2022.1. Upgrading to v2022.1 ------- diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst deleted file mode 100644 index 6393d5511..000000000 --- a/releases/2022.1_index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _2022.1_index: - -************************** -Release Notes 2022.1 -************************** -The 2022.1 Release Notes describe the following releases: - -+---------------------------------+----------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+----------------------------------+ -| :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | -+---------------------------------+----------------------------------+ - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1 - 2022.1.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 19f447988..b1d065a9e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -3,29 +3,27 @@ ********** Release Notes ********** -SQream releases notes are specific to each version of the application. Select your version from the table below to see the related release notes. -+---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Major Release** | **Minor Releases** | -+---------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`2022.1<2022.1>` | :ref:`2022.1.1<2022.1.1>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ -| :ref:`2021.1<2021.1>` | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1_rdb_1<2021.1.1_rdb_1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.1.1.11<2021.1.1.11>` | :ref:`2021.1.1.2<2021.1.1.2>` | :ref:`2021.1.1.3<2021.1.1.3>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ -| | :ref:`2021.1.1.4<2021.1.1.4>` | :ref:`2021.1.1.6<2021.1.1.6>` | :ref:`2021.1.1.7<2021.1.1.7>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ -| :ref:`2021.2<2021.2>` | :ref:`2021.2.0.1<2021.2.0.1>` |:ref:`2021.2.0.3<2021.2.0.3>` | :ref:`2021.2.1<2021.2.1>` | :ref:`2021.2.1.14<2021.2.1.14>` | :ref:`2021.2.1.16<2021.2.1.16>` | :ref:`2021.2.1.17<2021.2.1.17>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ -| | :ref:`2021.2.1.18<2021.2.1.18>` |:ref:`2021.2.1.19<2021.2.1.19>` | :ref:`2021.2.1.20<2021.2.1.20>` | :ref:`2021.2.1.21<2021.2.1.21>` | :ref:`2021.2.1.22<2021.2.1.22>` | :ref:`2021.2.1.23<2021.2.1.23>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+----------------------------------+----------------------------------+--------------------------------------------------------------------+ -| | :ref:`2021.1.1<2021.1.1>` | :ref:`2021.1.1.1<2021.1.1.1>` | :ref:`2021.2.1.8<2021.2.1.8>` | :ref:`2021.1.2<2021.1.2>` | -+---------------------------------+----------------------------------+---------------------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`2020.3<2020.3>` | :ref:`2020.3.1<2020.3.1>` | :ref:`2020.3.2.1<2020.3.2.1>` | -+---------------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`2020.2<2020.2>` | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`2020.1<2020.1>` | -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +.. list-table:: + :widths: auto + :header-rows: 1 + + + * - Version + - Release Date + * - :ref:`2022.1` + - July 19, 2022 + * - :ref:`2021.2` + - September 13, 2021 + * - :ref:`2021.1` + - June 13, 2021 + * - :ref:`2020.3` + - October 8, 2020 + * - :ref:`2020.2` + - July 22, 2020 + * - :ref:`2020.1` + - January 15, 2020 @@ -34,7 +32,7 @@ SQream releases notes are specific to each version of the application. Select yo :glob: :hidden: - 2022.1_index + 2022.1 2021.2_index 2021.1_index 2020.3_index From ce03a5ea5bb41dab92621fb5a335db6b0a4710b5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 14:02:36 +0300 Subject: [PATCH 0121/1892] Update get_metadata_chunk_key.rst --- .../utility_commands/get_metadata_chunk_key.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst index 9c69d423f..08eba8345 100644 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -78,12 +78,12 @@ The following table describes the output generated from the ``GET_METADATA_CHUNK * - ``chunk_status`` - The status of the chunk. - - **Comment** - *What is the type?* + - Numeric - ``1`` * - ``chunk_aligned`` - Describes the state of the chunk. - - **Comment** - *What is the type?* + - Text - ``chunk_state::`` * - ``offset_in_file`` From 74a04f3e7196aae9457c44457b182980602d953a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 17:24:35 +0300 Subject: [PATCH 0122/1892] Implementing SQ-10818 on live branch (testing) https://sqream.atlassian.net/browse/SQ-10818 If works correctly, will implement on all other live branches. --- reference/catalog_reference.rst | 610 +----------------- .../catalog_reference_additonal_tables.rst | 120 ++++ .../catalog_reference_catalog_tables.rst | 455 +++++++++++++ reference/catalog_reference_examples.rst | 64 ++ reference/catalog_reference_overview.rst | 11 + .../catalog_reference_schema_information.rst | 62 ++ .../alter_default_permissions.rst | 76 ++- 7 files changed, 782 insertions(+), 616 deletions(-) create mode 100644 reference/catalog_reference_additonal_tables.rst create mode 100644 reference/catalog_reference_catalog_tables.rst create mode 100644 reference/catalog_reference_examples.rst create mode 100644 reference/catalog_reference_overview.rst create mode 100644 reference/catalog_reference_schema_information.rst diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index 8cfa8e832..8fc0593b8 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -1,606 +1,16 @@ .. _catalog_reference: ************************************* -Catalog reference +Catalog Reference Guide ************************************* +The **Catalog Reference Guide** describes the following: -SQream DB contains a schema called ``sqream_catalog`` that contains information about your database's objects - tables, columns, views, permissions, and more. +.. toctree:: + :maxdepth: 1 + :glob: -Some additional catalog tables are used primarily for internal introspection, which could change across SQream DB versions. - - -.. contents:: In this topic: - :local: - -Types of data exposed by ``sqream_catalog`` -============================================== - -.. list-table:: Database objects - :widths: auto - :header-rows: 1 - - * - Object - - Table - * - Clustering keys - - ``clustering_keys`` - * - Columns - - ``columns``, ``external_table_columns`` - * - Databases - - ``databases`` - * - Permissions - - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions`` - * - Roles - - ``roles``, ``roles_memeberships`` - * - Schemas - - ``schemas`` - * - Sequences - - ``identity_key`` - * - Tables - - ``tables``, ``external_tables`` - * - Views - - ``views`` - * - UDFs - - ``user_defined_functions`` - -The catalog contains a few more tables which contain storage details for internal use - -.. list-table:: Storage objects - :widths: auto - :header-rows: 1 - - * - Object - - Table - * - Extents - - ``extents`` - * - Chunks - - ``chunks`` - * - Delete predicates - - ``delete_predicates`` - -Tables in the catalog -======================== - -clustering_keys ------------------------ - -Explicit clustering keys for tables. - -When more than one clustering key is defined, each key is listed in a separate row. - - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - ID of the table containing the column - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table containing the column - * - ``clustering_key`` - - Name of the column that is a clustering key for this table - -columns --------- - -Column objects for standard tables - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_id`` - - ID of the table containing the column - * - ``table_name`` - - Name of the table containing the column - * - ``column_id`` - - Ordinal of the column in the table (begins at 0) - * - ``column_name`` - - Name of the column - * - ``type_name`` - - :ref:`Data type ` of the column - * - ``column_size`` - - The maximum length in bytes. - * - ``has_default`` - - ``NULL`` if the column has no default value. ``1`` if the default is a fixed value, or ``2`` if the default is an :ref:`identity` - * - ``default_value`` - - :ref:`Default value` for the column - * - ``compression_strategy`` - - User-overridden compression strategy - * - ``created`` - - Timestamp when the column was created - * - ``altered`` - - Timestamp when the column was last altered - - -.. _external_tables_table: - -external_tables ----------------- - -``external_tables`` identifies external tables in the database. - -For ``TABLES`` see :ref:`tables ` - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - Database-unique ID for the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table - * - ``format`` - - - Identifies the foreign data wrapper used. - - ``0`` for csv_fdw, ``1`` for parquet_fdw, ``2`` for orc_fdw. - - * - ``created`` - - Identifies the clause used to create the table - -external_table_columns ------------------------- - -Column objects for external tables - -databases ------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_Id`` - - Unique ID of the database - * - ``database_name`` - - Name of the database - * - ``default_disk_chunk_size`` - - Internal use - * - ``default_process_chunk_size`` - - Internal use - * - ``rechunk_size`` - - Internal use - * - ``storage_subchunk_size`` - - Internal use - * - ``compression_chunk_size_threshold`` - - Internal use - -database_permissions ----------------------- - -``database_permissions`` identifies all permissions granted to databases. - -There is one row for each combination of role (grantee) and permission granted to a database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -identity_key --------------- - - -permission_types ------------------- - -``permission_types`` Identifies the permission names that exist in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``permission_type_id`` - - ID of the permission type - * - ``name`` - - Name of the permission type - -roles ------- - -``roles`` identifies the roles in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``role_id`` - - Database-unique ID of the role - * - ``name`` - - Name of the role - * - ``superuser`` - - Identifies if this role is a superuser. ``1`` for superuser or ``0`` otherwise. - * - ``login`` - - Identifies if this role can be used to log in to SQream DB. ``1`` for yes or ``0`` otherwise. - * - ``has_password`` - - Identifies if this role has a password. ``1`` for yes or ``0`` otherwise. - * - ``can_create_function`` - - Identifies if this role can create UDFs. ``1`` for yes, ``0`` otherwise. - -roles_memberships -------------------- - -``roles_memberships`` identifies the role memberships in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``role_id`` - - Role ID - * - ``member_role_id`` - - ID of the parent role from which this role will inherit - * - ``inherit`` - - Identifies if permissions are inherited. ``1`` for yes or ``0`` otherwise. - -savedqueries ----------------- - -``savedqueries`` identifies the :ref:`saved_queries` in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``name`` - - Saved query name - * - ``num_parameters`` - - Number of parameters to be replaced at run-time - -schemas ----------- - -``schemas`` identifies all the database's schemas. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``schema_id`` - - Unique ID of the schema - * - ``schema_name`` - - Name of the schema - * - ``schema_owner`` - - Name of the role who owns this schema - * - ``rechunker_ignore`` - - Internal use - - -schema_permissions --------------------- - -``schema_permissions`` identifies all permissions granted to schemas. - -There is one row for each combination of role (grantee) and permission granted to a schema. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the schema - * - ``schema_id`` - - ID of the schema the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -.. _tables_table: - -tables ----------- - -``tables`` identifies proper SQream tables in the database. - -For ``EXTERNAL TABLES`` see :ref:`external_tables ` - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - Database-unique ID for the table - * - ``schema_name`` - - Name of the schema containing the table - * - ``table_name`` - - Name of the table - * - ``row_count_valid`` - - Identifies if the ``row_count`` can be used - * - ``row_count`` - - Number of rows in the table - * - ``rechunker_ignore`` - - Internal use - - -table_permissions ------------------- - -``table_permissions`` identifies all permissions granted to tables. - -There is one row for each combination of role (grantee) and permission granted to a table. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the table - * - ``table_id`` - - ID of the table the permission applies to - * - ``role_id`` - - ID of the role granted permissions (grantee) - * - ``permission_type`` - - Identifies the permission type - - -udf_permissions ------------------- - -user_defined_functions -------------------------- - -``user_defined_functions`` identifies UDFs in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the database containing the view - * - ``function_id`` - - Database-unique ID for the UDF - * - ``function_name`` - - Name of the UDF - -views -------- - -``views`` identifies views in the database. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``view_id`` - - Database-unique ID for the view - * - ``view_schema`` - - Name of the schema containing the view - * - ``view_name`` - - Name of the view - * - ``view_data`` - - Internal use - * - ``view_query_text`` - - Identifies the ``AS`` clause used to create the view - - -Additional tables -====================== - -There are additional tables in the catalog that can be used for performance monitoring and inspection. - -The definition for these tables is provided below could change across SQream DB versions. - -extents ----------- - -``extents`` identifies storage extents. - -Each storage extents can contain several chunks. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the extent - * - ``table_id`` - - ID of the table containing the extent - * - ``column_id`` - - ID of the column containing the extent - * - ``extent_id`` - - ID for the extent - * - ``size`` - - Extent size in megabytes - * - ``path`` - - Full path to the extent on the file system - -chunk_columns -------------------- - -``chunk_columns`` lists chunk information by column. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the extent - * - ``table_id`` - - ID of the table containing the extent - * - ``column_id`` - - ID of the column containing the extent - * - ``chunk_id`` - - ID for the chunk - * - ``extent_id`` - - ID for the extent - * - ``compressed_size`` - - Actual chunk size in bytes - * - ``uncompressed_size`` - - Uncompressed chunk size in bytes - * - ``compression_type`` - - Actual compression scheme for this chunk - * - ``long_min`` - - Minimum numeric value in this chunk (if exists) - * - ``long_max`` - - Maximum numeric value in this chunk (if exists) - * - ``string_min`` - - Minimum text value in this chunk (if exists) - * - ``string_max`` - - Maximum text value in this chunk (if exists) - * - ``offset_in_file`` - - Internal use - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -chunks -------- - -``chunks`` identifies storage chunks. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the chunk - * - ``table_id`` - - ID of the table containing the chunk - * - ``column_id`` - - ID of the column containing the chunk - * - ``rows_num`` - - Amount of rows contained in the chunk - * - ``deletion_status`` - - When data is deleted from the table, it is first deleted logically. This value identifies how much data is deleted from the chunk. ``0`` for no data, ``1`` for some data, ``2`` to specify the entire chunk is deleted. - -delete_predicates -------------------- - -``delete_predicates`` identifies the existing delete predicates that have not been cleaned up. - -Each :ref:`DELETE ` command may result in several entries in this table. - -.. note:: This is an internal table designed for low-level performance troubleshooting. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Column - - Description - * - ``database_name`` - - Name of the databse containing the predicate - * - ``table_id`` - - ID of the table containing the predicate - * - ``max_chunk_id`` - - Internal use. Placeholder marker for the highest ``chunk_id`` logged during the DELETE operation. - * - ``delete_predicate`` - - Identifies the DELETE predicate - - -Examples -=========== - -List all tables in the database ----------------------------------- - -.. code-block:: psql - - master=> SELECT * FROM sqream_catalog.tables; - database_name | table_id | schema_name | table_name | row_count_valid | row_count | rechunker_ignore - --------------+----------+-------------+----------------+-----------------+-----------+----------------- - master | 1 | public | nba | true | 457 | 0 - master | 12 | public | cool_dates | true | 5 | 0 - master | 13 | public | cool_numbers | true | 9 | 0 - master | 27 | public | jabberwocky | true | 8 | 0 - -List all schemas in the database ------------------------------------- - -.. code-block:: psql - - master=> SELECT * FROM sqream_catalog.schemas; - schema_id | schema_name | schema_owner | rechunker_ignore - ----------+---------------+--------------+----------------- - 0 | public | sqream | false - 1 | secret_schema | mjordan | false - - -List columns and their types for a specific table ---------------------------------------------------- - -.. code-block:: postgres - - SELECT column_name, type_name - FROM sqream_catalog.columns - WHERE table_name='cool_animals'; - -List delete predicates ------------------------- - -.. code-block:: postgres - - SELECT t.table_name, d.* FROM - sqream_catalog.delete_predicates AS d - INNER JOIN sqream_catalog.tables AS t - ON d.table_id=t.table_id; - - -List :ref:`saved_queries` ------------------------------ - -.. code-block:: postgres - - SELECT * FROM sqream_catalog.savedqueries; + catalog_reference_overview + catalog_reference_schema_information + catalog_reference_catalog_tables + catalog_reference_additonal_tables + catalog_reference_examples \ No newline at end of file diff --git a/reference/catalog_reference_additonal_tables.rst b/reference/catalog_reference_additonal_tables.rst new file mode 100644 index 000000000..7d34429d3 --- /dev/null +++ b/reference/catalog_reference_additonal_tables.rst @@ -0,0 +1,120 @@ +.. _catalog_reference_additonal_tables: + +************************************* +Additional Tables +************************************* +The Reference Catalog includes additional tables that can be used for performance monitoring and inspection. The definition for these tables described on this page may change across SQream versions. + +.. contents:: + :local: + :depth: 1 + +Extents +---------- +The ``extents`` storage object identifies storage extents, and each storage extents can contain several chunks. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the extent. + * - ``table_id`` + - Shows the ID of the table containing the extent. + * - ``column_id`` + - Shows the ID of the column containing the extent. + * - ``extent_id`` + - Shows the ID for the extent. + * - ``size`` + - Shows the extent size in megabytes. + * - ``path`` + - Shows the full path to the extent on the file system. + +Chunk Columns +------------------- +The ``chunk_columns`` storage object lists chunk information by column. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the extent. + * - ``table_id`` + - Shows the ID of the table containing the extent. + * - ``column_id`` + - Shows the ID of the column containing the extent. + * - ``chunk_id`` + - Shows the chunk ID. + * - ``extent_id`` + - Shows the extent ID. + * - ``compressed_size`` + - Shows the compressed chunk size in bytes. + * - ``uncompressed_size`` + - Shows the uncompressed chunk size in bytes. + * - ``compression_type`` + - Shows the chunk's actual compression scheme. + * - ``long_min`` + - Shows the minimum numeric value in the chunk (if one exists). + * - ``long_max`` + - Shows the maximum numeric value in the chunk (if one exists). + * - ``string_min`` + - Shows the minimum text value in the chunk (if one exists). + * - ``string_max`` + - Shows the maximum text value in the chunk (if one exists). + * - ``offset_in_file`` + - Reserved for internal use. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +Chunks +------- +The ``chunks`` storage object identifies storage chunks. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the chunk. + * - ``table_id`` + - Shows the ID of the table containing the chunk. + * - ``column_id`` + - Shows the ID of the column containing the chunk. + * - ``rows_num`` + - Shows the amount of rows in the chunk. + * - ``deletion_status`` + - Determines what data to logically delete from the table first, and identifies how much data to delete from the chunk. The value ``0`` is ued for no data, ``1`` for some data, and ``2`` to delete the entire chunk. + +.. note:: This is an internal table designed for low-level performance troubleshooting. + +Delete Predicates +------------------- +The ``delete_predicates`` storage object identifies the existing delete predicates that have not been cleaned up. + +Each :ref:`DELETE ` command may result in several entries in this table. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the databse containing the predicate. + * - ``table_id`` + - Shows the ID of the table containing the predicate. + * - ``max_chunk_id`` + - Reserved for internal use, this is a placeholder marker for the highest ``chunk_id`` logged during the ``DELETE`` operation. + * - ``delete_predicate`` + - Identifies the DELETE predicate. + +.. note:: This is an internal table designed for low-level performance troubleshooting. \ No newline at end of file diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst new file mode 100644 index 000000000..20c1bf342 --- /dev/null +++ b/reference/catalog_reference_catalog_tables.rst @@ -0,0 +1,455 @@ +.. _catalog_reference_catalog_tables: + +************************************* +Catalog Tables +************************************* +The ``sqream_catalog`` includes the following tables: + +.. contents:: + :local: + :depth: 1 + +.. _clustering_keys: + +Clustering Keys +---------------- +The ``clustering_keys`` data object is used for explicit clustering keys for tables. If you define more than one clustering key, each key is listed in a separate row, and is described in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the ID of the table containing the column. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table containing the column. + * - ``clustering_key`` + - Shows the name of the column used as a clustering key for this table. + +.. _columns: + +Columns +---------------- +The **Columns** database object shows the following tables: + +.. contents:: + :local: + :depth: 1 + +Columns +*********** +The ``column`` data object is used with standard tables and is described in the following table: + +.. list-table:: + :widths: 20 150 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_id`` + - Shows the ID of the table containing the column. + * - ``table_name`` + - Shows the name of the table containing the column. + * - ``column_id`` + - Shows the ordinal number of the column in the table (begins at **0**). + * - ``column_name`` + - Shows the column's name. + * - ``type_name`` + - Shows the column's data type. For more information see :ref:`Supported Data Types `. + * - ``column_size`` + - Shows the maximum length in bytes. + * - ``has_default`` + - Shows ``NULL`` if the column has no default value, ``1`` if the default is a fixed value, or ``2`` if the default is an identity. For more information, see :ref:`identity`. + * - ``default_value`` + - Shows the column's default value. For more information, see :ref:`Default Value Constraints`. + * - ``compression_strategy`` + - Shows the compression strategy that a user has overridden. + * - ``created`` + - Shows the timestamp displaying when the column was created. + * - ``altered`` + - Shows the timestamp displaying when the column was last altered. + +External Table Columns +*********** +The ``external_table_columns`` is used for viewing data from foreign tables. + +For more information on foreign tables, see :ref:`CREATE FOREIGN TABLE`. + +.. _databases: + +Databases +---------------- +The ``databases`` data object is used for displaying database information, and is described in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_Id`` + - Shows the database's unique ID. + * - ``database_name`` + - Shows the database's name. + * - ``default_disk_chunk_size`` + - Reserved for internal use. + * - ``default_process_chunk_size`` + - Reserved for internal use. + * - ``rechunk_size`` + - Reserved for internal use. + * - ``storage_subchunk_size`` + - Reserved for internal use. + * - ``compression_chunk_size_threshold`` + - Reserved for internal use. + +.. _permissions: + +Permissions +---------------- +The ``permissions`` data object is used for displaying permissions information, such as roles (also known as **grantees**), and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Permission Types +*********** +The ``permission_types`` object identifies the permission names existing in the database. + +The following table describes the ``permission_types`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``permission_type_id`` + - Shows the permission type's ID. + * - ``name`` + - Shows the name of the permission type. + +Default Permissions +*********** +The commands included in the **Default Permissions** section describe how to check the following default permissions: + +.. contents:: + :local: + :depth: 1 + +Default Table Permissions +~~~~~~~~~~~~~~~~ +The ``sqream_catalog.table_default_permissions`` command shows the columns described below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the database that the default permission rule applies to. + * - ``schema_id`` + - Shows the schema that the rule applies to, or ``NULL`` if the ``ALTER`` statement does not specify a schema. + * - ``modifier_role_id`` + - Shows the role to apply the rule to. + * - ``getter_role_id`` + - Shows the role that the permission is granted to. + * - ``permission_type`` + - Shows the type of permission granted. + +Default Schema Permissions +~~~~~~~~~~~~~~~~ +The ``sqream_catalog.schema_default_permissions`` command shows the columns described below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the database that the default permission rule applies to. + * - ``modifier_role_id`` + - Shows the role to apply the rule to. + * - ``getter_role_id`` + - Shows the role that the permission is granted to. + * - ``permission_type`` + - Shows the type of permission granted. + +For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions `_. + +Table Permissions +*********** +The ``table_permissions`` data object identifies all permissions granted to tables. Each role-permission combination displays one row. + +The following table describes the ``table_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the ID of the table the permission applies to. + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +Database Permissions +*********** +The ``database_permissions`` data object identifies all permissions granted to databases. Each role-permission combination displays one row. + +The following table describes the ``database_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database the permission applies to + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +Schema Permissions +*********** +The ``schema_permissions`` data object identifies all permissions granted to schemas. Each role-permission combination displays one row. + +The following table describes the ``schema_permissions`` data object: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the schema. + * - ``schema_id`` + - Shows the ID of the schema the permission applies to. + * - ``role_id`` + - Shows the ID of the role granted permissions. + * - ``permission_type`` + - Identifies the permission type. + +UDF Permissions +*********** +**Comment** - *No content.* + +.. _queries: + +Queries +---------------- +The ``savedqueries`` data object identifies the saved_queries in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``name`` + - Shows the saved query name. + * - ``num_parameters`` + - Shows the number of parameters to be replaced at run-time. + +For more information, see :ref:`saved_queries`. + +.. _roles: + +Roles +---------------- +The ``roles`` data object is used for displaying role information, and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Roles +*********** +The ``roles`` data object identifies the roles in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``role_id`` + - Shows the role's database-unique ID. + * - ``name`` + - Shows the role's name. + * - ``superuser`` + - Identifies whether the role is a superuser (``1`` - superuser, ``0`` - regular user). + * - ``login`` + - Identifies whether the role can be used to log in to SQream (``1`` - yes, ``0`` - no). + * - ``has_password`` + - Identifies whether the role has a password (``1`` - yes, ``0`` - no). + * - ``can_create_function`` + - Identifies whether role can create UDFs (``1`` - yes, ``0`` - no). + +Role Memberships +*********** +The ``roles_memberships`` data object identifies the role memberships in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``role_id`` + - Shows the role ID. + * - ``member_role_id`` + - Shows the ID of the parent role that this role inherits from. + * - ``inherit`` + - Identifies whether permissions are inherited (``1`` - yes, ``0`` - no). + +.. _schemas: + +Schemas +---------------- +The ``schemas`` data object identifies all the database's schemas, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``schema_id`` + - Shows the schema's unique ID. + * - ``schema_name`` + - Shows the schema's name. + * - ``schema_owner`` + - Shows the name of the role that owns the schema. + * - ``rechunker_ignore`` + - Reserved for internal use. + +.. _sequences: + +Sequences +---------------- +The ``sequences`` data object is used for displaying identity key information, as shown below: + +Identity Key +*********** +**Comment** - *No content.* + +.. _tables: + +Tables +---------------- +The ``tables`` data object is used for displaying table information, and is described in the following tables: + +.. contents:: + :local: + :depth: 1 + +Tables +*********** +The ``tables`` data object identifies proper (**Comment** - *What does "proper" mean?*) SQream tables in the database, as shown in the following table: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the table's database-unique ID. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table. + * - ``row_count_valid`` + - Identifies whether the ``row_count`` can be used. + * - ``row_count`` + - Shows the number of rows in the table. + * - ``rechunker_ignore`` + - Relevant for internal use. + +Foreign Tables +*********** +The ``external_tables`` data object identifies foreign tables in the database, as shown below: + +.. list-table:: + :widths: 20 200 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the table. + * - ``table_id`` + - Shows the table's database-unique ID. + * - ``schema_name`` + - Shows the name of the schema containing the table. + * - ``table_name`` + - Shows the name of the table. + * - ``format`` + - Identifies the foreign data wrapper used. ``0`` for ``csv_fdw``, ``1`` for ``parquet_fdw``, ``2`` for ``orc_fdw``. + * - ``created`` + - Identifies the clause used to create the table. + +.. _views: + +Views +---------------- +The ``views`` data object is used for displaying views in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``view_id`` + - Shows the view's database-unique ID. + * - ``view_schema`` + - Shows the name of the schema containing the view. + * - ``view_name`` + - Shows the name of the view. + * - ``view_data`` + - Reserved for internal use. + * - ``view_query_text`` + - Identifies the ``AS`` clause used to create the view. + +.. _udfs: + +User Defined Functions +---------------- +The ``udf`` data object is used for displaying UDFs in the database, as shown below: + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``database_name`` + - Shows the name of the database containing the view. + * - ``function_id`` + - Shows the UDF's database-unique ID. + * - ``function_name`` + - Shows the name of the UDF. \ No newline at end of file diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst new file mode 100644 index 000000000..4531dfefc --- /dev/null +++ b/reference/catalog_reference_examples.rst @@ -0,0 +1,64 @@ +.. _catalog_reference_examples: + +************************************* +Examples +************************************* +The **Examples** page includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Listing All Tables in a Database +---------------------------------- + +.. code-block:: psql + + master=> SELECT * FROM sqream_catalog.tables; + database_name | table_id | schema_name | table_name | row_count_valid | row_count | rechunker_ignore + --------------+----------+-------------+----------------+-----------------+-----------+----------------- + master | 1 | public | nba | true | 457 | 0 + master | 12 | public | cool_dates | true | 5 | 0 + master | 13 | public | cool_numbers | true | 9 | 0 + master | 27 | public | jabberwocky | true | 8 | 0 + +Listing All Schemas in a Database +------------------------------------ + +.. code-block:: psql + + master=> SELECT * FROM sqream_catalog.schemas; + schema_id | schema_name | schema_owner | rechunker_ignore + ----------+---------------+--------------+----------------- + 0 | public | sqream | false + 1 | secret_schema | mjordan | false + + +Listing Columns and Their Types for a Specific Table +--------------------------------------------------- + +.. code-block:: postgres + + SELECT column_name, type_name + FROM sqream_catalog.columns + WHERE table_name='cool_animals'; + +Listing Delete Predicates +------------------------ + +.. code-block:: postgres + + SELECT t.table_name, d.* FROM + sqream_catalog.delete_predicates AS d + INNER JOIN sqream_catalog.tables AS t + ON d.table_id=t.table_id; + + +Listing Saved Queries +----------------------------- + +.. code-block:: postgres + + SELECT * FROM sqream_catalog.savedqueries; + +For more information, see :ref:`saved_queries`. \ No newline at end of file diff --git a/reference/catalog_reference_overview.rst b/reference/catalog_reference_overview.rst new file mode 100644 index 000000000..b74663509 --- /dev/null +++ b/reference/catalog_reference_overview.rst @@ -0,0 +1,11 @@ +.. _catalog_reference_overview: + +************************************* +Overview +************************************* +The SQream database uses a schema called ``sqream_catalog`` that contains information about your database's objects, such tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and which may be different across SQream versions. + +* :ref:`catalog_reference_schema_information` +* :ref:`catalog_reference_catalog_tables` +* :ref:`catalog_reference_additonal_tables` +* :ref:`catalog_reference_examples` \ No newline at end of file diff --git a/reference/catalog_reference_schema_information.rst b/reference/catalog_reference_schema_information.rst new file mode 100644 index 000000000..6cd43ab6a --- /dev/null +++ b/reference/catalog_reference_schema_information.rst @@ -0,0 +1,62 @@ +.. _catalog_reference_schema_information: + +************************************* +What Information Does the Schema Contain? +************************************* +The schema includes tables designated and relevant for both external and internal use: + +.. contents:: + :local: + :depth: 1 + +External Tables +----------------- +The following table shows the data objects contained in the ``sqream_catalog`` schema designated for external use: + +.. list-table:: Database Objects + :widths: 20 180 + :header-rows: 1 + + * - Database Object + - Table + * - :ref:`Clustering Keys` + - ``clustering_keys`` + * - :ref:`Columns` + - ``columns``, ``external_table_columns`` + * - :ref:`Databases` + - ``databases`` + * - :ref:`Permissions` + - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions``, ``sqream_catalog.table_default_permissions`` + * - :ref:`Queries` + - ``saved_queries`` + * - :ref:`Roles` + - ``roles``, ``roles_memeberships`` + * - :ref:`Schemas` + - ``schemas`` + * - :ref:`Sequences` + - ``identity_key`` + * - :ref:`Tables` + - ``tables``, ``external_tables`` + * - :ref:`Views` + - ``views`` + * - :ref:`User Defined Functions` + - ``user_defined_functions`` + +Internal Tables +----------------- +The following table shows the data objects contained in the ``sqream_catalog`` schema designated for internal use: + +.. list-table:: Storage Objects + :widths: 20 180 + :header-rows: 1 + + * - Database Object + - Table + * - Extents + - Shows ``extents``. + * - Chunk columns + - Shows ``chunks_columns``. + * - Chunks + - Shows ``chunks``. + * - Delete predicates + - Shows ``delete_predicates``. For more information, see :ref:`Deleting Data`. \ No newline at end of file diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 220e05eb3..0ab200286 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -3,22 +3,27 @@ ***************************** ALTER DEFAULT PERMISSIONS ***************************** +The **ALTER DEFAULT PERMISSIONS** page describes the following: -``ALTER DEFAULT PERMISSIONS`` allows granting automatic permissions to future objects. +.. contents:: + :local: + :depth: 1 -By default, if one user creates a table, another user will not have ``SELECT`` permissions on it. -By modifying the target role's default permissions, a database administrator can ensure that -all objects created by that role will be accessible to others. +Overview +============= +The ``ALTER DEFAULT PERMISSIONS`` command lets you grant automatic permissions to future objects. + +By default, users do not have ``SELECT`` permissions on tables created by other users. Database administrators can grant access to other users by modifying the target role default permissions. -Learn more about the permission system in the :ref:`access control guide`. +For more information about access control, see :ref:`Access Control`. Permissions ============= - -To alter default permissions, the current role must have the ``SUPERUSER`` permission. +The ``SUPERUSER`` permission is required to alter default permissions. Syntax ========== +The following is the syntax for altering default permissions: .. code-block:: postgres @@ -55,32 +60,71 @@ Syntax :start-line: 127 :end-line: 180 - Examples ============ +This section includes the following examples: -Automatic permissions for newly created schemas +.. contents:: + :local: + :depth: 1 + +Granting Default Table Permissions ------------------------------------------------- +This example is based on the roles **r1** and **r2**, created as follows: -When role ``demo`` creates a new schema, roles u1,u2 will get USAGE and CREATE permissions in the new schema: +.. code-block:: postgres + + create role r1; + create role r2; + alter default permissions for r1 for tables grant select to r2; + +Once created, you can build and run the following query based on the above: .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + select + tdp.database_name as "database_name", + ss.schema_name as "schema_name", + rs1.name as "table_creator", + rs2.name as "grant_to", + pts.name as "permission_type" + from sqream_catalog.table_default_permissions tdp + inner join sqream_catalog.roles rs1 on tdp.modifier_role_id = rs1.role_id + inner join sqream_catalog.roles rs2 on tdp.getter_role_id = rs2.role_id + left join sqream_catalog.schemas ss on tdp.schema_id = ss.schema_id + inner join sqream_catalog.permission_types pts on pts.permission_type_id=tdp.permission_type + ; + +The following is an example of the output generated from the above queries: ++-----------------------+----------------------+-------------------+--------------+------------------------------+ +| **database_name** | **schema_name** | **table_creator** | **grant_to** | **permission_type** | ++-----------------------+----------------------+-------------------+--------------+------------------------------+ +| master | NULL | public | public | select | ++-----------------------+----------------------+-------------------+--------------+------------------------------+ -Automatic permissions for newly created tables in a schema ----------------------------------------------------------------- +For more information about default permissions, see `Default Permissions `_. + +Granting Automatic Permissions for Newly Created Schemas +------------------------------------------------- +When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE`` and ``CREATE`` permissions in the new schema, as shown below: -When role ``demo`` creates a new table in schema ``s1``, roles u1,u2 wil be granted with SELECT on it: +.. code-block:: postgres + + ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + +Granting Automatic Permissions for Newly Created Tables in a Schema +---------------------------------------------------------------- +When the role ``demo`` creates a new table in schema ``s1``, roles **u1,u2** are granted ``SELECT`` permissions, as shown below: .. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR demo IN s1 FOR TABLES GRANT SELECT TO u1,u2; -Revoke (``DROP GRANT``) permissions for newly created tables +Revoking Permissions from Newly Created Tables --------------------------------------------------------------- +Revoking permissions refers to using the ``DROP GRANT`` command, as shown below: .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR public FOR TABLES DROP GRANT SELECT,DDL,INSERT,DELETE TO public; + ALTER DEFAULT PERMISSIONS FOR public FOR TABLES DROP GRANT SELECT,DDL,INSERT,DELETE TO public; \ No newline at end of file From 3b13862d2959c862e65601fc522d089985a1e76d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 17:35:32 +0300 Subject: [PATCH 0123/1892] Fixed link syntax --- reference/catalog_reference_catalog_tables.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 20c1bf342..7ddb9c148 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -187,7 +187,7 @@ The ``sqream_catalog.schema_default_permissions`` command shows the columns desc * - ``permission_type`` - Shows the type of permission granted. -For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions `_. +For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions `_. Table Permissions *********** From c331ad331ec09b684e17b5ed0f285f0b8a1e9619 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 17:41:44 +0300 Subject: [PATCH 0124/1892] Update grant.rst Capitalization --- reference/sql/sql_statements/access_control_commands/grant.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index dfb48c212..ceac48f7a 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -126,7 +126,7 @@ Parameters .. include from here -Supported permissions +Supported Permissions ======================= .. list-table:: From 280f26dd224d9ae32ed62d02da641458be00a404 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 18:18:00 +0300 Subject: [PATCH 0125/1892] Update get_metadata_chunk_key.rst --- .../get_metadata_chunk_key.rst | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst index 08eba8345..784a54246 100644 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst @@ -107,34 +107,34 @@ The following table describes the output generated from the ``GET_METADATA_CHUNK - ``2`` * - ``min_long`` - - **Comment** - What is it? - - **Comment** - What is it? - - ``flat`` + - Shows the minimum value of the type. + - Long + - ``25`` * - ``max_long`` - - **Comment** - What is it? - - **Comment** - What is it? - - **Comment** - What is it? + - Shows the maximum value in the chunk of a number. + - Long + - ``12345`` * - ``min_string_max_string`` - - **Comment** - What is it? - - **Comment** - What is it? - - **Comment** - What is it? + - Shows the minimum value of the string type. + - String + - ``"abc"`` * - ``min_numeric`` - - **Comment** - What is it? - - **Comment** - What is it? - - **Comment** - What is it? + - Shows the minimum value of the numeric type in the chunk. + - Numeric + - ``12.22`` * - ``max_numeric`` - - **Comment** - What is it? - - **Comment** - What is it? - - **Comment** - What is it? + - Shows the maximum value of the numeric type in the chunk. + - Numeric + - ``555.22`` * - ``column_aligned`` - - **Comment** - What is it? - - **Comment** - What is it? - - **Comment** - What is it? + - Relevant to text columns, aligment in memory. + - Boolean + - ``Yes`` / ``No`` The following is an example of the output generated from the ``GET_METADATA_CHUNK_KEY`` command: From f348959e3c5789d19ff89a01986e8c8e3d2696e5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 18:26:00 +0300 Subject: [PATCH 0126/1892] Updated --- index.rst | 6 +----- releases/2022.1.rst | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/index.rst b/index.rst index db8e0fa2a..5c4582c19 100644 --- a/index.rst +++ b/index.rst @@ -4,8 +4,6 @@ SQream DB Documentation ************************* -The **v2022.1** branch is a private branch designed for internal use only until the release date. - .. only:: html .. tip:: @@ -51,7 +49,6 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`connect_to_tableau` * - **Releases** - **Driver and Deployment** @@ -59,7 +56,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`2021.2<2021.2>` + :ref:`2021.2<2021.2>` :ref:`2021.1<2021.1>` @@ -74,7 +71,6 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`connect_to_tableau` - :ref:`troubleshooting` guide diff --git a/releases/2022.1.rst b/releases/2022.1.rst index b6ffdf9ef..8d881c92c 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -67,7 +67,7 @@ The following table lists the known issues for Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ | SQ-9889 | Running a query including Thai characters generated an internal runtime error. | +-------------+-------------------------------------------------------------------------------------------+ -| SQ-10071 | error on exists subqueries with text and varchar equality condition | +| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | +-------------+-------------------------------------------------------------------------------------------+ | SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | +-------------+-------------------------------------------------------------------------------------------+ From 50e67c53984237eed802fe6b8ea9a884443c01f9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 18:45:40 +0300 Subject: [PATCH 0127/1892] Fixed table alignment. --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 5c4582c19..bc5c25c2c 100644 --- a/index.rst +++ b/index.rst @@ -56,7 +56,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau` - :ref:`2021.2<2021.2>` + :ref:`2021.2<2021.2>` :ref:`2021.1<2021.1>` From dd2de29193efb911a2bd87643930b8fe7250fdce Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 19 Jul 2022 23:39:00 +0300 Subject: [PATCH 0128/1892] Fixed link and table alignment --- data_ingestion/avro.rst | 2 +- .../installing_prometheus_using_binary_packages.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index e943fe41c..753786376 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -161,7 +161,7 @@ The following table shows the supported **Complex** data types: +------------+-------------------------------------------------------+ | | SQream Type | -| +---------------+---------------+-----------+-----------+ +| +------------+----------------+-------------+-----------+ |Avro Type | Number | Date/Datetime | String | Boolean | +============+============+================+=============+===========+ | ``record`` | | | | | diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst index a6104bdd0..5031ec181 100644 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -102,7 +102,7 @@ You must install Prometheus before installing the Dashboard Data Collector. $ sudo chown -R prometheus:prometheus /etc/prometheus/consoles $ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries -For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector `_. +For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector `_. Back to :ref:`Installing Prometheus Using Binary Packages` @@ -238,4 +238,4 @@ From the **Query** tab you can query metrics, as shown below: * - .. image:: /_static/images/3c9c4e8b-49bd-44a8-9829-81d1772ed962.gif -Back to :ref:`Installing Prometheus Using Binary Packages` +Back to :ref:`Installing Prometheus Using Binary Packages` \ No newline at end of file From 77092d8367f34e4a87c37b131dd174774d4347ef Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 20 Jul 2022 14:46:07 +0300 Subject: [PATCH 0129/1892] Reinstituted Client Platforms (removed by accident) --- .../client_platforms/connect.sas | 27 ++ .../client_platforms/connect2.sas | 27 ++ .../client_platforms/connect3.sas | 17 + .../client_platforms/index.rst | 39 ++ .../client_platforms/informatica.rst | 173 +++++++ .../client_platforms/microstrategy.rst | 185 +++++++ .../client_platforms/odbc-sqream.tdc | 25 + .../client_platforms/pentaho.rst | 253 ++++++++++ connecting_to_sqream/client_platforms/php.rst | 76 +++ .../client_platforms/power_bi.rst | 143 ++++++ connecting_to_sqream/client_platforms/r.rst | 151 ++++++ .../client_platforms/sas_viya.rst | 185 +++++++ .../client_platforms/sql_workbench.rst | 135 ++++++ .../client_platforms/tableau.rst | 453 ++++++++++++++++++ .../client_platforms/talend.rst | 204 ++++++++ .../client_platforms/test.php | 16 + .../client_platforms/tibco_spotfire.rst | 387 +++++++++++++++ connecting_to_sqream/index.rst | 3 +- 18 files changed, 2498 insertions(+), 1 deletion(-) create mode 100644 connecting_to_sqream/client_platforms/connect.sas create mode 100644 connecting_to_sqream/client_platforms/connect2.sas create mode 100644 connecting_to_sqream/client_platforms/connect3.sas create mode 100644 connecting_to_sqream/client_platforms/index.rst create mode 100644 connecting_to_sqream/client_platforms/informatica.rst create mode 100644 connecting_to_sqream/client_platforms/microstrategy.rst create mode 100644 connecting_to_sqream/client_platforms/odbc-sqream.tdc create mode 100644 connecting_to_sqream/client_platforms/pentaho.rst create mode 100644 connecting_to_sqream/client_platforms/php.rst create mode 100644 connecting_to_sqream/client_platforms/power_bi.rst create mode 100644 connecting_to_sqream/client_platforms/r.rst create mode 100644 connecting_to_sqream/client_platforms/sas_viya.rst create mode 100644 connecting_to_sqream/client_platforms/sql_workbench.rst create mode 100644 connecting_to_sqream/client_platforms/tableau.rst create mode 100644 connecting_to_sqream/client_platforms/talend.rst create mode 100644 connecting_to_sqream/client_platforms/test.php create mode 100644 connecting_to_sqream/client_platforms/tibco_spotfire.rst diff --git a/connecting_to_sqream/client_platforms/connect.sas b/connecting_to_sqream/client_platforms/connect.sas new file mode 100644 index 000000000..10fcdb0a2 --- /dev/null +++ b/connecting_to_sqream/client_platforms/connect.sas @@ -0,0 +1,27 @@ +options sastrace='d,d,d,d' +sastraceloc=saslog +nostsuffix +msglevel=i +sql_ip_trace=(note,source) +DEBUG=DBMS_SELECT; + +options validvarname=any; + +libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" + classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" + URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" + user="rhendricks" + password="Tr0ub4dor3" + schema="public" + PRESERVE_TAB_NAMES=YES + PRESERVE_COL_NAMES=YES; + +proc sql; + title 'Customers table'; + select * + from sqlib.customers; +quit; + +data sqlib.customers; + set sqlib.customers; +run; \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/connect2.sas b/connecting_to_sqream/client_platforms/connect2.sas new file mode 100644 index 000000000..10fcdb0a2 --- /dev/null +++ b/connecting_to_sqream/client_platforms/connect2.sas @@ -0,0 +1,27 @@ +options sastrace='d,d,d,d' +sastraceloc=saslog +nostsuffix +msglevel=i +sql_ip_trace=(note,source) +DEBUG=DBMS_SELECT; + +options validvarname=any; + +libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" + classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" + URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" + user="rhendricks" + password="Tr0ub4dor3" + schema="public" + PRESERVE_TAB_NAMES=YES + PRESERVE_COL_NAMES=YES; + +proc sql; + title 'Customers table'; + select * + from sqlib.customers; +quit; + +data sqlib.customers; + set sqlib.customers; +run; \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/connect3.sas b/connecting_to_sqream/client_platforms/connect3.sas new file mode 100644 index 000000000..c1bf11dcf --- /dev/null +++ b/connecting_to_sqream/client_platforms/connect3.sas @@ -0,0 +1,17 @@ +options sastrace='d,d,d,d' +sastraceloc=saslog +nostsuffix +msglevel=i +sql_ip_trace=(note,source) +DEBUG=DBMS_SELECT; + +options validvarname=any; + +libname sqlib jdbc driver="com.sqream.jdbc.SQDriver" + classpath="/opt/sqream/sqream-jdbc-4.0.0.jar" + URL="jdbc:Sqream://sqream-cluster.piedpiper.com:3108/raviga;cluster=true" + user="rhendricks" + password="Tr0ub4dor3" + schema="public" + PRESERVE_TAB_NAMES=YES + PRESERVE_COL_NAMES=YES; \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst new file mode 100644 index 000000000..a5a3f5166 --- /dev/null +++ b/connecting_to_sqream/client_platforms/index.rst @@ -0,0 +1,39 @@ +.. _client_platforms: + +************************************ +Client Platforms +************************************ +These topics explain how to install and connect a variety of third party tools. + +Browse the articles below, in the sidebar, or use the search to find the information you need. + +Overview +========== + +SQream DB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, tools, vizualisers, and utilities. + +The tools listed have been tested and approved for use with SQream DB. Most 3\ :sup:`rd` party tools that work through JDBC, ODBC, and Python should work. + +If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support `_ or contact your SQream account manager for more information. + +.. toctree:: + :maxdepth: 4 + :caption: In this section: + :titlesonly: + + power_bi + tibco_spotfire + sas_viya + sql_workbench + tableau + pentaho + microstrategy + informatica + r + php + xxtalend + xxdiagnosing_common_connectivity_issues + +.. image:: /_static/images/connectivity_ecosystem.png + + diff --git a/connecting_to_sqream/client_platforms/informatica.rst b/connecting_to_sqream/client_platforms/informatica.rst new file mode 100644 index 000000000..6bc50b22a --- /dev/null +++ b/connecting_to_sqream/client_platforms/informatica.rst @@ -0,0 +1,173 @@ +.. _informatica: + +************************* +Connect to SQream Using Informatica Cloud Services +************************* + +Overview +========= +The **Connecting to SQream Using Informatica Cloud Services** page is quick start guide for connecting to SQream using Informatica cloud services. + +It describes the following: + +.. contents:: + :local: + +Establishing a Connection between SQream and Informatica +----------------- +The **Establishing a Connection between SQream and Informatica** page describes how to establish a connection between SQream and the Informatica data integration Cloud. + +**To establish a connection between SQream and the Informatica data integration Cloud:** + +1. Go to the `Informatica Cloud homepage `_. + + :: + +2. Do one of the following: + + 1. Log in using your credentials. + + :: + + 2. Log in using your SAML Identity Provider. + +3. From the **Services** window, select **Administrator** or click **Show all services** to show all services. + + + The SQream dashboard is displayed. + + + :: + + +4. In the menu on the left, click **Runtime Environments**. + + + The **Runtime Environments** panel is displayed. + + :: + +5. Click **Download Secure Agent**. + + :: + +6. When the **Download the Secure Agent** panel is displayed, do the following: + + 1. Select a platform (Windows 64 or Linux 64). + + :: + + + 2. Click **Copy** and save the token on your local hard drive. + + The token is used in combination with your user name to authorize the agent to access your account. + + +7. Click **Download**. + + The installation begins. + + :: + +8. When the **Informatica Cloud Secure Agent Setup** panel is displayed, click **Next**. + + + :: + + +9. Provide your **User Name** and **Install Token** and click **Register**. + + :: + + + +10. From the Runtime Environments panel, click **New Runtime Environment**. + + + The **New Secure Agent Group** window is displayed. + + :: + +11. On the New Secure Agent Group window, click **OK** to connect your Runtime Environment with the running agent. + + .. note:: If you do not download Secure Agent, you will not be able to connect your Runtime Environment with the running agent and continue establishing a connection between SQream and the Informatica data integration Cloud. + +Establishing a Connection In Your Environment +----------------- + +The **Establishing a Connection In Your Environment** describes the following: + +.. contents:: + :local: + +Establishing an ODBC DSN Connection In Your Environment +~~~~~~~~~~~~~ +After establishing a connection between SQream and Informatica you can establish an ODBC DSN connection in your environment. + +**To establish an ODBC connection in your environment:** + +1. Click **Add**. + + :: + +2. Click **Configure**. + + .. note:: Verify that **Use Server Picker** is selected. + +3. Click **Test**. + + :: + +4. Verify that the connection has tested successfully. + + :: + +5. Click **Save**. + + :: + +6. Click **Actions** > **Publish**. + +Establishing a JDBC Connection In Your Environment +~~~~~~~~~~~~~ +After establishing a connection between SQream and Informatica you can establish a JDBC connection in your environment. + +**To establish a JDBC connection in your environment:** + +1. Create a new DB connection by clicking **Connections** > **New Connection**. + + The **New Connection** window is displayed. + + :: + + +2. In the **JDBC_IC Connection Properties** section, in the **JDBC Connection URL** field, establish a JDBC connection by providing the correct connection string. + + For connection string examples, see `Connection Strings `_. + + :: + +3. Click **Test**. + + :: + +4. Verify that the connection has tested successfully. + + :: + +5. Click **Save**. + + :: + +6. Click **Actions** > **Publish**. + +Supported SQream Driver Versions +--------------- + +SQream supports the following SQream driver versions: + +* **JDBC** - Version 4.3.4 and above. + + :: + +* **ODBC** - Version 4.0.0 and above. diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst new file mode 100644 index 000000000..6cad19be2 --- /dev/null +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -0,0 +1,185 @@ +.. _microstrategy: + + +************************* +Connect to SQream Using MicroStrategy +************************* + +.. _ms_top: + +Overview +--------------- +This document is a Quick Start Guide that describes how to install MicroStrategy and connect a datasource to the MicroStrategy dasbhoard for analysis. + + + +The **Connecting to SQream Using MicroStrategy** page describes the following: + + +.. contents:: + :local: + + + + + + +What is MicroStrategy? +================ +MicroStrategy is a Business Intelligence software offering a wide variety of data analytics capabilities. SQream uses the MicroStrategy connector for reading and loading data into SQream. + +MicroStrategy provides the following: + +* Data discovery +* Advanced analytics +* Data visualization +* Embedded BI +* Banded reports and statements + + +For more information about Microstrategy, see `MicroStrategy `_. + + + +:ref:`Back to Overview ` + + + + + +Connecting a Data Source +======================= + +1. Activate the **MicroStrategy Desktop** app. The app displays the Dossiers panel to the right. + + :: + +2. Download the most current version of the `SQream JDBC driver `_. + + :: + +3. Click **Dossiers** and **New Dossier**. The **Untitled Dossier** panel is displayed. + + :: + +4. Click **New Data**. + + :: + +5. From the **Data Sources** panel, select **Databases** to access data from tables. The **Select Import Options** panel is displayed. + + :: + +6. Select one of the following: + + * Build a Query + * Type a Query + * Select Tables + + :: + +7. Click **Next**. + + :: + +8. In the Data Source panel, do the following: + + 1. From the **Database** dropdown menu, select **Generic**. The **Host Name**, **Port Number**, and **Database Name** fields are removed from the panel. + + :: + + 2. In the **Version** dropdown menu, verify that **Generic DBMS** is selected. + + :: + + 3. Click **Show Connection String**. + + :: + + 4. Select the **Edit connection string** checkbox. + + :: + + 5. From the **Driver** dropdown menu, select a driver for one of the following connectors: + + * **JDBC** - The SQream driver is not integrated with MicroStrategy and does not appear in the dropdown menu. However, to proceed, you must select an item, and in the next step you must specify the path to the SQream driver that you installed on your machine. + * **ODBC** - SQreamDB ODBC + + :: + + 6. In the **Connection String** text box, type the relevant connection string and path to the JDBC jar file using the following syntax: + + .. code-block:: console + + $ jdbc:Sqream:///;user=;password=sqream;[; ...] + + The following example shows the correct syntax for the JDBC connector: + + .. code-block:: console + + jdbc;MSTR_JDBC_JAR_FOLDER=C:\path\to\jdbc\folder;DRIVER=;URL={jdbc:Sqream:///;user=;password=;[; ...];} + + The following example shows the correct syntax for the ODBC connector: + + .. code-block:: console + + odbc:Driver={SqreamODBCDriver};DSN={SQreamDB ODBC};Server=;Port=;Database=;User=;Password=;Cluster=; + + For more information about the available **connection parameters** and other examples, see `Connection Parameters `_. + + 7. In the **User** and **Password** fields, fill out your user name and password. + + :: + + 8. In the **Data Source Name** field, type **SQreamDB**. + + :: + + 9. Click **Save**. The SQreamDB that you picked in the Data Source panel is displayed. + + +9. In the **Namespace** menu, select a namespace. The tables files are displayed. + + :: + +10. Drag and drop the tables into the panel on the right in your required order. + + :: + +11. **Recommended** - Click **Prepare Data** to customize your data for analysis. + + :: + +12. Click **Finish**. + + :: + +13. From the **Data Access Mode** dialog box, select one of the following: + + + * Connect Live + * Import as an In-memory Dataset + +Your populated dashboard is displayed and is ready for data discovery and analytics. + + + + + + +.. _supported_sqream_drivers: + +:ref:`Back to Overview ` + +Supported SQream Drivers +================ + +The following list shows the supported SQream drivers and versions: + +* **JDBC** - Version 4.3.3 and higher. +* **ODBC** - Version 4.0.0. + + +.. _supported_tools_and_operating_systems: + +:ref:`Back to Overview ` diff --git a/connecting_to_sqream/client_platforms/odbc-sqream.tdc b/connecting_to_sqream/client_platforms/odbc-sqream.tdc new file mode 100644 index 000000000..36cd55e33 --- /dev/null +++ b/connecting_to_sqream/client_platforms/odbc-sqream.tdc @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst new file mode 100644 index 000000000..fa8146c41 --- /dev/null +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -0,0 +1,253 @@ +.. _pentaho_data_integration: + +************************* +Connecting to SQream Using Pentaho Data Integration +************************* +.. _pentaho_top: + +Overview +========= +This document is a Quick Start Guide that describes how to install Pentaho, create a transformation, and define your output. + +The Connecting to SQream Using Pentaho page describes the following: + +* :ref:`Installing Pentaho ` +* :ref:`Installing and setting up the JDBC driver ` +* :ref:`Creating a transformation ` +* :ref:`Defining your output ` +* :ref:`Importing your data ` + +.. _install_pentaho: + +Installing Pentaho +~~~~~~~~~~~~~~~~~ +To install PDI, see the `Pentaho Community Edition (CE) Installation Guide `_. + +The **Pentaho Community Edition (CE) Installation Guide** describes how to do the following: + +* Downloading the PDI software. +* Installing the **JRE (Java Runtime Environment)** and **JDK (Java Development Kit)**. +* Setting up the JRE and JDK environment variables for PDI. + +:ref:`Back to Overview ` + +.. _install_set_up_jdbc_driver: + +Installing and Setting Up the JDBC Driver +~~~~~~~~~~~~~~~~~ +After installing Pentaho you must install and set up the JDBC driver. This section explains how to set up the JDBC driver using Pentaho. These instructions use Spoon, the graphical transformation and job designer associated with the PDI suite. + +You can install the driver by copying and pasting the SQream JDBC .jar file into your **/design-tools/data-integration/lib** directory. + +**NOTE:** Contact your SQream license account manager for the JDBC .jar file. + +:ref:`Back to Overview ` + +.. _create_transformation: + +Creating a Transformation +~~~~~~~~~~~~~~~~~~ +After installing Pentaho you can create a transformation. + +**To create a transformation:** + +1. Use the CLI to open the PDI client for your operating system (Windows): + + .. code-block:: console + + $ spoon.bat + +2. Open the spoon.bat file from its folder location. + +:: + +3. In the **View** tab, right-click **Transformations** and click **New**. + + A new transformation tab is created. + +4. In the **Design** tab, click **Input** to show its file contents. + +:: + +5. Drag and drop the **CSV file input** item to the new transformation tab that you created. + +:: + +6. Double-click **CSV file input**. The **CSV file input** panel is displayed. + +:: + +7. In the **Step name** field, type a name. + +:: + +8. To the right of the **Filename** field, click **Browse**. + +:: + +9. Select the file that you want to read from and click **OK**. + +:: + +10. In the CSV file input window, click **Get Fields**. + +:: + +11. In the **Sample data** window, enter the number of lines you want to sample and click **OK**. The default setting is **100**. + + The tool reads the file and suggests the field name and type. + +12. In the CSV file input window, click **Preview**. + +:: + +13. In the **Preview size** window, enter the number of rows you want to preview and click **OK**. The default setting is **1000**. + +:: + +14. Verify that the preview data is correct and click **Close**. + +:: + +15. Click **OK** in the **CSV file input** window. + +:ref:`Back to Overview ` + +.. _define_output: + +Defining Your Output +----------------- +After creating your transformation you must define your output. + +**To define your output:** + +1. In the **Design** tab, click **Output**. + + The Output folder is opened. + +2. Drag and drop **Table output** item to the Transformation window. + +:: + +3. Double-click **Table output** to open the **Table output** dialog box. + +:: + +4. From the **Table output** dialog box, type a **Step name** and click **New** to create a new connection. Your **steps** are the building blocks of a transformation, such as file input or a table output. + + The **Database Connection** window is displayed with the **General** tab selected by default. + +5. Enter or select the following information in the Database Connection window and click **Test**. + + The following table shows and describes the information that you need to fill out in the Database Connection window: + + .. list-table:: + :widths: 6 31 73 + :header-rows: 1 + + * - No. + - Element Name + - Description + * - 1 + - Connection name + - Enter a name that uniquely describes your connection, such as **sampledata**. + * - 2 + - Connection type + - Select **Generic database**. + * - 3 + - Access + - Select **Native (JDBC)**. + * - 4 + - Custom connection URL + - Insert **jdbc:Sqream:///;user=;password=;[; ...];**. The IP is a node in your SQream cluster and is the name or schema of the database you want to connect to. Verify that you have not used any leading or trailing spaces. + * - 5 + - Custom driver class name + - Insert **com.sqream.jdbc.SQDriver**. Verify that you have not used any leading or trailing spaces. + * - 6 + - Username + - Your SQreamdb username. If you leave this blank, you will be prompted to provide it when you connect. + * - 7 + - Password + - Your password. If you leave this blank, you will be prompted to provide it when you connect. + + The following message is displayed: + +.. image:: /_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png + +6. Click **OK** in the window above, in the Database Connection window, and Table Output window. + +:ref:`Back to Overview ` + +.. _import_data: + +Importing Data +----------------- +After defining your output you can begin importing your data. + +For more information about backing up users, permissions, or schedules, see `Backup and Restore Pentaho Repositories `_ + +**To import data:** + +1. Double-click the **Table output** connection that you just created. + +:: + +2. To the right of the **Target schema** field, click **Browse** and select a schema name. + +:: + +3. Click **OK**. The selected schema name is displayed in the **Target schema** field. + +:: + +4. Create a new hop connection between the **CSV file input** and **Table output** steps: + + 1. On the CSV file input step item, click the **new hop connection** icon. + + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png + + 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. + + .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png + + 3. Release the mouse button. The following options are displayed. + + :: + + 4. Select **Main output of step**. + + .. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png + +:: + +5. Double-click **Table output** to open the **Table output** dialog box. + +:: + +6. In the **Target table** field, define a target table name. + +:: + +7. Click **SQL** to open the **Simple SQL editor.** + +:: + +8. In the **Simple SQL editor**, click **Execute**. + + The system processes and displays the results of the SQL statements. + +9. Close all open dialog boxes. + +:: + +10. Click the play button to execute the transformation. + + .. image:: /_static/images/third_party_connectors/pentaho/execute_transformation.png + + The **Run Options** dialog box is displayed. + +11. Click **Run**. + + The **Execution Results** are displayed. + +:ref:`Back to Overview ` \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/php.rst b/connecting_to_sqream/client_platforms/php.rst new file mode 100644 index 000000000..2310fde6b --- /dev/null +++ b/connecting_to_sqream/client_platforms/php.rst @@ -0,0 +1,76 @@ +.. _php: + +***************************** +Connect to SQream Using PHP +***************************** + +Overview +========== +PHP is an open source scripting language that executes scripts on servers. The **Connect to PHP** page explains how to connect to a SQream cluster, and describes the following: + +.. contents:: + :local: + :depth: 1 + +Installing PHP +------------------- +**To install PHP:** + +1. Download the JDBC driver installer from the `SQream Drivers page `_. + + :: + +2. Create a DSN. + + :: + +3. Install the **uODBC** extension for your PHP installation. + + For more information, navigate to `PHP Documentation `_ and see the topic menu on the right side of the page. + +Configuring PHP +------------------- +You can configure PHP in one of the following ways: + +* When compiling, configure PHP to enable uODBC using ``./configure --with-pdo-odbc=unixODBC,/usr/local``. + + :: + +* Install ``php-odbc`` and ``php-pdo`` along with PHP using your distribution package manager. SQream recommends a minimum of version 7.1 for the best results. + +.. note:: PHP's string size limitations truncates fetched text, which you can override by doing one of the following: + + * Increasing the **php.ini** default setting, such as the *odbc.defaultlrl* to **10000**. + + :: + + * Setting the size limitation in your code before making your connection using **ini_set("odbc.defaultlrl", "10000");**. + + :: + + * Setting the size limitation in your code before fetchng your result using **odbc_longreadlen($result, "10000");**. + +Operating PHP +------------------- +After configuring PHP, you can test your connection. + +**To test your connection:** + +#. Create a test connection file using the correct parameters for your SQream installation, as shown below: + + .. literalinclude:: test.php + :language: php + :emphasize-lines: 4 + :linenos: + + For more information, download the sample :download:`PHP example connection file ` shown above. + + The following is an example of a valid DSN line: + + .. code:: php + + $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; + +#. Run the PHP file either directly with PHP (``php test.php``) or through a browser. + + For more information about supported DSN parameters, see :ref:`dsn_params`. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst new file mode 100644 index 000000000..c088db851 --- /dev/null +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -0,0 +1,143 @@ +.. _power_bi: + +************************* +Connect to SQream Using Power BI Desktop +************************* + +Overview +========= +**Power BI Desktop** lets you connect to SQream and use underlying data as with other data sources in Power BI Desktop. + +SQream integrates with Power BI Desktop to do the following: + +* Extract and transform your datasets into usable visual models in approximately one minute. + + :: + +* Use **DAX** functions **(Data Analysis Expressions)** to analyze your datasets. + + :: + +* Refresh datasets as needed or by using scheduled jobs. + +SQream uses Power BI for extracting data sets using the following methods: + +* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide `_. + + :: + +* **Import** - Lets you extract datasets from remote databases. + +The **Connect to SQream Using Power BI** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------------- +To connect to SQream, the following must be installed: + +* **ODBC data source administrator** - 32 or 64, depending on your operating system. For Windows users, the ODBC data source administrator is embedded within the operating system. + +* **SQream driver** - The SQream application required for interacting with the ODBC according to the configuration specified in the ODBC administrator tool. + +Installing Power BI Desktop +------------------- +**To install Power BI Desktop:** + +1. Download `Power BI Desktop 64x `_. + + :: + +2. Download and configure your ODBC driver. + + For more information about configuring your ODBC driver, see `ODBC `_. + +3. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. + + :: + +4. In the **Power BI Desktop** folder, create a folder called **Custom Connectors**. + + +5. From the Client Drivers page, download the **PowerQuery.mez** file. + + :: + +5. Save the PowerQuery.mez file in the **Custom Connectors** folder you created in Step 3. + + :: + +6. Open the Power BI application. + + :: + +7. Navigate to **File** > **Options and Settings** > **Option** > **Security** > **Data Extensions**, and select **(Not Recommended) Allow any extension to load without validation or warning**. + + :: + +8. Restart the Power BI Desktop application. + + :: + +9. From the **Get Data** menu, select **SQream**. + + :: + +10. Click **Connect** and provide the information shown in the following table: + + .. list-table:: + :widths: 6 31 + :header-rows: 1 + + * - Element Name + - Description + * - Server + - Provide the network address to your database server. You can use a hostname or an IP address. + * - Port + - Provide the port that the database is responding to at the network address. + * - Database + - Provide the name of your database or the schema on your database server. + * - User + - Provide a SQreamdb username. + * - Passwords + - Provide a password for your user. + +11. Under **Data Connectivity mode**, select **DirectQuery mode**. + + :: + +12. Click **Connect**. + + :: + +13. Provide your user name and password and click **Connect**. + +Best Practices for Power BI +--------------- +SQream recommends using Power BI in the following ways for acquiring the best performance metrics: + +* Creating bar, pie, line, or plot charts when illustrating one or more columns. + + :: + +* Displaying trends and statuses using visual models. + + :: + +* Creating a unified view using **PowerQuery** to connect different data sources into a single dashboard. + +Supported SQream Driver Versions +--------------- +SQream supports the following SQream driver versions: + +* The **PowerQuery Connector** is an additional layer on top of the ODBC. + + :: + +* SQream Driver Installation (ODBC v4.1.1) - Contact your administrator for the link to download ODBC v4.1.1. + +Related Information +------------------- +For more information, see the `Glossary `_. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/r.rst b/connecting_to_sqream/client_platforms/r.rst new file mode 100644 index 000000000..c84bf901b --- /dev/null +++ b/connecting_to_sqream/client_platforms/r.rst @@ -0,0 +1,151 @@ +.. _r: + +***************************** +Connect to SQream Using R +***************************** + +You can use R to interact with a SQream DB cluster. + +This tutorial is a guide that will show you how to connect R to SQream DB. + +.. contents:: In this topic: + :local: + +JDBC +========= + + +#. Get the :ref:`SQream DB JDBC driver`. + +#. + In R, install RJDBC + + .. code-block:: rconsole + + > install.packages("RJDBC") + Installing package into 'C:/Users/r/...' + (as 'lib' is unspecified) + + package 'RJDBC' successfully unpacked and MD5 sums checked + +#. + Import the RJDBC library + + .. code-block:: rconsole + + > library(RJDBC) + +#. + Set the classpath and initialize the JDBC driver which was previously installed. For example, on Windows: + + .. code-block:: rconsole + + > cp = c("C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") + > .jinit(classpath=cp) + > drv <- JDBC("com.sqream.jdbc.SQDriver","C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") +#. + Open a connection with a :ref:`JDBC connection string` and run your first statement + + .. code-block:: rconsole + + > con <- dbConnect(drv,"jdbc:Sqream://127.0.0.1:3108/master;user=rhendricks;password=Tr0ub4dor&3;cluster=true") + + > dbGetQuery(con,"select top 5 * from t") + xint xtinyint xsmallint xbigint + 1 1 82 5067 1 + 2 2 14 1756 2 + 3 3 91 22356 3 + 4 4 84 17232 4 + 5 5 13 14315 5 + +#. + Close the connection + + .. code-block:: rconsole + + > close(con) + +A full example +----------------- + +.. code-block:: rconsole + + > library(RJDBC) + > cp = c("C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") + > .jinit(classpath=cp) + > drv <- JDBC("com.sqream.jdbc.SQDriver","C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") + > con <- dbConnect(drv,"jdbc:Sqream://127.0.0.1:3108/master;user=rhendricks;password=Tr0ub4dor&3;cluster=true") + > dbGetQuery(con,"select top 5 * from t") + xint xtinyint xsmallint xbigint + 1 1 82 5067 1 + 2 2 14 1756 2 + 3 3 91 22356 3 + 4 4 84 17232 4 + 5 5 13 14315 5 + > close(con) + +ODBC +========= + +#. Install the :ref:`SQream DB ODBC driver` for your operating system, and create a DSN. + +#. + In R, install RODBC + + .. code-block:: rconsole + + > install.packages("RODBC") + Installing package into 'C:/Users/r/...' + (as 'lib' is unspecified) + + package 'RODBC' successfully unpacked and MD5 sums checked + +#. + Import the RODBC library + + .. code-block:: rconsole + + > library(RODBC) + +#. + Open a connection handle to an existing DSN (``my_cool_dsn`` in this example) + + .. code-block:: rconsole + + > ch <- odbcConnect("my_cool_dsn",believeNRows=F) + +#. + Run your first statement + + .. code-block:: rconsole + + > sqlQuery(ch,"select top 5 * from t") + xint xtinyint xsmallint xbigint + 1 1 82 5067 1 + 2 2 14 1756 2 + 3 3 91 22356 3 + 4 4 84 17232 4 + 5 5 13 14315 5 + +#. + Close the connection + + .. code-block:: rconsole + + > close(ch) + +A full example +----------------- + +.. code-block:: rconsole + + > library(RODBC) + > ch <- odbcConnect("my_cool_dsn",believeNRows=F) + > sqlQuery(ch,"select top 5 * from t") + xint xtinyint xsmallint xbigint + 1 1 82 5067 1 + 2 2 14 1756 2 + 3 3 91 22356 3 + 4 4 84 17232 4 + 5 5 13 14315 5 + > close(ch) diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst new file mode 100644 index 000000000..83942ccfd --- /dev/null +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -0,0 +1,185 @@ +.. _connect_to_sas_viya: + +************************* +Connect to SQream Using SAS Viya +************************* + +Overview +========== +SAS Viya is a cloud-enabled analytics engine used for producing useful insights. The **Connect to SQream Using SAS Viya** page describes how to connect to SAS Viya, and describes the following: + +.. contents:: + :local: + :depth: 1 + +Installing SAS Viya +------------------- +The **Installing SAS Viya** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Downloading SAS Viya +~~~~~~~~~~~~~~~~~~ +Integrating with SQream has been tested with SAS Viya v.03.05 and newer. + +To download SAS Viya, see `SAS Viya `_. + +Installing the JDBC Driver +~~~~~~~~~~~~~~~~~~ +The SQream JDBC driver is required for establishing a connection between SAS Viya and SQream. + +**To install the JDBC driver:** + +#. Download the `JDBC driver `_. + + :: + +#. Unzip the JDBC driver into a location on the SAS Viya server. + + SQream recommends creating the directory ``/opt/sqream`` on the SAS Viya server. + +Configuring SAS Viya +------------------- +After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQream Studio. + +**To configure the JDBC driver from the SAS Studio:** + +#. Sign in to the SAS Studio. + + :: + +#. From the **New** menu, click **SAS Program**. + + :: + +#. Configure the SQream JDBC connector by adding the following rows: + + .. literalinclude:: connect3.sas + :language: php + +For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String `_. + +Operating SAS Viya +-------------------- +The **Operating SAS Viya** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Using SAS Viya Visual Analytics +~~~~~~~~~~~~~~~~~~ +This section describes how to use SAS Viya Visual Analytics. + +**To use SAS Viya Visual Analytics:** + +#. Log in to `SAS Viya Visual Analytics `_ using your credentials: + + :: + +2. Click **New Report**. + + :: + +3. Click **Data**. + + :: + +4. Click **Data Sources**. + + :: + +5. Click the **Connect** icon. + + :: + +6. From the **Type** menu, select **Database**. + + :: + +7. Provide the required information and select **Persist this connection beyond the current session**. + + :: + +8. Click **Advanced** and provide the required information. + + :: + +9. Add the following additional parameters by clicking **Add Parameters**: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - Name + - Value + * - class + - com.sqream.jdbc.SQDriver + * - classPath + - ** + * - url + - \jdbc:Sqream://**:**/**;cluster=true + * - username + - + * - password + - + +10. Click **Test Connection**. + + :: + +11. If the connection is successful, click **Save**. + +If your connection is not successful, see :ref:`troubleshooting_sas_viya` below. + +.. _troubleshooting_sas_viya: + +Troubleshooting SAS Viya +------------------------- +The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: + +.. contents:: + :local: + :depth: 1 + +Inserting Only Required Data +~~~~~~~~~~~~~~~~~~ +When using SAS Viya, SQream recommends using only data that you need, as described below: + +* Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. + + :: + +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. + +Creating a Separate Service for SAS Viya +~~~~~~~~~~~~~~~~~~ +SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. + +Locating the SQream JDBC Driver +~~~~~~~~~~~~~~~~~~ +In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: + +.. code-block:: text + + java.lang.ClassNotFoundException: com.sqream.jdbc.SQDriver + +**To locate the SQream JDBC driver:** + +1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. + + :: + +2. Verify that the classpath in your SAS program is correct, and that SAS Viya can access the file that it references. + + :: + +3. Restart SAS Viya. + +For more troubleshooting assistance, see the `SQream Support Portal `_. + +Supporting TEXT +~~~~~~~~~~~~~~~~~~ +In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst new file mode 100644 index 000000000..16265ebd4 --- /dev/null +++ b/connecting_to_sqream/client_platforms/sql_workbench.rst @@ -0,0 +1,135 @@ +.. _connect_to_sql_workbench: + +***************************** +Connect to SQream Using SQL Workbench +***************************** + +You can use SQL Workbench to interact with a SQream DB cluster. SQL Workbench/J is a free SQL query tool, and is designed to run on any JRE-enabled environment. + +This tutorial is a guide that will show you how to connect SQL Workbench to SQream DB. + +.. contents:: In this topic: + :local: + +Installing SQL Workbench with the SQream DB installer (Windows only) +===================================================================== + +SQream DB's driver installer for Windows can install the Java prerequisites and SQL Workbench for you. + +#. Get the JDBC driver installer available for download from the `SQream Drivers page `_. The Windows installer takes care of the Java prerequisites and subsequent configuration. + +#. Install the driver by following the on-screen instructions in the easy-to-follow installer. + By default, the installer does not install SQL Workbench. Make sure to select the item! + + .. image:: /_static/images/jdbc_windows_installer_screen.png + +.. note:: The installer will install SQL Workbench in ``C:\Program Files\SQream Technologies\SQLWorkbench`` by default. You can change this path during the installation. + +#. Once finished, SQL Workbench is installed and contains the necessary configuration for connecting to SQream DB clusters. + +#. Start SQL Workbench from the Windows start menu. Be sure to select **SQL Workbench (64)** if you're on 64-bit Windows. + + .. image:: /_static/images/sql_workbench_launch.png + +You are now ready to create a profile for your cluster. Continue to :ref:`Creating a new connection profile `. + +Installing SQL Workbench manually (Linux, MacOS) +=================================================== + +Install Java Runtime +------------------------ + +Both SQL Workbench and the SQream DB JDBC driver require Java 1.8 or newer. You can install either Oracle Java or OpenJDK. + +**Oracle Java** + +Download and install Java 8 from Oracle for your platform - https://www.java.com/en/download/manual.jsp + +**OpenJDK** + +For Linux and BSD, see https://openjdk.java.net/install/ + +For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk + +Get the SQream DB JDBC driver +------------------------------- + +SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page `_. + +Download and extract the JAR file from the zip archive. + +Install SQL Workbench +----------------------- + +#. Download the latest stable release from https://www.sql-workbench.eu/downloads.html . The **Generic package for all systems** is recommended. + +#. Extract the downloaded ZIP archive into a directory of your choice. + +#. Start SQL workbench. If you are using 64 bit windows, run ``SQLWorkbench64.exe`` instead of ``SQLWOrkbench.exe``. + +Setting up the SQream DB JDBC driver profile +--------------------------------------------- + +#. Define a connection profile - :menuselection:`&File --> &Connect window (Alt+C)` + + .. image:: /_static/images/sql_workbench_connect_window1.png + +#. Open the drivers management window - :menuselection:`&Manage Drivers` + + .. image:: /_static/images/sql_workbench_manage_drivers.png + + + +#. Create the SQream DB driver profile + + .. image:: /_static/images/sql_workbench_create_driver.png + + #. Click on the Add new driver button ("New" icon) + + #. Name the driver as you see fit. We recommend calling it SQream DB , where is the version you have installed. + + #. + Add the JDBC drivers from the location where you extracted the SQream DB JDBC JAR. + + If you used the SQream installer, the file will be in ``C:\Program Files\SQream Technologies\JDBC Driver\`` + + #. Click the magnifying glass button to detect the classname automatically. Other details are purely optional + + #. Click OK to save and return to "new connection screen" + + +.. _new_connection_profile: + +Create a new connection profile for your cluster +===================================================== + + .. image:: /_static/images/sql_workbench_connection_profile.png + +#. Create new connection by clicking the New icon (top left) + +#. Give your connection a descriptive name + +#. Select the SQream Driver that was created in the previous screen + +#. Type in your connection string. To find out more about your connection string (URL), see the :ref:`Connection string documentation `. + +#. Text the connection details + +#. Click OK to save the connection profile and connect to SQream DB + +Suggested optional configuration +================================== + +If you installed SQL Workbench manually, you can set a customization to help SQL Workbench show information correctly in the DB Explorer panel. + +#. Locate your workbench.settings file + On Windows, typically: ``C:\Users\\.sqlworkbench\workbench.settings`` + On Linux, ``$HOME/.sqlworkbench`` + +#. Add the following line at the end of the file: + + .. code-block:: text + + workbench.db.sqreamdb.schema.retrieve.change.catalog=true + +#. Save the file and restart SQL Workbench diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst new file mode 100644 index 000000000..ac67c8d55 --- /dev/null +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -0,0 +1,453 @@ +.. _connect_to_tableau: + +************************* +Connecting to SQream Using Tableau +************************* + +Overview +===================== +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. + +The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. + +For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. + +The Connecting to SQream Using Tableau page describes the following: + +.. contents:: + :local: + +Installing the JDBC Driver and Tableau Connector Plugin +------------------- +This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. + +**To connect to SQream using Tableau:** + +#. Install the Tableau Desktop application. + + For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. + + :: + +#. Do one of the following: + + * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. + * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. + +.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. + +.. _tableau_windows_installer: + +Installing the JDBC Driver Using the Windows Installer +~~~~~~~~~~~~~~~~~~ +If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. + +**To install Tableau using the Windows installer**: + +#. Close Tableau Desktop. + + :: + +#. Download the most current version of the `SQream JDBC driver `_. + + :: + +#. Do the following: + + #. Start the installer. + #. Verify that the **Tableau Desktop connector** item is selected. + #. Follow the installation steps. + + :: + +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. + +.. _tableau_jdbc_installer: + +Installing the JDBC Driver Manually +~~~~~~~~~~~~~ +If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. + +**To install the JDBC driver manually:** + +1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. + + :: + +#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. + + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: + + * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + +.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. + +Note the following when installing the JDBC driver: + +* You must have read permissions on the .jar file. +* Tableau requires a JDBC 4.0 or later driver. +* Tableau requires a Type 4 JDBC driver. +* The latest 64-bit version of Java 8 is installed. + +3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. + + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: + + * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* + * **Tableau Desktop on Mac:** *~/My Tableau Repository/Connectors* + + :: + +4. *Optional* - If you are using the Tableau Server, do the following: + + 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. + + This directory needs to exist on all Tableau servers. + + :: + + 2. Copy the SQreamDB.taco file into the new directory. + + :: + + 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: + + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors + + If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: + + .. code-block:: console + + $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys + + 4. To apply the pending configuration changes, run the following command: + + .. code-block:: console + + $ tsm pending-changes apply + + .. warning:: This restarts the server. + +You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. + +.. _tableau_connect_to_sqream: + + +Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier +-------------- + + +This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: + +.. contents:: + :local: + +.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. + +Automatically Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: + +.. image:: /_static/images/odbc_windows_installer_tableau.png + +SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. + +For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. + +If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. + +.. _manually_reconfigure_odbc_driver: + +Manually Reconfiguring the ODBC Driver After Initial Installation +~~~~~~~~~~~~~~~~~~ +The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. + +**To manually reconfigure the ODBC driver after initial installation:** + +1. Do one of the following: + + 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. + + :: + + 2. Copy the text below into a text editor: + + .. literalinclude:: odbc-sqream.tdc + :language: xml + :caption: SQream ODBC TDC File + :emphasize-lines: 2 + +#. Check which version of Tableau you are using. + + :: + +#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. + + For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. + + :: + +#. Do one of the following: + + * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. + + :: + + * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. + +Configuring the ODBC Connection +~~~~~~~~~~~~ +The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. + +**To configure the ODBC connection:** + +1. Create an ODBC DSN. + + :: + +#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. + + :: + +#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. + + During installation, the installer created a sample user DSN named **SQreamDB**. + + :: + +#. *Optional* - Do one or both of the following: + + * Modify the DSN name. + + :: + + * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. + +.. image:: /_static/images/odbc_windows_dsns.png + + +5. Click **Finish**. + + :: + +6. Enter your connection parameters. + + The following table describes the connection parameters: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 + + * - Item + - Description + - Example + * - Data Source Name + - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. + - + * - Description + - The description of your DSN. This field is optional. + - + * - User + - The username of a role to use for establishing the connection. + - ``rhendricks`` + * - Password + - The password of the selected role. + - ``Tr0ub4dor`` + * - Database + - The database name to connect to. For example, ``master`` + - ``master`` + * - Service + - The :ref:`service queue` to use. + - For example, ``etl``. For the default service ``sqream``, leave blank. + * - Server + - The hostname of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - The TCP port of the SQream worker. + - ``5000`` or ``3108`` + * - User Server Picker + - Uses the load balancer when establishing a connection. Use only if exists, and check port. + - + * - SSL + - Uses SSL when establishing a connection. + - + * - Logging Options + - Lets you modify your logging options when tracking the ODBC connection for connection issues. + - + +.. tip:: Test the connection by clicking **Test** before saving your DSN. + +7. Save the DSN by clicking **OK.** + +Connecting Tableau to SQream +~~~~~~~~~~~~ +**To connect Tableau to SQream:** + +1. Start Tableau Desktop. + + :: + +#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. + + The **Other Databases (ODBC)** window is displayed. + + :: + +#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. + + Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. + +#. Provide your username and password and click **OK**. + +.. _tableau_connect_to_sqream_db: + + +Connecting to SQream +--------------------- +After installing the JDBC driver you can connect to SQream. + +**To connect to SQream:** + +#. Start Tableau Desktop. + + :: + +#. In the **Connect** menu, in the **To a Server** sub-menu, click **More...**. + + More connection options are displayed. + + :: + +#. Select **SQream DB by SQream Technologies**. + + The **New Connection** dialog box is displayed. + + :: + +#. In the New Connection dialog box, fill in the fields and click **Sign In**. + + The following table describes the fields: + + .. list-table:: + :widths: 15 38 38 + :header-rows: 1 + + * - Item + - Description + - Example + * - Server + - Defines the server of the SQream worker. + - ``127.0.0.1`` or ``sqream.mynetwork.co`` + * - Port + - Defines the TCP port of the SQream worker. + - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL. + * - Database + - Defines the database to establish a connection with. + - ``master`` + * - Cluster + - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection. + - + * - Username + - Specifies the username of a role to use when connecting. + - ``rhendricks`` + * - Password + - Specifies the password of the selected role. + - ``Tr0ub4dor&3`` + * - Require SSL (recommended) + - Sets SSL as a requirement for establishing this connection. + - + +The connection is established and the data source page is displayed. + +.. tip:: + Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. + +.. _set_up_sqream_tables_as_data_sources: + +Setting Up SQream Tables as Data Sources +---------------- +After connecting to SQream you must set up the SQream tables as data sources. + +**To set up SQream tables as data sources:** + +1. From the **Table** menu, select the desired database and schema. + + SQream's default schema is **public**. + + :: + +#. Drag the desired tables into the main area (labeled **Drag tables here**). + + This area is also used for specifying joins and data source filters. + + :: + +#. Open a new sheet to analyze data. + +.. tip:: + For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. + +Tableau Best Practices and Troubleshooting +--------------- +This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: + +.. contents:: + :local: + +Inserting Only Required Data +~~~~~~~~~~~~~~~~~~ +When using Tableau, SQream recommends using only data that you need, as described below: + +* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. + + :: + +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. + +Using Tableau's Table Query Syntax +~~~~~~~~~~~~~~~~~~~ +Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. + +Creating a Separate Service for Tableau +~~~~~~~~~~~~~~~~~~~ +SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. + +Troubleshooting Workbook Performance Before Deploying to the Tableau Server +~~~~~~~~~~~~~~~~~~~ +Tableau has a built-in `performance recorder `_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. + +Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. + +Troubleshooting Error Codes +~~~~~~~~~~~~~~~~~~~ +Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: + +.. code-block:: console + + Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect + +**To troubleshoot error codes:** + +If Tableau cannot locate the SQream JDBC driver, do the following: + + 1. Verify that the JDBC driver is located in the correct directory: + + * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + + 2. Find the file path for the JDBC driver and add it to the Java classpath: + + * **For Linux** - ``export CLASSPATH=;$CLASSPATH`` + + :: + + * **For Windows** - add an environment variable for the classpath: + + .. image:: /_static/images/Third_Party_Connectors/tableau/envrionment_variable_for_classpath.png + +If you experience issues after restarting Tableau, see the `SQream support portal `_. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst new file mode 100644 index 000000000..2a4d2658a --- /dev/null +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -0,0 +1,204 @@ +.. _talend: + +************************* +Connecting to SQream Using Talend +************************* + +.. _top: + +Overview +================= + +This page describes how to use Talend to interact with a SQream DB cluster. The Talend connector is used for reading data from a SQream DB cluster and loading data into SQream DB. + +In addition, this page provides a viability report on Talend's comptability with SQream DB for stakeholders. + +It includes the following: + +* :ref:`A Quick Start guide ` +* :ref:`Information about supported SQream drivers ` +* :ref:`Supported data sources ` and :ref:`tool and operating system versions ` +* :ref:`A description of known issues ` +* :ref:`Related links ` + + +About Talend +================= +Talend is an open-source data integration platform. It provides various software and services for Big Data integration and management, enterprise application integration, data quality and cloud storage. + +For more information about Talend, see `Talend `_. + + +.. _quickstart_guide: + +Quick Start Guide +======================= + +Creating a New Metadata JDBC DB Connection +------------- +**To create a new metadata JDBC DB connection:** + +1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_1.png + +2. Select **Create connection**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_2.png + +3. In the **Name** field, type a name. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_3.png + +The name cannot contain spaces. + +4. In the **Purpose** field, type a purpose and click **Next**. You cannot go to the next step until you define both a Name and a Purpose. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_4.png + +5. In the **DB Type** field, select **JDBC**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_5.png + +6. In the **JDBC URL** field, type the relevant connection string. + + For connection string examples, see `Connection Strings `_. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_6.png + +7. In the **Drivers** field, click the **Add** button. + + The **"newLine** entry is added. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_7.png + +8. One the **"newLine** entry, click the ellipsis. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_8.png + +The **Module** window is displayed. + +9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.png + +10. Click the ellipsis. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.5.png + +Your hard drive is displayed. + +11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.4.0.jar**)and click **Open**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_10.png + +12. Click **Detect the module install status**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_11.5.png + +13. Click **OK**. + +The JDBC that you selected is displayed in the **Driver** field. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_12.png + +14. Click **Select class name**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_13.png + +15. Click **Test connection**. + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_14.png + +If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: + +.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_15.png + +After creating a new metadata JDBC DB connection, you can do the following: + + * Use your new metadata connection. + * Drag it to the **job** screen. + * Build Talend components. + +For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. + +:ref:`Back to top ` + +.. _supported_sqream_drivers: + +Supported SQream Drivers +================ + +The following list shows the supported SQream drivers and versions: + +* **JDBC** - Version 4.3.3 and higher. +* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. + +:ref:`Back to top ` + + +.. _supported_data_sources: + +Supported Data Sources +============================ +Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. + +* **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. + +* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. + +:ref:`Back to top ` + + +.. _supported_tools_os_sys_versions: + +Supported Tool and Operating System Versions +====================== +Talend was tested using the following: + +* Talend version 7.4.1M6 +* Windows 10 +* SQream version 2021.1 +* JDBC version + + + + +:ref:`Back to top ` + + +.. _known_issues: + +Known Issues +=========================== +The the list below describes the following known issues as of 6/1/2021: + +* Schemas not displayed for tables with identical names. + +:ref:`Back to top ` + + +.. _related_links: + +Related Links +=============== +The following is a list of links relevant to the Talend connector: + +* `Talend Home page `_ +* `Talend Community page `_ +* `Talend BugTracker `_ + + +Download Links +================== +The following is a list of download links relevant to the Talend connector: + +* `Talend Open Studio for Big Data `_ +* `Latest version of SQream JDBC `_ + +:ref:`Back to top ` + + + +.. contents:: In this topic: + :local: diff --git a/connecting_to_sqream/client_platforms/test.php b/connecting_to_sqream/client_platforms/test.php new file mode 100644 index 000000000..88ec88338 --- /dev/null +++ b/connecting_to_sqream/client_platforms/test.php @@ -0,0 +1,16 @@ + diff --git a/connecting_to_sqream/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst new file mode 100644 index 000000000..4c032ba84 --- /dev/null +++ b/connecting_to_sqream/client_platforms/tibco_spotfire.rst @@ -0,0 +1,387 @@ +.. _tibco_spotfire: + + +************************* +Connecting to SQream Using TIBCO Spotfire +************************* +Overview +========= +The **TIBCO Spotfire** software is an analytics solution that enables visualizing and exploring data through dashboards and advanced analytics. + +This document is a Quick Start Guide that describes the following: + +.. contents:: + :local: + :depth: 1 + +Establishing a Connection between TIBCO Spotfire and SQream +----------------- +TIBCO Spotfire supports the following versions: + +* **JDBC driver** - Version 4.5.2 +* **ODBC driver** - Version 4.1.1 + +SQream supports TIBCO Spotfire version 7.12.0. + +The **Establishing a JDBC Connection between TIBCO Spotfire and SQream** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Creating a JDBC Connection +~~~~~~~~~~~ +For TIBCO Spotfire to recognize SQream, you must add the correct JDBC jar file to Spotfire's loaded binary folder. The following is an example of a path to the Spotfire loaded binaries folder: ``C:\tibco\tss\7.12.0\tomcat\bin``. + +For the complete TIBCO Spotfire documentation, see `TIBCO Spotfire® JDBC Data Access Connectivity Details `_. + +Creating an ODBC Connection +~~~~~~~~~~~ +**To create an ODBC connection** + +1. Install and configure ODBC on Windows. + + For more information, see :ref:`Install and Configure ODBC on Windows`. + +#. Launch the TIBCO Spotfire application. + + :: + +#. From the **File** menu click **Add Data Tables**. + + The **Add Database Tables** window is displayed. + +#. Click **Add** and select **Database**. + + The **Open Database** window is displayed. + +#. In the **Data source type** area, select **ODBC SQream** (Odbc Data Provider) and click **Configure**. + + The **Configure Data Source and Connection** window is displayed. + +#. Select **System or user data source** and from the drop-down menu select the DSN of your data source (SQreamDB). + + :: + +#. Provide your database username and password and click **OK**. + + :: + +#. In the **Open Database** window, click **OK**. + + The **Specify Tables and Columns** window is displayed. + +#. In the **Specify Tables and Columns** window, select the checkboxes corresponding to the tables and columns that you want to include in your SQL statement. + + :: + +#. In the **Data source name** field, set your data source name and click **OK**. + + Your data source is displayed in the **Data tables** area. + +#. In the **Add Data Tables** dialog, click **OK** to load the data from your ODBC data source into Spotfire. + +.. note:: Verify that you have checked the SQL statement. + +Creating the SQream Data Source Template +~~~~~~~~~~~ +After creating a connection, you can create your SQream data source template. + +**To create your SQream data source template:** + +1. Log in to the TIBCO Spotfire Server Configuration Tool. + + :: + +#. From the **Configuration** tab, in the **Configuration Start** menu, click **Data Source Templates**. + + The **Data Source Templates** list is displayed. + +#. From the Data Source Templates list do one of the following: + + * Override an existing template: + + 1. In the template text field, select an existing template. + + :: + + 2. Copy and paste your data source template text. + + :: + + * Create a new template: + + 1. Click **New**. + + The **Add Data Source Template** window is displayed. + + .. _creating_sqream_data_source_template: + + 2. In the **Name** field, define your template name. + + :: + + 3. In the **Data Source Template** text field, copy and paste your data source template text. + + The following is an example of a data source template: + + .. code-block:: console + + + SQream + com.sqream.jdbc.SQDriver + jdbc:Sqream://<host>:<port>/database;user=sqream;password=sqream;cluster=true + true + true + false + TABLE,EXTERNAL_TABLE + + + Bool + Integer + + + VARCHAR(2048) + String + + + INT + Integer + + + BIGINT + LongInteger + + + Real + Real + + + Decimal + Float + + + Numeric + Float + + + Date + DATE + + + DateTime + DateTime + + + + + +4. Click **Save configuration**. + + :: + +5. Close and restart your Spotfire server. + +Creating a Data Source +~~~~~~~~~~~ +After creating the SQream data source template, you can create a data source. + +**To create a data source:** + +1. Launch the TIBCO Spotfire application. + + :: + +#. From the **Tools** menu, select **Information Designer**. + + The **Information Designer** window is displayed. + + :: + +#. From the **New** menu, click **Data Source**. + + The **Data Source** tab is displayed. + + :: + +#. Provide the following information: + + * **Name** - define a unique name. + + :: + + * **Type** - use the same type template name you used while configuring your template. See **Step 3** in :ref:`Creating the SQream Data Source Template`. + + :: + + * **Connection URL** - use the standard JDBC connection string, ``:/database``. + + :: + + * **No. of connections** - define a number between **1** and **100**. SQream recommends setting your number of connections to **100**. + + :: + + * **Username and Password** - define your SQream username and password. + +Creating an Information Link +~~~~~~~~~~~ +After creating a data source, you can create an information link. + +**To create an information link**: + +1. From the **Tools** menu, select **Information Designer**. + + The **Information Designer** window is displayed. + + :: + +#. From the **New** menu, click **Information Link**. + + The **Information link** tab is displayed. + +#. From the **Elements** tab, select a column type and click **Add**. + + The column type is added to the **Elements** region as a filter. + + Note the following: + + * You can select procedures from the Elements region. + + :: + + * You can remove an element by selecting an element and clicking **Remove**. + + .. tip:: If the Elements menu is not displayed, you can display it by clicking the **Elements** tab. You can simultaneously select multiple elements by pressing **Ctrl** and making additional selections, and select a range of elements by holding **Shift** and clicking two elements. + +#. If the elements you select originate from more than one data source table, specify a **Join path**. + +5. *Optional* - In the **Description** region, type the description of the information link. + + :: + +#. *Optional* - To filter your data, expand the **Filters** section and do the following: + + 1. From the **Information Link** region, select the element you added in Step 3 above. + + :: + + 2. Click **Add**. + + The **Add Column** window is displayed. + + 3. From the drop-down list, select a column to add a hard filter to and click **OK**. + + The selected column is added to the Filters list. + + 4. Repeat steps 2 and 3 to add filters to additional columns. + + :: + + 5. For each column, from the **Filter Type** drop-down list, select **range** or **values**. + + .. note:: Filtering by range means entering the upper and lower limits of the desired range. Filtering by values means entering the exact values that you want to include in the returned data, separated by semicolon. + + 6. In the **Values** field type the desired values separated with semicolons, or set the upper and lower limits in the **Min Value** and **Max Value** fields. Alternatively, you can type ``?param_name`` in the Values field to use a parameter as the filter for the selected column, where ``param_name`` is the name used to identify the parameter. + + .. note:: Because limits are inclusive, setting the lower limit to **1000** includes the value **1000** in the data table. + + .. note:: When setting upper and lower limits on **String** type columns, ``A`` precedes ``AA``, and a lone letter precedes words beginning with that latter. For example, ``S** precedes **Smith**, indicating that the name ``Smith`` will not be present when you select names from ``D`` to ``S``. The order of characters is standard ASCII. + + For more information on adding filters, see `Adding Hard Filters `_. + +7. *Optional* - To add runtime filtering prompts, expand the **Prompts** section and do the following: + + 1. Click **Add**. + + The **Add Column** window is displayed. + + #. From the **Select column** list, select a column to add a prompt to and click **OK**. + + The selected column is added to the Prompts list. + + #. Repeat **Step 1** to add prompts to additional columns. + + :: + + #. Do the following for each column: + + * Make a selection from the **Prompt Type** drop-down list. + * Select or clear **Mandatory**. + * *Optional* - Set your **Max Selections**. + + For more information on adding prompts, see `Adding Prompts `_. + +8. *Optional* - Expand the **Conditioning** section and specify one of the following conditions: + + * None + * Distinct + * Pivot + + Note that you can edit the Pivot conditioning by selecting **Pivot** and clicking **Edit**. + +9. *Optional* - Expand the **Parameters** section and define your parameters. + + :: + +10. *Optional* - Expand the **Properties** section and define your properties. + + :: + +11. *Optional* - Expand the **Caching** section and enable or disable whether your information link can be cached. + + :: + +12. Click **Save**. + + The **Save As** window is displayed. + +13. In the tree, select where you want to save the information link. + + :: + +14. In the **Name** field, type a name and description for the information link. + + :: + + +15. Click **Save**. + + The new information link is added to the library and can be accessed by other users. + +.. tip:: You can test the information link directly by clicking **Open Data**. You can also view and edit the SQL belonging to the information link by clicking **SQL**. + +For more information on the Information Link attributes, see `Information Link Tab `_. + +Troubleshooting +------------- +The **Troubleshooting** section describes the following scenarios: + +.. contents:: + :local: + :depth: 1 + +The JDBC Driver does not Support Boolean, Decimal, or Numeric Types +~~~~~~~~~~~ +When attempting to load data, the the Boolean, Decimal, or Numeric column types are not supported and generate the following error: + +.. code-block:: console + + Failed to execute query: Unsupported JDBC data type in query result: Bool (HRESULT: 80131500) + +The error above is resolved by casting the columns as follows: + +* ``Bool`` columns to ``INT``. +* ``Decimal`` and ``Numeric`` columns to ``REAL``. + +For more information, see the following: + +* **Resolving this error** - `Details on Change Data Types `_. + +* **Supported data types** - :ref:`Data Types`. + +Information Services do not Support Live Queries +~~~~~~~~~~~ +TIBCO Spotfire data connectors support live queries, but no APIs currently exist for creating custom data connectors. This is resolved by creating a customized SQream adapter using TIBCO's **Data Virtualization (TDV)** or the **Spotfire Advanced Services (ADS)**. These can be used from the built-in TDV connector to enable live queries. + +This resolution applies to JDBC and ODBC drivers. \ No newline at end of file diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index a790f085d..ecb9e4715 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,4 +1,4 @@ -.. _third_party_tools: +.. _connecting_to_sqream: ************************* Connecting to SQream @@ -12,6 +12,7 @@ This section provides information about the following third party tools: :glob: :titlesonly: + client_platforms/index client_drivers/index If you need a tool that SQream does not support, contact SQream Support or your SQream account manager for more information. \ No newline at end of file From e46f40bc2d874b9de4a13f7aea69f2a197db2663 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 20 Jul 2022 15:02:18 +0300 Subject: [PATCH 0130/1892] Fixed links (changed to 2022.1) --- .../client_platforms/informatica.rst | 2 +- .../client_platforms/microstrategy.rst | 2 +- connecting_to_sqream/client_platforms/php.rst | 2 +- connecting_to_sqream/client_platforms/power_bi.rst | 6 +++--- connecting_to_sqream/client_platforms/sas_viya.rst | 4 ++-- .../client_platforms/sql_workbench.rst | 14 ++++++++------ connecting_to_sqream/client_platforms/tableau.rst | 2 +- connecting_to_sqream/client_platforms/talend.rst | 2 +- 8 files changed, 18 insertions(+), 16 deletions(-) diff --git a/connecting_to_sqream/client_platforms/informatica.rst b/connecting_to_sqream/client_platforms/informatica.rst index 6bc50b22a..ec39a0129 100644 --- a/connecting_to_sqream/client_platforms/informatica.rst +++ b/connecting_to_sqream/client_platforms/informatica.rst @@ -143,7 +143,7 @@ After establishing a connection between SQream and Informatica you can establish 2. In the **JDBC_IC Connection Properties** section, in the **JDBC Connection URL** field, establish a JDBC connection by providing the correct connection string. - For connection string examples, see `Connection Strings `_. + For connection string examples, see `Connection Strings `_. :: diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index 6cad19be2..370312a0d 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -54,7 +54,7 @@ Connecting a Data Source :: -2. Download the most current version of the `SQream JDBC driver `_. +2. Download the most current version of the `SQream JDBC driver `_. :: diff --git a/connecting_to_sqream/client_platforms/php.rst b/connecting_to_sqream/client_platforms/php.rst index 2310fde6b..ebb2c796f 100644 --- a/connecting_to_sqream/client_platforms/php.rst +++ b/connecting_to_sqream/client_platforms/php.rst @@ -16,7 +16,7 @@ Installing PHP ------------------- **To install PHP:** -1. Download the JDBC driver installer from the `SQream Drivers page `_. +1. Download the JDBC driver installer from the `SQream Drivers page `_. :: diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index c088db851..1cdf7c81b 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -22,7 +22,7 @@ SQream integrates with Power BI Desktop to do the following: SQream uses Power BI for extracting data sets using the following methods: -* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide `_. +* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide `_. :: @@ -52,7 +52,7 @@ Installing Power BI Desktop 2. Download and configure your ODBC driver. - For more information about configuring your ODBC driver, see `ODBC `_. + For more information about configuring your ODBC driver, see `ODBC `_. 3. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. @@ -140,4 +140,4 @@ SQream supports the following SQream driver versions: Related Information ------------------- -For more information, see the `Glossary `_. \ No newline at end of file +For more information, see the `Glossary `_. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index 83942ccfd..ef4a338a4 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -32,7 +32,7 @@ The SQream JDBC driver is required for establishing a connection between SAS Viy **To install the JDBC driver:** -#. Download the `JDBC driver `_. +#. Download the `JDBC driver `_. :: @@ -59,7 +59,7 @@ After installing the JDBC driver, you must configure the JDBC driver from the SA .. literalinclude:: connect3.sas :language: php -For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String `_. +For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String `_. Operating SAS Viya -------------------- diff --git a/connecting_to_sqream/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst index 16265ebd4..a5f7e8871 100644 --- a/connecting_to_sqream/client_platforms/sql_workbench.rst +++ b/connecting_to_sqream/client_platforms/sql_workbench.rst @@ -11,8 +11,9 @@ This tutorial is a guide that will show you how to connect SQL Workbench to SQre .. contents:: In this topic: :local: -Installing SQL Workbench with the SQream DB installer (Windows only) +Installing SQL Workbench with the SQream Installer ===================================================================== +This section applies to Windows only. SQream DB's driver installer for Windows can install the Java prerequisites and SQL Workbench for you. @@ -33,8 +34,9 @@ SQream DB's driver installer for Windows can install the Java prerequisites and You are now ready to create a profile for your cluster. Continue to :ref:`Creating a new connection profile `. -Installing SQL Workbench manually (Linux, MacOS) +Installing SQL Workbench Manually =================================================== +This section applies to Linux and MacOS only. Install Java Runtime ------------------------ @@ -51,7 +53,7 @@ For Linux and BSD, see https://openjdk.java.net/install/ For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk -Get the SQream DB JDBC driver +Get the SQream DB JDBC Driver ------------------------------- SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page `_. @@ -67,7 +69,7 @@ Install SQL Workbench #. Start SQL workbench. If you are using 64 bit windows, run ``SQLWorkbench64.exe`` instead of ``SQLWOrkbench.exe``. -Setting up the SQream DB JDBC driver profile +Setting up the SQream DB JDBC Driver Profile --------------------------------------------- #. Define a connection profile - :menuselection:`&File --> &Connect window (Alt+C)` @@ -100,7 +102,7 @@ Setting up the SQream DB JDBC driver profile .. _new_connection_profile: -Create a new connection profile for your cluster +Create a New Connection Profile for Your Cluster ===================================================== .. image:: /_static/images/sql_workbench_connection_profile.png @@ -117,7 +119,7 @@ Create a new connection profile for your cluster #. Click OK to save the connection profile and connect to SQream DB -Suggested optional configuration +Suggested Optional Configuration ================================== If you installed SQL Workbench manually, you can set a customization to help SQL Workbench show information correctly in the DB Explorer panel. diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index ac67c8d55..3c08ebe83 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -48,7 +48,7 @@ If you are using Windows, after installing the Tableau Desktop application you c :: -#. Download the most current version of the `SQream JDBC driver `_. +#. Download the most current version of the `SQream JDBC driver `_. :: diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index 2a4d2658a..fc16441b9 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -194,7 +194,7 @@ Download Links The following is a list of download links relevant to the Talend connector: * `Talend Open Studio for Big Data `_ -* `Latest version of SQream JDBC `_ +* `Latest version of SQream JDBC `_ :ref:`Back to top ` From c3c7b867b6b326af44b2fe48254527707473b3d9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 11:52:03 +0300 Subject: [PATCH 0131/1892] Updated Talend with Yotam --- .../client_platforms/talend.rst | 183 +++++------------- 1 file changed, 51 insertions(+), 132 deletions(-) diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index fc16441b9..1aefe8917 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -4,201 +4,120 @@ Connecting to SQream Using Talend ************************* -.. _top: - Overview -================= - -This page describes how to use Talend to interact with a SQream DB cluster. The Talend connector is used for reading data from a SQream DB cluster and loading data into SQream DB. - -In addition, this page provides a viability report on Talend's comptability with SQream DB for stakeholders. - -It includes the following: - -* :ref:`A Quick Start guide ` -* :ref:`Information about supported SQream drivers ` -* :ref:`Supported data sources ` and :ref:`tool and operating system versions ` -* :ref:`A description of known issues ` -* :ref:`Related links ` - - -About Talend -================= -Talend is an open-source data integration platform. It provides various software and services for Big Data integration and management, enterprise application integration, data quality and cloud storage. +================= +This page describes how to use Talend to interact with a SQream cluster. The Talend connector is used for reading data from a SQream cluster and loading data into SQream. In addition, this page provides a viability report on Talend's comptability with SQream for stakeholders. -For more information about Talend, see `Talend `_. +The **Connecting to SQream Using Talend** describes the following: - -.. _quickstart_guide: - -Quick Start Guide -======================= +.. contents:: + :local: + :depth: 1 Creating a New Metadata JDBC DB Connection -------------- +---------------- **To create a new metadata JDBC DB connection:** 1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_1.png - + :: + 2. Select **Create connection**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_2.png - + :: + 3. In the **Name** field, type a name. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_3.png + :: -The name cannot contain spaces. + Note that the name cannot contain spaces. -4. In the **Purpose** field, type a purpose and click **Next**. You cannot go to the next step until you define both a Name and a Purpose. +4. In the **Purpose** field, type a purpose and click **Next**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_4.png + Note that you cannot continue to the next step until you define both a Name and a Purpose. + + :: 5. In the **DB Type** field, select **JDBC**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_5.png + :: 6. In the **JDBC URL** field, type the relevant connection string. - For connection string examples, see `Connection Strings `_. + For connection string examples, see `Connection Strings `_. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_6.png - 7. In the **Drivers** field, click the **Add** button. - The **"newLine** entry is added. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_7.png - -8. One the **"newLine** entry, click the ellipsis. + The **"newLine"** entry is added. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_8.png +8. One the **"newLine'** entry, click the ellipsis. -The **Module** window is displayed. + The **Module** window is displayed. 9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.png + :: 10. Click the ellipsis. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_9.5.png + Your hard drive is displayed. -Your hard drive is displayed. +11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.5.3.jar**)and click **Open**. -11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.4.0.jar**)and click **Open**. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_10.png + :: 12. Click **Detect the module install status**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_11.5.png + :: 13. Click **OK**. -The JDBC that you selected is displayed in the **Driver** field. - -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_12.png + The JDBC that you selected is displayed in the **Driver** field. 14. Click **Select class name**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_13.png + :: 15. Click **Test connection**. -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_14.png - -If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: + If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: -.. image:: /_static/images/Third_Party_Connectors/Creating_a_New_Metadata_JDBC_DB_Connection_15.png + After creating a new metadata JDBC DB connection, you can do the following: -After creating a new metadata JDBC DB connection, you can do the following: - - * Use your new metadata connection. - * Drag it to the **job** screen. - * Build Talend components. + * Use your new metadata connection. + + :: + + * Drag it to the **job** screen. + + :: + + * Build Talend components. -For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. - -:ref:`Back to top ` + For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend `_. -.. _supported_sqream_drivers: - Supported SQream Drivers -================ - +---------------- The following list shows the supported SQream drivers and versions: * **JDBC** - Version 4.3.3 and higher. -* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. -:ref:`Back to top ` - - -.. _supported_data_sources: + :: + +* **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database `_. Supported Data Sources -============================ +---------------- Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. * **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. -* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. - -:ref:`Back to top ` - - -.. _supported_tools_os_sys_versions: - -Supported Tool and Operating System Versions -====================== -Talend was tested using the following: - -* Talend version 7.4.1M6 -* Windows 10 -* SQream version 2021.1 -* JDBC version - - - - -:ref:`Back to top ` - + :: -.. _known_issues: +* **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors `_. Known Issues -=========================== -The the list below describes the following known issues as of 6/1/2021: - -* Schemas not displayed for tables with identical names. - -:ref:`Back to top ` - - -.. _related_links: - -Related Links -=============== -The following is a list of links relevant to the Talend connector: +---------------- +As of 6/1/2021 schemas were not displayed for tables with identical names. -* `Talend Home page `_ -* `Talend Community page `_ -* `Talend BugTracker `_ - - -Download Links -================== -The following is a list of download links relevant to the Talend connector: - -* `Talend Open Studio for Big Data `_ -* `Latest version of SQream JDBC `_ - -:ref:`Back to top ` - - - -.. contents:: In this topic: - :local: +If you experience issues using Talend, see the `SQream support portal `_. \ No newline at end of file From da777d3fdaff938683c7ed3b58d34853eda2132c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 11:54:47 +0300 Subject: [PATCH 0132/1892] Updated with Yotam --- connecting_to_sqream/client_platforms/talend.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index 1aefe8917..7f11092fb 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -44,7 +44,7 @@ Creating a New Metadata JDBC DB Connection 6. In the **JDBC URL** field, type the relevant connection string. - For connection string examples, see `Connection Strings `_. + For connection string examples, see `Connection Strings `_. 7. In the **Drivers** field, click the **Add** button. From e61fc4053407a30e2ef361c66e48247bd98ac766 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 11:59:29 +0300 Subject: [PATCH 0133/1892] Added Talend to index --- connecting_to_sqream/client_platforms/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index a5a3f5166..19f929067 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -31,7 +31,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he informatica r php - xxtalend + talend xxdiagnosing_common_connectivity_issues .. image:: /_static/images/connectivity_ecosystem.png From 0f1264ea356b718d39b318fb4a23a303917b41ab Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 12:16:38 +0300 Subject: [PATCH 0134/1892] Alphabetized --- connecting_to_sqream/client_platforms/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 19f929067..a38f1f1f5 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -21,17 +21,17 @@ If you are looking for a tool that is not listed, SQream and our partners can he :caption: In this section: :titlesonly: + informatica + microstrategy + pentaho + php power_bi - tibco_spotfire + r sas_viya sql_workbench tableau - pentaho - microstrategy - informatica - r - php talend + tibco_spotfire xxdiagnosing_common_connectivity_issues .. image:: /_static/images/connectivity_ecosystem.png From 3366ab3ecd7753351d9d754e7db193ad057582aa Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 12:48:57 +0300 Subject: [PATCH 0135/1892] Update tableau.rst --- .../client_platforms/tableau.rst | 310 +++--------------- 1 file changed, 40 insertions(+), 270 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 3c08ebe83..01f90bbb4 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -1,4 +1,4 @@ -.. _connect_to_tableau: +.. _tableau: ************************* Connecting to SQream Using Tableau @@ -8,7 +8,7 @@ Overview ===================== SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. -The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC and ODBC drivers and connect to SQream using the JDBC and ODBC drivers for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. +The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery `_. @@ -16,295 +16,75 @@ The Connecting to SQream Using Tableau page describes the following: .. contents:: :local: + :depth: 1 Installing the JDBC Driver and Tableau Connector Plugin ------------------- This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. -**To connect to SQream using Tableau:** - -#. Install the Tableau Desktop application. - - For more information about installing the Tableau Desktop application, see the `Tableau products page `_ and click **Download Free Trial**. Note that Tableau offers a 14-day trial version. - - :: +You can connect to SQream using Tableau by doing one of the following: -#. Do one of the following: - - * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. -.. note:: For Tableau **2019.4 versions and later**, SQream recommends installing the JDBC driver instead of the previously recommended ODBC driver. - -.. _tableau_windows_installer: - -Installing the JDBC Driver Using the Windows Installer -~~~~~~~~~~~~~~~~~~ -If you are using Windows, after installing the Tableau Desktop application you can install the JDBC driver using the Windows installer. The Windows installer is an installation wizard that guides you through the JDBC driver installation steps. When the driver is installed, you can connect to SQream. - -**To install Tableau using the Windows installer**: - -#. Close Tableau Desktop. - - :: - -#. Download the most current version of the `SQream JDBC driver `_. - - :: - -#. Do the following: - - #. Start the installer. - #. Verify that the **Tableau Desktop connector** item is selected. - #. Follow the installation steps. - - :: - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream `. - -.. _tableau_jdbc_installer: + :: -Installing the JDBC Driver Manually + * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. + +Installing the JDBC Driver ~~~~~~~~~~~~~ If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. -**To install the JDBC driver manually:** +**To install the JDBC driver:** 1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page`. :: -#. Install the JDBC driver by unzipping the JDBC driver into a Tableau driver directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: +2. Based on your operating system, your Tableau driver directory is located in one of the following places: - * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - -.. note:: If the driver includes only a single .jar file, copy it to *C:\\Program Files\\Tableau/Drivers*. If the driver includes multiple files, create a subfolder *A* in *C:\\Program Files\\Tableau/Drivers* and copy all files to folder *A*. - -Note the following when installing the JDBC driver: - -* You must have read permissions on the .jar file. -* Tableau requires a JDBC 4.0 or later driver. -* Tableau requires a Type 4 JDBC driver. -* The latest 64-bit version of Java 8 is installed. - -3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. - - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - - * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* - * **Tableau Desktop on Mac:** *~/My Tableau Repository/Connectors* :: -4. *Optional* - If you are using the Tableau Server, do the following: - - 1. Create a directory for Tableau connectors and give it a descriptive name, such as *C:\\tableau_connectors*. - - This directory needs to exist on all Tableau servers. - - :: - - 2. Copy the SQreamDB.taco file into the new directory. - - :: - - 3. Set the **native_api.connect_plugins_path** option to ``tsm`` as shown in the following example: - - .. code-block:: console - - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors + * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* - If a configuration error is displayed, add ``--force-keys`` to the end of the command as shown in the following example: - - .. code-block:: console + :: - $ tsm configuration set -k native_api.connect_plugins_path -v C:/tableau_connectors--force-keys - - 4. To apply the pending configuration changes, run the following command: - - .. code-block:: console - - $ tsm pending-changes apply - - .. warning:: This restarts the server. - -You can now restart Tableau Desktop or Server to begin using the SQream driver by :ref:`connecting to SQream ` as described in the section below. - -.. _tableau_connect_to_sqream: - - -Installing the ODBC Driver for Tableau Versions 2019.3 and Earlier --------------- - - -This section describes the installation method for Tableau version 2019.3 or earlier and describes the following: - -.. contents:: - :local: - -.. note:: SQream recommends installing the JDBC driver to provide improved connectivity. - -Automatically Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -If you've already installed the SQream ODBC driver and installed Tableau, SQream recommends reinstalling the ODBC driver with the **.TDC Tableau Settings for SQream DB** configuration shown in the image below: - -.. image:: /_static/images/odbc_windows_installer_tableau.png - -SQream recommends this configuration because Tableau creates temporary tables and runs several discovery queries that may impact performance. The ODBC driver installer avoids this by automatically reconfiguring Tableau. - -For more information about reinstalling the ODBC driver installer, see :ref:`Install and Configure ODBC on Windows `. - -If you want to manually reconfigure the ODBC driver, see :ref:`Manually Reconfiguring the ODBC Driver After Initial Installation ` below. - -.. _manually_reconfigure_odbc_driver: - -Manually Reconfiguring the ODBC Driver After Initial Installation -~~~~~~~~~~~~~~~~~~ -The file **Tableau Datasource Customization (TDC)** file lets you use Tableau make full use of SQream DB's features and capabilities. - -**To manually reconfigure the ODBC driver after initial installation:** - -1. Do one of the following: + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* + + Note the following when installing the JDBC driver: - 1. Download the :download:`odbc-sqream.tdc ` file to your machine and open it in a text editor. + * You must have read permissions on the .jar file. - :: + :: + + * Tableau requires a JDBC 4.0 or later driver. - 2. Copy the text below into a text editor: + :: + + * Tableau requires a Type 4 JDBC driver. - .. literalinclude:: odbc-sqream.tdc - :language: xml - :caption: SQream ODBC TDC File - :emphasize-lines: 2 - -#. Check which version of Tableau you are using. - - :: - -#. In the text of the file shown above, in the highlighted line, replace the version number with the **major** version of Tableau that you are using. - - For example, if you are using Tableau vesion **2019.2.1**, replace it with **2019.2**. - - :: - -#. Do one of the following: - - * If you are using **Tableau Desktop** - save the TDC file to *C:\\Users\\\\Documents\\My Tableau Repository\\Datasources*, where ```` is the Windows username that you have installed Tableau under. - - :: - - * If you are using the **Tableau Server** - save the TDC file to *C:\\ProgramData\\Tableau\\Tableau Server\\data\\tabsvc\\vizqlserver\\Datasources*. - -Configuring the ODBC Connection -~~~~~~~~~~~~ -The ODBC connection uses a DSN when connecting to ODBC data sources, and each DSN represents one SQream database. - -**To configure the ODBC connection:** - -1. Create an ODBC DSN. - - :: - -#. Open the Windows menu by pressing the Windows button (:kbd:`⊞ Win`) or clicking the **Windows** menu button. - - :: - -#. Type **ODBC** and select **ODBC Data Sources (64-bit)**. + :: + + * The latest 64-bit version of Java 8 is installed. - During installation, the installer created a sample user DSN named **SQreamDB**. - - :: +3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. -#. *Optional* - Do one or both of the following: + Based on the installation method that you used, your Tableau driver directory is located in one of the following places: - * Modify the DSN name. + * **Tableau Desktop on Windows:** *C:\\Users\\\\My Tableau Repository\\Connectors* :: - - * Create a new DSN name by clicking **Add** and selecting **SQream ODBC Driver**. - -.. image:: /_static/images/odbc_windows_dsns.png - -5. Click **Finish**. + * **Tableau Desktop on MacOS:** *~/My Tableau Repository/Connectors* - :: +You can now restart Tableau Desktop or Server to begin using the SQream driver by connecting to SQream as described in the section below. -6. Enter your connection parameters. - - The following table describes the connection parameters: - - .. list-table:: - :widths: 15 38 38 - :header-rows: 1 - - * - Item - - Description - - Example - * - Data Source Name - - The Data Source Name. SQream recommends using a descriptive and easily recognizable name for referencing your DSN. Once set, the Data Source Name cannot be changed. - - - * - Description - - The description of your DSN. This field is optional. - - - * - User - - The username of a role to use for establishing the connection. - - ``rhendricks`` - * - Password - - The password of the selected role. - - ``Tr0ub4dor`` - * - Database - - The database name to connect to. For example, ``master`` - - ``master`` - * - Service - - The :ref:`service queue` to use. - - For example, ``etl``. For the default service ``sqream``, leave blank. - * - Server - - The hostname of the SQream worker. - - ``127.0.0.1`` or ``sqream.mynetwork.co`` - * - Port - - The TCP port of the SQream worker. - - ``5000`` or ``3108`` - * - User Server Picker - - Uses the load balancer when establishing a connection. Use only if exists, and check port. - - - * - SSL - - Uses SSL when establishing a connection. - - - * - Logging Options - - Lets you modify your logging options when tracking the ODBC connection for connection issues. - - - -.. tip:: Test the connection by clicking **Test** before saving your DSN. - -7. Save the DSN by clicking **OK.** - -Connecting Tableau to SQream -~~~~~~~~~~~~ -**To connect Tableau to SQream:** - -1. Start Tableau Desktop. - - :: - -#. In the **Connect** menu, in the **To a server** sub-menu, click **More Servers** and select **Other Databases (ODBC)**. - - The **Other Databases (ODBC)** window is displayed. - - :: - -#. In the Other Databases (ODBC) window, select the DSN that you created in :ref:`Setting Up SQream Tables as Data Sources `. - - Tableau may display the **Sqream ODBC Driver Connection Dialog** window and prompt you to provide your username and password. +.. _tableau_windows_installer: -#. Provide your username and password and click **OK**. - -.. _tableau_connect_to_sqream_db: +.. _tableau_jdbc_installer: +.. _tableau_connect_to_sqream: Connecting to SQream --------------------- @@ -362,10 +142,7 @@ After installing the JDBC driver you can connect to SQream. - The connection is established and the data source page is displayed. - -.. tip:: - Tableau automatically assigns your connection a default name based on the DSN and table. SQream recommends giving the connection a more descriptive name. - + .. _set_up_sqream_tables_as_data_sources: Setting Up SQream Tables as Data Sources @@ -388,9 +165,6 @@ After connecting to SQream you must set up the SQream tables as data sources. #. Open a new sheet to analyze data. -.. tip:: - For more information about configuring data sources, joining, filtering, see Tableau's `Set Up Data Sources `_ tutorials. - Tableau Best Practices and Troubleshooting --------------- This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: @@ -398,16 +172,6 @@ This section describes the following best practices and troubleshooting procedur .. contents:: :local: -Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ -When using Tableau, SQream recommends using only data that you need, as described below: - -* Insert only the data sources you need into Tableau, excluding tables that don't require analysis. - - :: - -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyze and increases query performance. - Using Tableau's Table Query Syntax ~~~~~~~~~~~~~~~~~~~ Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. @@ -437,7 +201,13 @@ If Tableau cannot locate the SQream JDBC driver, do the following: 1. Verify that the JDBC driver is located in the correct directory: * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* + + :: + * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* + + :: + * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* 2. Find the file path for the JDBC driver and add it to the Java classpath: From 4e6bd961b99742efbde41793580af6fa442b1200 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 12:55:04 +0300 Subject: [PATCH 0136/1892] Update tableau.rst --- connecting_to_sqream/client_platforms/tableau.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 01f90bbb4..ad29a7d15 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -6,7 +6,7 @@ Connecting to SQream Using Tableau Overview ===================== -SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. +SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. From a58d0028e203acd4eea8ad0f1517a236ed28e8bd Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 13:02:27 +0300 Subject: [PATCH 0137/1892] Update tableau.rst --- connecting_to_sqream/client_platforms/tableau.rst | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index ad29a7d15..1d2ca17b6 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -24,14 +24,12 @@ This section describes how to install the JDBC driver using the fully-integrated You can connect to SQream using Tableau by doing one of the following: - * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver Manually `. + * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver `. - :: - - * **For Windows** - See :ref:`Installing Tableau Using the Windows Installer `. +.. _tableau_jdbc_installer: Installing the JDBC Driver -~~~~~~~~~~~~~ +------------------- If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. **To install the JDBC driver:** @@ -80,12 +78,6 @@ If you are using MacOS, Linux, or the Tableau server, after installing the Table You can now restart Tableau Desktop or Server to begin using the SQream driver by connecting to SQream as described in the section below. -.. _tableau_windows_installer: - -.. _tableau_jdbc_installer: - -.. _tableau_connect_to_sqream: - Connecting to SQream --------------------- After installing the JDBC driver you can connect to SQream. From bfefafacce2957e7c8924f2ae5a84ba93626b722 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 13:31:53 +0300 Subject: [PATCH 0138/1892] Reinstated missing files --- .../installing_and_launching_sqream.rst | 3 +- installation_guides/installing_monit.rst | 315 ++++++++++++++++++ .../installing_sqream_with_binary.rst | 277 +++++++++++++++ 3 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 installation_guides/installing_monit.rst create mode 100644 installation_guides/installing_sqream_with_binary.rst diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 6ff465758..6a41ba52b 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -13,4 +13,5 @@ The **Installing and Launching SQream** page includes the following installation installing_sqream_with_binary running_sqream_in_a_docker_container installing_sqream_with_kubernetes - installing_monit \ No newline at end of file + installing_monit + launching_sqream_with_monit \ No newline at end of file diff --git a/installation_guides/installing_monit.rst b/installation_guides/installing_monit.rst new file mode 100644 index 000000000..ab49164f6 --- /dev/null +++ b/installation_guides/installing_monit.rst @@ -0,0 +1,315 @@ +.. _installing_monit: + +********************************************* +Installing Monit +********************************************* + +Getting Started +============================== + +Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations `. + +The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. + +.. _back_to_top: + +Overview +============================== + + +Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. + +SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. + +The **Installing Monit** procedures describes how to install, configure, and start Monit. + +You can install Monit in one of the following ways: + +* :ref:`Installing Monit on CentOS ` +* :ref:`Installing Monit on CentOS offline ` +* :ref:`Installing Monit on Ubuntu ` +* :ref:`Installing Monit on Ubuntu offline ` + + + + + + + +.. _installing-monit-on-centos: + +Installing Monit on CentOS: +------------------------------------ + + + +**To install Monit on CentOS:** + +1. Install Monit as a superuser on CentOS: + + .. code-block:: console + + $ sudo yum install monit + + +.. _installing-monit-on-centos-offline: + + + +Installing Monit on CentOS Offline: +------------------------------------ + + +Installing Monit on CentOS offline can be done in either of the following ways: + +* :ref:`Building Monit from Source Code ` +* :ref:`Building Monit from Pre-Built Binaries ` + + + + +.. _building_monit_from_source_code: + +Building Monit from Source Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + + +**To build Monit from source code:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Configure the files in the package: + + .. code-block:: console + + $ ./configure (use ./configure --help to view available options) + +4. Build and install the package: + + .. code-block:: console + + $ make && make install + +The following are the default storage directories: + +* The Monit package: **/usr/local/bin/** +* The **monit.1 man-file**: **/usr/local/man/man1/** + +5. **Optional** - To change the above default location(s), use the **--prefix** option to ./configure. + +.. + _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** + +6. **Optional** - Create an RPM package for CentOS directly from the source code: + + .. code-block:: console + + $ rpmbuild -tb monit-x.y.z.tar.gz + +.. + _**Comment - Is this an optional or mandatory step?** + + + + +.. _building_monit_from_pre_built_binaries: + +Building Monit from Pre-Built Binaries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +**To build Monit from pre-built binaries:** + +1. Copy the Monit package for the current version: + + .. code-block:: console + + $ tar zxvf monit-x.y.z-linux-x64.tar.gz + + The value ``x.y.z`` denotes the version numbers. + +2. Navigate to the directory where you want to store the package: + + .. code-block:: console$ cd monit-x.y.z + +3. Copy the **bin/monit** and **/usr/local/bin/** directories: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** and **/etc/** directories: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +.. + _**Comment - please review this procedure.** + +For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries`. + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu: + + + +Installing Monit on Ubuntu: +------------------------------------ + + +**To install Monit on Ubuntu:** + +1. Install Monit as a superuser on Ubuntu: + + .. code-block:: console + + $ sudo apt-get install monit + +:ref:`Back to top ` + + + +.. _installing-monit-on-ubuntu-offline: + + +Installing Monit on Ubuntu Offline: +------------------------------------- + + +You can install Monit on Ubuntu when you do not have an internet connection. + +**To install Monit on Ubuntu offline:** + +1. Compress the required file: + + .. code-block:: console + + $ tar zxvf monit--linux-x64.tar.gz + + **NOTICE:** ** denotes the version number. + +2. Navigate to the directory where you want to save the file: + + .. code-block:: console + + $ cd monit-x.y.z + +3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: + + .. code-block:: console + + $ cp bin/monit /usr/local/bin/ + +4. Copy the **conf/monitrc** directory into the **/etc/** directory: + + .. code-block:: console + + $ cp conf/monitrc /etc/ + +:ref:`Back to top ` + + +Configuring Monit +==================================== + +When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. + +The following is an example of a service block: + + .. code-block:: console + + $ #SQREAM1-START + $ check process sqream1 with pidfile /var/run/sqream1.pid + $ start program = "/usr/bin/systemctl start sqream1" + $ stop program = "/usr/bin/systemctl stop sqream1" + $ #SQREAM1-END + +For example, if you have 16 services, you can configure this block by copying the entire block 15 times and modifying all service names as required, as shown below: + + .. code-block:: console + + $ #SQREAM2-START + $ check process sqream2 with pidfile /var/run/sqream2.pid + $ start program = "/usr/bin/systemctl start sqream2" + $ stop program = "/usr/bin/systemctl stop sqream2" + $ #SQREAM2-END + +For servers that don't run the **metadataserver** and **serverpicker** commands, you can use the block example above, but comment out the related commands, as shown below: + + .. code-block:: console + + $ #METADATASERVER-START + $ #check process metadataserver with pidfile /var/run/metadataserver.pid + $ #start program = "/usr/bin/systemctl start metadataserver" + $ #stop program = "/usr/bin/systemctl stop metadataserver" + $ #METADATASERVER-END + +**To configure Monit:** + +1. Copy the required block for each required service. +2. Modify all service names in the block. +3. Copy the configured **monitrc** file to the **/etc/monit.d/** directory: + + .. code-block:: console + + $ cp monitrc /etc/monit.d/ + +4. Set file permissions to **600** (full read and write access): + + .. code-block:: console + + $ sudo chmod 600 /etc/monit.d/monitrc + +5. Reload the system to activate the current configurations: + + .. code-block:: console + + $ sudo systemctl daemon-reload + +6. **Optional** - Navigate to the **/etc/sqream** directory and create a symbolic link to the **monitrc** file: + + .. code-block:: console + + $ cd /etc/sqream + $ sudo ln -s /etc/monit.d/monitrc monitrc + +Starting Monit +==================================== + +After configuring Monit, you can start it. + +**To start Monit:** + +1. Start Monit as a super user: + + .. code-block:: console + + $ sudo systemctl start monit + +2. View Monit's service status: + + .. code-block:: console + + $ sudo systemctl status monit + +3. If Monit is functioning correctly, enable the Monit service to start on boot: + + .. code-block:: console + + $ sudo systemctl enable monit diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst new file mode 100644 index 000000000..7a3c7fff8 --- /dev/null +++ b/installation_guides/installing_sqream_with_binary.rst @@ -0,0 +1,277 @@ +.. _installing_sqream_with_binary: + +********************************************* +Installing SQream Using Binary Packages +********************************************* +This procedure describes how to install SQream using Binary packages and must be done on all servers. + +**To install SQream using Binary packages:** + +1. Copy the SQream package to the **/home/sqream** directory for the current version: + + .. code-block:: console + + $ tar -xf sqream-db-v<2020.2>.tar.gz + +2. Append the version number to the name of the SQream folder. The version number in the following example is **v2020.2**: + + .. code-block:: console + + $ mv sqream sqream-db-v<2020.2> + +3. Move the new version of the SQream folder to the **/usr/local/** directory: + + .. code-block:: console + + $ sudo mv sqream-db-v<2020.2> /usr/local/ + +4. Change the ownership of the folder to **sqream folder**: + + .. code-block:: console + + $ sudo chown -R sqream:sqream /usr/local/sqream-db-v<2020.2> + +5. Navigate to the **/usr/local/** directory and create a symbolic link to SQream: + + .. code-block:: console + + $ cd /usr/local + $ sudo ln -s sqream-db-v<2020.2> sqream + +6. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ ls -l + +7. Verify that the symbolic link that you created points to the folder that you created: + + .. code-block:: console + + $ sqream -> sqream-db-v<2020.2> + +8. Create the SQream configuration file destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /etc/sqream + $ sudo chown -R sqream:sqream /etc/sqream + +9. Create the SQream service log destination folders and set their ownership to **sqream**: + + .. code-block:: console + + $ sudo mkdir /var/log/sqream + $ sudo chown -R sqream:sqream /var/log/sqream + +10. Navigate to the **/usr/local/** directory and copy the SQream configuration files from them: + + .. code-block:: console + + $ cd /usr/local/sqream/etc/ + $ cp * /etc/sqream + +The configuration files are **service configuration files**, and the JSON files are **SQream configuration files**, for a total of four files. The number of SQream configuration files and JSON files must be identical. + +.. note:: Verify that the JSON files have been configured correctly and that all required flags have been set to the correct values. + +In each JSON file, the following parameters **must be updated**: + +* instanceId +* machineIP +* metadataServerIp +* spoolMemoryGB +* limitQueryMemoryGB +* gpu +* port +* ssl_port + +Note the following: + +* The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. +* The value of the **machineIP** parameter must point to the IP of your local machine. + +It would be same on server running metadataserver and different on other server nodes. + +11. **Optional** - To run additional SQream services, copy the required configuration files and create additional JSON files: + + .. code-block:: console + + $ cp sqream2_config.json sqream3_config.json + $ vim sqream3_config.json + +.. note:: A unique **instanceID** must be used in each JSON file. IN the example above, the instanceID **sqream_2** is changed to **sqream_3**. + +12. **Optional** - If you created additional services in **Step 11**, verify that you have also created their additional configuration files: + + .. code-block:: console + + $ cp sqream2-service.conf sqream3-service.conf + $ vim sqream3-service.conf + +13. For each SQream service configuration file, do the following: + + 1. Change the **SERVICE_NAME=sqream2** value to **SERVICE_NAME=sqream3**. + + 2. Change **LOGFILE=/var/log/sqream/sqream2.log** to **LOGFILE=/var/log/sqream/sqream3.log**. + +.. note:: If you are running SQream on more than one server, you must configure the ``serverpicker`` and ``metadatserver`` services to start on only one of the servers. If **metadataserver** is running on the first server, the ``metadataServerIP`` value in the second server's /etc/sqream/sqream1_config.json file must point to the IP of the server on which the ``metadataserver`` service is running. + +14. Set up **servicepicker**: + + 1. Do the following: + + .. code-block:: console + + $ vim /etc/sqream/server_picker.conf + + 2. Change the IP **127.0.0.1** to the IP of the server that the **metadataserver** service is running on. + + 3. Change the **CLUSTER** to the value of the cluster path. + +15. Set up your service files: + + .. code-block:: console + + $ cd /usr/local/sqream/service/ + $ cp sqream2.service sqream3.service + $ vim sqream3.service + +16. Increment each **EnvironmentFile=/etc/sqream/sqream2-service.conf** configuration file for each SQream service file, as shown below: + + .. code-block:: console + + $ EnvironmentFile=/etc/sqream/sqream<3>-service.conf + +17. Copy and register your service files into systemd: + + .. code-block:: console + + $ sudo cp metadataserver.service /usr/lib/systemd/system/ + $ sudo cp serverpicker.service /usr/lib/systemd/system/ + $ sudo cp sqream*.service /usr/lib/systemd/system/ + +18. Verify that your service files have been copied into systemd: + + .. code-block:: console + + $ ls -l /usr/lib/systemd/system/sqream* + $ ls -l /usr/lib/systemd/system/metadataserver.service + $ ls -l /usr/lib/systemd/system/serverpicker.service + $ sudo systemctl daemon-reload + +19. Copy the license into the **/etc/license** directory: + + .. code-block:: console + + $ cp license.enc /etc/sqream/ + + +If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream `. + + + + + + +Upgrading SQream Version +------------------------- +Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. + +**To upgrade your version of SQream:** + +1. Stop all actively running SQream services. + +.. note:: All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. + +For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit `. + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + + .. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + +3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: + + .. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + + .. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + + .. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQream link points to the real folder: + + .. code-block:: console + + $ ls -l + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream -> sqream-db-v2021.1 + +7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + $ ./upgrade_storage + + The following is an example of the correct output: + + .. code-block:: console + + get_leveldb_version path{} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + + .. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + The following is an example of the correct output: + + .. code-block:: console + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the `upgrade_storage `_ command line program. + +For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server `_. \ No newline at end of file From 3c89d556f405dc12e25a1d9d6ab3eaa04da749ac Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Thu, 21 Jul 2022 13:52:14 +0300 Subject: [PATCH 0139/1892] Added Upgrade Storage link --- releases/2022.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 8d881c92c..f02676c34 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -138,11 +138,11 @@ Upgrading to v2022.1 $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. .. toctree:: :maxdepth: 2 :glob: :hidden: - 2022.1 \ No newline at end of file + 2022.1 From bce4e2dc23534b6dddb56308896231c449067c0c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 21 Jul 2022 14:14:04 +0300 Subject: [PATCH 0140/1892] Added SAP BO --- .../client_platforms/index.rst | 1 + .../client_platforms/sap_businessobjects.rst | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/sap_businessobjects.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index a38f1f1f5..be5f4af16 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -27,6 +27,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he php power_bi r + sap_businessobjects sas_viya sql_workbench tableau diff --git a/connecting_to_sqream/client_platforms/sap_businessobjects.rst b/connecting_to_sqream/client_platforms/sap_businessobjects.rst new file mode 100644 index 000000000..4c740b034 --- /dev/null +++ b/connecting_to_sqream/client_platforms/sap_businessobjects.rst @@ -0,0 +1,60 @@ +.. _sap_businessobjects: + +************************* +Connecting to SQream Using SAP BusinessObjects +************************* +The **Connecting to SQream Using SAP BusinessObjects** guide includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Overview +========== +The **Connecting to SQream Using SAP BusinessObjects** guide describes the best practices for configuring a connection between SQream and the SAP BusinessObjects BI platform. SAP BO's multi-tier architecture includes both client and server components, and this guide describes integrating SQream with SAP BO's object client tools using a generic JDBC connector. The instructions in this guide are relevant to both the **Universe Design Tool (UDT)** and the **Information Design Tool (IDT)**. This document only covers how to establish a connection using the generic out-of-the-box JDBC connectors, and does not cover related business object products, such as the **Business Objects Data Integrator**. + +The **Define a new connection** window below shows the generic JDBC driver, which you can use to establish a new connection to a database. + +.. image:: /_static/images/SAP_BO_2.png + +SAP BO also lets you customize the interface to include a SQream data source. + +Establising a New Connection Using a Generic JDCB Connector +========== +This section shows an example of using a generic JDBC connector to establish a new connection. + +**To establish a new connection using a generic JDBC connector:** + +1. In the fields, provide a user name, password, database URL, and JDBC class. + + The following is the correct format for the database URL: + + .. code-block:: console + +
jdbc:Sqream://:3108/
+	  
+   SQream recommends quickly testing your connection to SQream by selecting the Generic JDBC data source in the **Define a new connection** window. When you connect using a generic JDBC data source you do not need to modify your configuration files, but are limited to the out-of-the-box settings defined in the default **jdbc.prm** file.
+   
+   .. note:: Modifying the jdbc.prm file for the generic driver impacts all other databases using the same driver.
+
+For more information, see `Connection String Examples `_.
+
+2. (Optonal)If you are using the generic JDBC driver specific to SQream, modify the jdbc.sbo file to include the SQream JDBC driver location by adding the following lines under the Database section of the file:
+
+   .. code-block:: console
+
+      Database Active="Yes" Name="SQream JDBC data source">
+      
+      
+      C:\Program Files\SQream Technologies\JDBC Driver\2021.2.0-4.5.3\sqream-jdbc-4.5.3.jar
+      
+      
+      
+      com.sqream.jdbc.SQDriver
+
+      
+      
+
+3. Restart the BusinessObjects server.
+
+   When the connection is established, **SQream** is listed as a driver selection.
\ No newline at end of file

From 980753a69c3792e854316368614f1dfe370de159 Mon Sep 17 00:00:00 2001
From: Yaniv Gerowitz 
Date: Thu, 21 Jul 2022 14:16:55 +0300
Subject: [PATCH 0141/1892] Added images

---
 _static/images/SAP_BO.png   | Bin 0 -> 112881 bytes
 _static/images/SAP_BO_2.png | Bin 0 -> 25160 bytes
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 _static/images/SAP_BO.png
 create mode 100644 _static/images/SAP_BO_2.png

diff --git a/_static/images/SAP_BO.png b/_static/images/SAP_BO.png
new file mode 100644
index 0000000000000000000000000000000000000000..413ce7d0e4731668b9320ab6a6139177329c1af6
GIT binary patch
literal 112881
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

pLD2D_$vWC+{e~$c+6bxRmwn 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 Z{{yVFQ$#+Xs)hgn002ovPDHLkV1g9&3}^rV literal 0 HcmV?d00001 diff --git a/_static/images/SAP_BO_2.png b/_static/images/SAP_BO_2.png new file mode 100644 index 0000000000000000000000000000000000000000..91bc53d1a98462d50718f5cada0b2149d55b04bb GIT binary patch literal 25160 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 }(bbAR8C%mz z`bhSO)ialLz;}uvYsz7?-Y%Ry$}Z&tH!bIgqg*DAW|W?L!9#QYJgw#|+~0LfXj~yA z6BPR_E&#>GSyM+w@h;c&4!VrH<8YH1Lr zd-(uULsnH}I#R1^Of-Uo2@G)qVST0U6vHzJ%mb>D5AO0>r&9M!!v8 z5a(njyIWBeRa>1^zs24Ow@62LwhePD(_ak|3P-$sR`{0_EdMu7FrrhB5PWfF1Ukn0 zz}gCQYPaBCdLjg0wE2DBLK{fy{5?P_ydx56uxY12Tx9WLTz#%MzI4WW?p1YI>lkic zH7+mT$9J&V)`Z6UE$QnEt_zHuve;BgWELszQ+-E&S#sL3?Sp1X?{hxUtxTD##|&16 z8Ifz8XofuO-Bo>c{z?MhR;MuLjdHVn{3MqJ;;XFU?{8tF^+Qjfr4jGObQiZpokfe^ zWMM$F^dWEgzgH}GwI5H+am$3+o1ZVm00~vo%PF$&LZp9jEgYfZsE0VY^ z9ZhKlb~|54Xw1wmAY#lv0GxbhuRbhO7V+fPNIxEF0#S(qF=ArQOg=xaSdvz_ar%c$ zf)%YEs*Di6<5z_%Wn)%4Td-B7SA+E4j;`X?D$JFfl^&&YlPd(7I!VB^S1Rw792pv@|7ZM_)G?n$^C+&JM$ z;6t{TKtaO#la@h0cB_vB2*A7exI$Sl@YATEq$CdRv18g@i!V%jtSUEJjhQ zh)PX342UA!pO1Mx$NH10L!dnvWc;?CS263m8lz3^!*?DRbQ!i@*0MzAmiU!_QW81b zf8rC_{};D%zY?5zkQOD>lkJ?qv`k`luQzjf*f1M$XdrNvTKaO|T7f_UOqZSgdi&+4 zn~mTu`l9r4-B3y@8FqxjQXln)MLM_rCL6Dt=KVe^vPk6^OD@mv?)EH!pWb%SC}R-q zz{w&{Y$QtJyZT`Yz8m~g46h^qQpIe0Sx(uj!k~Hk(PQ8DrE@H?z={RYN6-Yb;_8Y8 z&n2{XLA(o(k60M&k9hqt=Y?|fn$rqfoFA|!*V?P1wPjGVyOMN#S4%P^Hd+3i7T?qH zSm#R>2V$wPE*B}S1f#r>Qy&lc0&%L*0j!zf!EBM(0ad(RL*y4uaeaA>*JVtM$!>nz zltPKgMXUs?Sr5Hh#l65a8XE}%;*>vu|Esq1jB2Xe)-X*1f|LLP3K2sMAkv#bDIrut z?}9W@KoAh52?EkfBoLa?l!RUl(v=p9NN)myQlv$bB!JvOlu1t9VXk`A+t#Z zBw;^TJiRDUbwA;|MUJW>n`ghh(GMW&L(Al6nhdF2DR~lvkQ8sM9jEVRX>H73s3tzJ!O)L+BMEp zD2Bh9Ir4ZucPujE6A|OBesW!v=OX`=2+;z?@NoB(5?rG&A-8APIa|AFPbki_hg8n$Q}blg^Jrc^5m^ExzNMUL9Vq3V6n8`KQmHL^oYqbEIc-#MKdaV;5S^9S&Re!*7YHZh)=f1qpOJN8*)X^* zH^mzeDR*Atcd_y?w9Y9|lz{5vec!XT?+$s=>S~}9_&pZt%$(v?r7P}4n=24|P_4FG z>cUdeCCX5H;iJ=f`2ro%6KO(uO(p=&8rtiuI`yNIrm=s;u(7txmhihToGm8*M|p_i z08~f_(e-*Pzg6a}!VObvZ)OJq}zq+6Cy>gC}+n z-j)Wau14P-lk%}-1#3)=KPjQpjgFy-nz%}9^vHsdNcK@jRdPiCFjI{z>P2l||8iDo zWmL=Q8gS|nXw>s;M!nPG3(s=b>X)Uo3+0#4UA>0nP4?=m_`zM=gs>+n)Zb_nl1E{T zxnuQLZs&BI@Qmq}S#*W>)RIMt#q-`<`{^V7@))r@ep_GfXwYZ8(^uN(*hbG#Ti-56 z&b;oUTZJ+?QCrbg<0z7zsyiu3ZhV0Io;_>K(rInQ^&|sNF??-p{iA-_OO%^z#W)9B zZY<(MTfHzl;pWf%RjzyK=EqOuWegk}#Byv6P`vDN(qon%t`=D!K9+26{w{nv_1r$6 z8v8rToq=mjE^l{6jebFBz6}5R%Ee1T1kDr^yElEiy`O*Ammo5)}S2c7U zq|bAbzijg=$R#hUxHbrg-JMu*ZW+1)?7}EHv2I5zSD*6hvIZN{+anWN{sj;1i|KF@ zk5Wj`^iiC0*p}W6x^_w0E1LY_r-`X?kG-1vy4Qy7uakM?qfxPWbdqm71vx~dOUsnpB;*} z{@$U8?%Bzl#`IUsZ3z3_@`EvU_0uU?o~1{UM8dP*wc^+7^eh>B#qJUxWfWFu8Ptx; z=ZCN7Qgg6UNPv=#;b+3ldltEKW;dR;H9qaLTv(UCKeI0w+=+lH=~OX5oyx+f#2bTk=;HyBz}k@sg_sbmAf5u&BGa+;V?V?HRocFSGk1}m)d)iJ{lerA zViqFyxs5yE4+zT@B|mS}E@WbMLjdx;q!qd?xQ*5UqGG zoO^@9CaJ(LKi1?q{nGVy9Fz_tW0}^ggxmmI>(_p=9^8CAI*aw10gvmCTTIw))GBIL zUk}{USIA;}%209+>Rg&FSJjZEG46Fx#i4*#f3?)t7Kcb;(y3P+088W`EQ=}WkYfu6 zH40JY>4$cHnWvQ2=H|eV7B2}@DhmclzQK%Xy1QANAWT$zMJ!Z%ffAN+XNej|ogUr{;Aryc8u~O_w@a?#FBK2&8y5v?H*pjgGmyiQEeJg7;cVEC@T5)iJPX zu(c_|>ga72HU~Km=k9!lXEil3P0s<1z?5A?$YkO=dHv3bfjQ>=UEak+t+Kg-@1!-J zygukh!_0l**c(JrcBxq%11ty`dN2Ui6*=Pp?5;Cpq99Iue33Eh6=k7nwoKso*Wwm} z_U`CM=3v2u`-&J@Yp}056rx)|)&yY~y=zU;l4%&Ar01rvt^c|~LOStp6Tg2jfSJkIgZ61tF&kgv5R% zI#zI8f<_0}p-{m*U2n%WiV5md*ML;9>)KO5zcTW}Q)zUS%w`Y?{#nqQ9mVh{{Nd;1 z&~yigRTRC6>X9*1ZfuNhV=w`J4-R>W>#AqX7Ce=C^}BZiC%RgZ*>+loE8dgcJJ9?z zDvGU+CB}hG;&P~*j-zDr!{uK8(*(DW8C!xX=BvEGYRszbios98mxK>}5~Bx?Kfhzq(uy%S=@M1>(w#L9u|k~9y5!+;6*1^FM_;@?X&oZ+v~?d>?^5q;QE zuu}GG@|v<4!7`8&yX+2#a?fY%YY&(+%<(o#`#Zc>`ZEubB;nB+lc)~R>Lnbqjgg0doh z{3R`%WVDv|60T-IP4_YB)4j#hndFjvFGepsM4De3a3Y*;SgUfsv)3Y`#3^C%!;->0 zp{S$1!elJ}XZe&xs=;(4mLS{LY54A|LFxsmW-fMrSq`tpHy*P?2H=@XFm9qI*dAuK zg)x;PyKiAB_QJgKhpPBxApr~x%QgBZgxuRo@EdKE=3F3x3p z2-+YDk!9@I4MqwHSVWfU_^(fqosF`CE?NLX!Lgkw1v{=QIqU6EdL1N{xD@m9r6DiO zHi8wdm$p;dN2aFRta)Bc_oe2h9c`%z`tG54`I}H`i6n%rNjc(rLT&aLFGEL zN?XF^+y*LKscSO#x7cRf2euinh8SmRdWsQ;mQ~x@OFq9~A(9KCH27CS&4x0fPsfTG zBzj#vbZ>2|HWwnkb_jBpG|=ZNQoFrD_7VRd!tp(~*`;7X?P|C0v9wiK*S*imD{rG$RMOlddCO2#90&9uhv`!@kkqgdyHlG8`}FsV zhh+i}kK=FUN$9Iz(mJD<5Z+&hc~4+}ay4MNUga<=2v2dd!XEh3Snpv&Y^i! z2|ZinyEte#HMlPz|CmD`NP7c9CJ*UoWl!vD@n<0nufP56EQT7#;1vwh%YRQ)eNi^t zR1cw+s6^=ZWCbg=+XkyN)YQ+Kv0=^*k2j-Zj|Sf#7?(bDhFu5Ak)I=y{i~5(Gz%En zJ)jvoewVT5!=j!4h?c zV>a0yGQz9c^G|LTtf2eSRp=#$fHax@+GIL(nB`HpQi=Wjb_1?W*LeHew!8g8ky@#t zkcv+tRQBHI*92ws8xG=WFy8*=m1|4OC|chlTZ<_nG0I-ec;;x8z3z*>sJAOB^s?2$ zW~*ooieEnM;3-~uz zTZz%2!?&j#qBu`#iIs4J9#?MJkqSK5Yturyfnu!D@(%XtBM+P&aR@{4#>TUgY13Ub z$}8}}-OO@XIz^GQ5Z}tiXwLQ!2V<^K-eiycG>tCVUp&;=`sF<;Y)3+GbNcNbQz~4K z$7vIC6w_%-9Z>#%c^AH~;*GTk(PkpFp$=4sU$3n2&6rF)gB$T#L%8qmReeE(gHRXs zqISEiiPom`IV^4zGSTGxfWz$+XQV0Pf;u|7Udw=l#}zt12dA5!v5o$BgRkwHcW-cw z;`l}t^{El`Ir(AAYe3iVhMF(4uSLuw)Mwg$9%^i&HmRk8<@s0Z?%!3orCoo7t`Eqw zY_96tIueRQ%gxXRVIwp_0Yco5EiO;DgR%q67%rW8-vu?)@Sv8+{bS*+_H@DQ3ZpZN8g-HFRvd2&{8IMBMuKMF&C%ZaNNVm)g?ev5lQ9`3xvN5e=Yd z){}`ZcQZURQO6}!`;_F_U!C7qViUQkt%uy>QGU!}+a|Oqo@tq;(Btr=deo0V(>Z|= zgO}K&w#j5`Hf_gxcv75b5s;qc_90%doB6Wee#DS-=|I(cE^9YGKmI*OBC@^0$h*s_ zmxr1&amkT34ErI^QL~0u2k3*y)q2Yf8~iYvD>Agd7+$<=m(K%0T0iRo`c4$$XM7@*Jg|D?~EJU+G${SsX!Itl^S zDdvCoUJ&8DK~OZBbt@uHN}!=G0L0z1F`45TFd@29YVJ4Px(Rinr$ifgQlWL*#%@Bm zKO8>h@FV#NQC`9==|#`pNd*6czgAm&qS0tWv9?veU#<+t$OEPa&;eGhG!4*sYga|) zxlp6-5fw0e6T0~l{5$gwOQ8zA5a8y7=y9MW?8SrI-s&g68@SitBR+3|=wnQ2sh*^s zk=&F%X~fKNX#e=$xo%T(Z3f~hD!x$|%B!?xl$tNdn~$EQw^s)2uoJ@!;K2JcVTRy$ zC!QI`vkpH!>b}NwqS|hGQ5XpOuq2%JB*p2ROZ6gC=VIytNCm)d;EXE3Qf4bMP-*w{ z`IdBipQO)WEMGYwT=!MIaO2`|?60lI3flYaq`@?B@yi|iI+_+9>hsrN2fUSr<)HM0 z=0scGBKveb5P^1O(6zakNka^Cx|BJj9lKXa8c^R)s1UeVLOqz`f$`_0DL5eBbl&wD zssH1A(e3A2VLD?_5K4W72SUzC4EaBUY3y=&)gpC?DRt3FSMcgtG$eY3ZjHYJB@yt% z=jwx;yn!=}6@0H5#~yPmIZarEPvQj{9HbnWC{fb*8ziyjlf-HVh;`b76%^Vf^nhCS zYrK8BBj?KY@oQBcWNlTjAtgR=Aeu=lE$URGd+;XKBkgo5K4D(6C7#HENRVTEVc>21 zz)XPAzU8?|eZ$u}!Z`W2(w-nFCb4VFNLL;a?3*#hvqNOIdvRjh>i6&y_>>+{R|c?>QBqvC&hw{RZVdx5rOl1CJ+8-ly>j7IOoEtMos@^XX1 zIbBk`20%T4ceLH=ypX{|qc<$LD1Sf&nIW9 zg-@R8TThI4h*X!93R5=Dq{s6(hEfod=+#1?JGn{qpPM9mWd_c-s2k&^Sx6PJp^l~5 zq9>qJV0?w%O2oRd%)KSG6A=Q+hUM481u03I%^=gNmu1eT*X~I^b({q>vm5B(QJ7W27gpC1WJCgFYw8~r{97MxkuHqw)IWM`(b15h_h0WF2F zera0$FlihL|NVyZ>f6Y5Xc!MYaF2JrCjJJ@n@zT2euo(OadP#w%3S7Q|3yVi^}8Kg zLa9j^ulaY523Dp5$XK?IdK<6xtL!)vp@C@UZ>yh-!!^pWg1d@o@DM&%)<|V-e!qwY zngfE%;(jd4j)n8imnE4E$ zv=s~nY{-33r`ZTVkM6q4M950Nh^kunt|T1jA4icv!A06)R|bPilC=cNyFTZ zBo{@F^S->%I(5;=11XA+i`GWO{+z`?TUHs+-IB^r3MoPi&C}vX$jhgIe>92GlMJrN zoH-JBIO(PnN&|K$l*SUPGdfC=xyRxSQ<61 zWmQjWGh!BWk?GMVqdfU%bq-{kt%N)L?EcZqTg+4#DnJ&eQ~{3EK1Gsjf3PG_UY1wF z&8eekT$gfFbTK9wPo`J49J>%2ZgOMJLb$&^{Xxa&i&z!AGFu21{lpT@|F9nBw z5$z~$Qy0}>^U7*7kjr&2o?^S(Sy|kXQiY`%RYz#ENwB;$4ej=lvBHgBU_@%^7Aw+* z6|w*ieXAIo$3?^3BHfbrx|-}EGTdN1V@`Cf^z2}3i05h3V!}P8aTrIjlhHEMr~9y| zt@Hv9c8yY}=xVn3s0pSA;2}Pbcb%LGbNt38$e(ZogiKP0?N;~0!Vfe)HC=_tz-y57 zm#6Ko&$F+^uv-hv8!%FcVYL*ZeI5cZ8~M#JqkGJVV-f`?W7u!@@fGh25}n)tkinKN zBttvw4#$5p{Qik$gBZR^CE?PV=nL1}VX{x7unR`?q^F`M0({$)?M0v&`(GFd{^?Op zrrJMP-3}8J(!gRUpqG7v>j6>um`4$cYdMTv+tUb-#99Udz%qafGEorb2#GHrY*+&Q zy}dcg3KTt#kx8I|*L#-qQNekoKkO?_Ym68}TLf%Te!o4uLDBQo)$rhl9ii8lzmlI| zeQKKCxEp@$6o2UT=K!EB^k>;Xcq9&w$;z8!FR!<$$ib(ryPzyZL7Xem6`8bd@Ct<}AqGyk;DLmmTD*1i{FtnI&? zA~Gh!H=#LD>7!oM@P-<*gGEQFzg`m{O$yRQ=__}uoCd7Yd&*4|;*z`J8xD{lN{>fB z-6Kb}kI2Vlr9!VSpBa0d`xBDZB4z#Yvoj6M%xski(ST4luU2<)^27T#cS_)%k~%#~ z73kMz*<$D?C5iyDcX0Ini{0;IuISZ_Gj;A3o|Kh53;kc4ytt438?O2)2zD6uKkK$E zIe+=QGu4)>cso3_>GMQds7|aetzVQFOQI`>N>t zo(+X`KK9xBaz(@~3kXrPO~1Kj4V9-=KY7>Z^?U=9zmJo6oK{D*EHGC}?`N*)Ho)&` zb`d)`6H27o?NHtbtQTv!6u{1Bhc~BJZEwm-7OXSnVd)@d%_4VcUlRkN@yu3< zO>igkaSANjnBAtfI%Nd-UeC2!5w~|I@XJe|&pOx3g2KT9!O5_fFEI(q8EaG+$TB1Mdfp}S3mzmJ%lUOs)2 zmuhlx41?5|gu!I*m~Cpi;3g=afhI1L#y@Avb~j(^>7J&-z4RGB`K1ju>y{ro3ChbG z=PUIp#SbHBo4SV9FJwJHm$tX__8R&?lW|;I4T|5UEWAyBij4!QgKF}8OtuzIw?`_8 zI(a7^?+MV|t3TI-uL7$G{zcp8fX&MR^p*^!C-qM!PPXW~1BEUoGFdquS9G?%SSFSv)d4T8d^Tt z{cl=9wqG0lH%*&?9`@9fXU8;H4pgp2Qn>n6rx Date: Thu, 21 Jul 2022 15:02:28 +0300 Subject: [PATCH 0142/1892] Moved Hardware Guide to Getting Started --- {operational_guides => getting_started}/hardware_guide.rst | 0 getting_started/index.rst | 3 ++- 2 files changed, 2 insertions(+), 1 deletion(-) rename {operational_guides => getting_started}/hardware_guide.rst (100%) diff --git a/operational_guides/hardware_guide.rst b/getting_started/hardware_guide.rst similarity index 100% rename from operational_guides/hardware_guide.rst rename to getting_started/hardware_guide.rst diff --git a/getting_started/index.rst b/getting_started/index.rst index e799d047a..87b98870d 100644 --- a/getting_started/index.rst +++ b/getting_started/index.rst @@ -12,4 +12,5 @@ The **Getting Started** page describes the following things you need to start us preparing_your_machine_to_install_sqream installing_sqream executing_statements_in_sqream - performing_basic_sqream_operations \ No newline at end of file + performing_basic_sqream_operations + hardware_guide \ No newline at end of file From f7cb29376a22d163b8ff7427e7777234795b19fe Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 24 Jul 2022 17:07:39 +0300 Subject: [PATCH 0143/1892] TPD-233 --- operational_guides/access_control.rst | 81 ++++++++----------- .../alter_default_permissions.rst | 3 +- .../access_control_commands/grant.rst | 43 +++++----- 3 files changed, 61 insertions(+), 66 deletions(-) diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index 7f92f8eaf..ffe687213 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -4,61 +4,42 @@ Access Control ************** -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 Overview ========== +Access control provides authentication and authorization in SQream DB. SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. -Access control provides authentication and authorization in SQream DB. +SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. -SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. +Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. -SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. +The following: -In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. +* **Role** - a role can be a user, a group, or both. Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. -Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. + :: -To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. +* **Authentication** - verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. + :: -Terminology -================ +* **Authorization** - checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. -Roles ----------- - -:term:`Role` : a role can be a user, a group, or both. - -Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. - -Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. - -Authentication --------------------- - -:term:`Authentication` : verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. - - -Authorization ----------------- - -:term:`Authorization` : checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. - - -Roles +Managing Roles ===== +Roles are used for both users and groups. Roles are global across all databases in the SQream DB cluster. To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. -Roles are used for both users and groups. +The Roles section describes the following role-related operations: -Roles are global across all databases in the SQream DB cluster. - -To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. +.. contents:: + :local: + :depth: 1 -Creating new roles (users) +Creating New Roles (Users) ------------------------------ - A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. For example: @@ -81,7 +62,7 @@ Examples: A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. -Dropping a user +Dropping Users --------------- .. code-block:: postgres @@ -94,7 +75,7 @@ Examples: DROP ROLE admin_role ; -Altering a user name +Altering a User Name ------------------------ Renaming a user's role: @@ -111,7 +92,7 @@ Examples: .. _change_password: -Changing user passwords +Changing User Passwords -------------------------- To change a user role's password, grant the user a new password. @@ -122,7 +103,7 @@ To change a user role's password, grant the user a new password. .. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. -Public Role +Altering Public Role Permissions ----------- There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. @@ -130,7 +111,7 @@ There is a public role which always exists. Each role is granted to the ``PUBLIC The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. -Role membership (groups) +Altering Role Membership (Groups) ------------------------- Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. @@ -174,6 +155,7 @@ Removing users and permissions can be done with the ``REVOKE`` command: Permissions =========== +The following table displays the access control permissions: .. list-table:: :widths: auto @@ -226,6 +208,10 @@ Permissions * - table - ``INSERT`` - :ref:`insert` into the table + + * - table + - ``UPDATE`` + - :ref:`update` the value of certain columns in existing rows without creating a table * - table - ``DELETE`` @@ -254,7 +240,7 @@ Permissions GRANT ----- -:ref:`grant` gives permissions to a role. +:ref:`grant` gives permissions to a role, shown in the following syntax example: .. code-block:: postgres @@ -296,8 +282,8 @@ GRANT GRANT [, ...] TO WITH ADMIN OPTION - -``GRANT`` examples: + +The following are some ``GRANT`` examples: .. code-block:: postgres @@ -324,7 +310,7 @@ GRANT REVOKE ------ -:ref:`revoke` removes permissions from a role. +:ref:`revoke` removes permissions from a role, shown in the following syntax example: .. code-block:: postgres @@ -372,7 +358,7 @@ Examples: REVOKE CREATE FUNCTION FROM admin; -Default permissions +Default Permissions ------------------- The default permissions system (See :ref:`alter_default_permissions`) @@ -403,6 +389,7 @@ schema statement is run. | USAGE | SELECT | INSERT + | UPDATE | DELETE | DDL | EXECUTE diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 0ab200286..a49e53f88 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -43,6 +43,7 @@ The following is the syntax for altering default permissions: | USAGE | SELECT | INSERT + | UPDATE | DELETE | DDL | EXECUTE @@ -103,7 +104,7 @@ The following is an example of the output generated from the above queries: | master | NULL | public | public | select | +-----------------------+----------------------+-------------------+--------------+------------------------------+ -For more information about default permissions, see `Default Permissions `_. +For more information about default permissions, see `Default Permissions `_. Granting Automatic Permissions for Newly Created Schemas ------------------------------------------------- diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index ceac48f7a..d86522900 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -15,13 +15,9 @@ Learn more about the permission system in the :ref:`access control guide Date: Sun, 24 Jul 2022 17:24:04 +0300 Subject: [PATCH 0144/1892] Removed HW Guide from Index --- operational_guides/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/operational_guides/index.rst b/operational_guides/index.rst index aca578e8b..9deb0835c 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -24,4 +24,3 @@ This section summarizes the following operational guides: seeing_system_objects_as_ddl configuration optimization_best_practices - hardware_guide From 37f40386591f873b287020ec0c6864a5acd0164f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 26 Jul 2022 10:25:02 +0300 Subject: [PATCH 0145/1892] Removed internal items. --- reference/sql/sql_statements/index.rst | 4 - .../get_extents_file_list_for_chunk.rst | 107 ------------- .../get_metadata_chunk_key.rst | 151 ------------------ releases/2022.1.rst | 11 -- 4 files changed, 273 deletions(-) delete mode 100644 reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst delete mode 100644 reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 1a075f69e..d2b92b152 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -108,10 +108,6 @@ The following table shows the Utility commands: - Usage * - :ref:`EXPLAIN` - Returns a static query plan, which can be used to debug query plans - * - :ref:`GET_EXTENTS_FILE_FOR_CHUNK` - - Points to all files that contain data related to a specific chunk |icon-new_2022.1| - * - :ref:`GET_METADATA_CHUNK_KEY` - - Returns a list of metadata key values for the chunks that you specify |icon-New_Dark_Gray| * - :ref:`SELECT GET_LICENSE_INFO` - View a user's license information * - :ref:`SELECT GET_DDL` diff --git a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst b/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst deleted file mode 100644 index 968c0655a..000000000 --- a/reference/sql/sql_statements/utility_commands/get_extents_file_list_for_chunk.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. _get_extents_file_list_for_chunk: - -******************** -GET_EXTENTS_FILE_FOR_CHUNK -******************** -The ``GET_EXTENTS_FILE_FOR_CHUNK`` |icon-new_2022.1| command points to all files that contain data related to a specific chunk. This command is used for debugging purposes. - -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png - :align: middle - :width: 110 - -This reference page includes the following information: - -.. contents:: - :local: - :depth: 1 - -Syntax -========== -The following is the syntax for the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: - -.. code-block:: postgres - - select get_extents_file_list_for_chunk(database_name, " - "table_id, chunk_id);" - -Parameters -============ -The following table shows the ``GET_EXTENTS_FILE_FOR_CHUNK`` parameters: - -.. list-table:: - :widths: 10 100 - :header-rows: 1 - - * - Parameter - - Description - * - ``database_name`` - - The name of the database where the chunk is located. - * - ``table_id`` - - The ID of the table where the chunk is located. - * - ``chunk_id`` - - The ID of the chunk. - -Example -=========== -The following is an example of the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: - -.. code-block:: postgres - - master=> select get_extents_file_list_for_chunk('master', 0, 3); - -Output -========== -The following table describes the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: - -.. list-table:: - :widths: 25 25 25 25 - :header-rows: 1 - - * - Parameter - - Description - - Type - - Example - - * - ``database_name`` - - The name of the database where the chunk is located. - - Text - - ``master`` - - * - ``table_name`` - - The ID of the table where the chunk is located. - - Numeric - - ``0`` - - * - ``table_id`` - - The ID of the column. - - Numeric - - ``0`` - - * - ``column_id`` - - The status of the chunk. - - Numeric - - ``1`` - - * - ``chunk_id`` - - Describes the state of the chunk. - - Numeric - - ``chunk_state::`` - - * - ``file_path`` - - Shows the path of the file. - - Text - - /home/sqream_testing_temp/sqreamdb/databases/master/tables - -The following is an example of the output generated from the ``GET_EXTENTS_FILE_FOR_CHUNK`` command: - -.. code-block:: postgres - - master,public.t_1,0,0,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables - master,public.t_1,0,1,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables - master,public.t_1,0,2,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables - master,public.t_1,0,3,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables - master,public.t_1,0,4,3,/home/sqream_testing_temp/sqreamdb/databases/master/tables - -Permissions -============= -The ``GET_EXTENTS_FILE_FOR_CHUNK`` requires no special permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst b/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst deleted file mode 100644 index 784a54246..000000000 --- a/reference/sql/sql_statements/utility_commands/get_metadata_chunk_key.rst +++ /dev/null @@ -1,151 +0,0 @@ -.. _get_metadata_chunk_key: - -******************** -GET_METADATA_CHUNK_KEY -******************** -The ``GET_METADATA_CHUNK_KEY`` |icon-new_2022.1| command returns specific metadata key values for user-specified chunks. - -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png - :align: middle - :width: 110 - -This reference page includes the following information: - -.. contents:: - :local: - :depth: 1 - -Syntax -========== -The following is the syntax for the ``GET_METADATA_CHUNK_KEY`` command: - -.. code-block:: postgres - - get_metadata_chunk_key(database_name, table_id, chunk_id); - -Parameters -============ -The following table shows the ``GET_METADATA_CHUNK_KEY`` parameters: - -.. list-table:: - :widths: 10 100 - :header-rows: 1 - - * - Parameter - - Description - * - ``database_name`` - - The name of the database where the chunk is located. - * - ``table_id`` - - The ID of the table where the chunk is located. - * - ``chunk_id`` - - The ID of the chunk. - -Example -=========== -The following is an example of the ``GET_METADATA_CHUNK_KEY`` command: - -.. code-block:: postgres - - master=> select get_metadata_chunk_key('master', 0, 1); - -Output -========== -The following table describes the output generated from the ``GET_METADATA_CHUNK_KEY`` command: - -.. list-table:: - :widths: 25 25 25 25 - :header-rows: 1 - - * - Parameter - - Description - - Type - - Example - - * - ``database_name`` - - The name of the database where the chunk is located. - - Text - - ``master`` - - * - ``table_id`` - - The ID of the table where the chunk is located. - - Numeric - - ``0`` - - * - ``column_id`` - - The ID of the column. - - Numeric - - ``0`` - - * - ``chunk_status`` - - The status of the chunk. - - Numeric - - ``1`` - - * - ``chunk_aligned`` - - Describes the state of the chunk. - - Text - - ``chunk_state::`` - - * - ``offset_in_file`` - - Shows the file's offset setting. - - Numeric - - ``-1`` - - * - ``compressed_size`` - - Shows the file's compressed size. - - Numeric - - ``0`` - - * - ``uncompressed_size`` - - Shows the file's uncompressed size. - - Numeric - - ``2`` - - * - ``compression_type`` - - Shows the file's compression type. - - Numeric - - ``2`` - - * - ``min_long`` - - Shows the minimum value of the type. - - Long - - ``25`` - - * - ``max_long`` - - Shows the maximum value in the chunk of a number. - - Long - - ``12345`` - - * - ``min_string_max_string`` - - Shows the minimum value of the string type. - - String - - ``"abc"`` - - * - ``min_numeric`` - - Shows the minimum value of the numeric type in the chunk. - - Numeric - - ``12.22`` - - * - ``max_numeric`` - - Shows the maximum value of the numeric type in the chunk. - - Numeric - - ``555.22`` - - * - ``column_aligned`` - - Relevant to text columns, aligment in memory. - - Boolean - - ``Yes`` / ``No`` - -The following is an example of the output generated from the ``GET_METADATA_CHUNK_KEY`` command: - -.. code-block:: postgres - - master,0,0,1,chunk_state::clean,1,0,2,2,flat,0,0,,,0x7f722ffb7c60,0x7f722ffb7c70,1 - master,0,1,1,chunk_state::clean,1,0,8,8,flat,1,2,,,0x7f722ffb7c60,0x7f722ffb7c70,1 - master,0,2,1,chunk_state::clean,1,0,2,2,flat,0,0,,,0x7f722ffb7c60,0x7f722ffb7c70,1 - master,0,3,1,chunk_state::clean,1,0,8,8,flat,3,3,,,0x7f722ffb7c60,0x7f722ffb7c70,1 - master,0,4,1,chunk_state::clean,1,0,16,16,flat,0,0,abc,dfg,0x7f722ffb7c60,0x7f722ffb7c70,1 - -Permissions -============= -The ``GET_METADATA_CHUNK_KEY`` requires no special permissions. \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index f02676c34..3c5ae24e6 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -16,7 +16,6 @@ The 2022.1 Release Notes describes the following: * Enhanced security features. * New data manipulation command. * Additional data ingestion format. -* New utility commands. New Features ---------- @@ -46,16 +45,6 @@ SQream now supports ingesting data from Avro files. For more information, see `Inserting Data from Avro `_. -New Utility Commands -************ -The following two new utility commands have been created: - -* `GET EXTENTS FILE FOR CHUNK `_ - points to all files that contain data related to a specific chunk. This command is used for debugging purposes. - - :: - -* `GET_METADATA_CHUNK_KEY `_ - returns specific metadata key values for user-specified chunks. - Known Issues --------- The following table lists the known issues for Version 2022.1: From ab2544bca967738da725b715b8fd76f937e397ca Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 26 Jul 2022 14:38:05 +0300 Subject: [PATCH 0146/1892] Corrected the links. --- configuration_guides/admin_cluster_flags.rst | 2 +- configuration_guides/admin_regular_flags.rst | 48 +++++++++---------- configuration_guides/admin_worker_flags.rst | 8 ++-- .../generic_regular_flags.rst | 26 +++++----- configuration_guides/generic_worker_flags.rst | 2 +- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/configuration_guides/admin_cluster_flags.rst b/configuration_guides/admin_cluster_flags.rst index 3c74819d6..f17cee34a 100644 --- a/configuration_guides/admin_cluster_flags.rst +++ b/configuration_guides/admin_cluster_flags.rst @@ -6,4 +6,4 @@ Cluster Administration Flags The **Cluster Administration Flags** page describes **Cluster** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Persisting Your Cache Directory `_ \ No newline at end of file +* `Persisting Your Cache Directory `_ \ No newline at end of file diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 5300310b6..064fc4b1a 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -5,27 +5,27 @@ Regular Administration Flags ************************* The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Bin Size `_ -* `Setting CUDA Memory `_ -* `Limiting Runtime to Utility Functions `_ -* `Enabling High Bin Control Granularity `_ -* `Reducing CPU Hashtable Sizes `_ -* `Setting Chunk Size for Copying from CPU to GPU `_ -* `Indicating GPU Synchronicity `_ -* `Enabling Modification of R&D Flags `_ -* `Checking for Post-Production CUDA Errors `_ -* `Enabling Modification of clientLogger_debug File `_ -* `Activating the NVidia Profiler Markers `_ -* `Appending String at End of Log Lines `_ -* `Monitoring and Printing Pinned Allocation Reports `_ -* `Increasing Chunk Size to Reduce Query Speed `_ -* `Adding Rechunker before Expensing Chunk Producer `_ -* `Setting the Buffer Size `_ -* `Setting Memory Used to Abort Server `_ -* `Splitting Large Reads for Concurrent Execution `_ -* `Setting Worker Amount to Handle Concurrent Reads `_ -* `Setting Implicit Casts in ORC Files `_ -* `Setting Timeout Limit for Locking Objects before Executing Statements `_ -* `Interpreting Decimal Literals as Double Instead of Numeric `_ -* `Interpreting VARCHAR as TEXT `_ -* `VARCHAR Identifiers `_ +* `Setting Bin Size `_ +* `Setting CUDA Memory `_ +* `Limiting Runtime to Utility Functions `_ +* `Enabling High Bin Control Granularity `_ +* `Reducing CPU Hashtable Sizes `_ +* `Setting Chunk Size for Copying from CPU to GPU `_ +* `Indicating GPU Synchronicity `_ +* `Enabling Modification of R&D Flags `_ +* `Checking for Post-Production CUDA Errors `_ +* `Enabling Modification of clientLogger_debug File `_ +* `Activating the NVidia Profiler Markers `_ +* `Appending String at End of Log Lines `_ +* `Monitoring and Printing Pinned Allocation Reports `_ +* `Increasing Chunk Size to Reduce Query Speed `_ +* `Adding Rechunker before Expensing Chunk Producer `_ +* `Setting the Buffer Size `_ +* `Setting Memory Used to Abort Server `_ +* `Splitting Large Reads for Concurrent Execution `_ +* `Setting Worker Amount to Handle Concurrent Reads `_ +* `Setting Implicit Casts in ORC Files `_ +* `Setting Timeout Limit for Locking Objects before Executing Statements `_ +* `Interpreting Decimal Literals as Double Instead of Numeric `_ +* `Interpreting VARCHAR as TEXT `_ +* `VARCHAR Identifiers `_ diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 2be570695..cd1a527d5 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -5,7 +5,7 @@ Worker Administration Flags ************************* The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Total Device Memory Usage in SQream Instance `_ -* `Enabling Manually Setting Reported IP `_ -* `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ \ No newline at end of file +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ +* `Assigning Local Network IP `_ \ No newline at end of file diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index f8235ae07..83afa9e8f 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -6,16 +6,16 @@ Regular Generic Flags The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: -* `Flipping Join Order to Force Equijoins `_ -* `Determining Client Level `_ -* `Setting CPU to Compress Defined Columns `_ -* `Setting Query Memory Processing Limit `_ -* `Setting the Spool Memory `_ -* `Setting Cache Partitions `_ -* `Setting Cache Flushing `_ -* `Setting InMemory Spool Memory `_ -* `Setting Disk Spool Memory `_ -* `Setting Spool Saved File Directory Location `_ -* `Setting Data Stored Persistently on Cache `_ -* `Setting Persistent Spool Saved File Directory Location `_ -* `Setting Session Tag Name `_ \ No newline at end of file +* `Flipping Join Order to Force Equijoins `_ +* `Determining Client Level `_ +* `Setting CPU to Compress Defined Columns `_ +* `Setting Query Memory Processing Limit `_ +* `Setting the Spool Memory `_ +* `Setting Cache Partitions `_ +* `Setting Cache Flushing `_ +* `Setting InMemory Spool Memory `_ +* `Setting Disk Spool Memory `_ +* `Setting Spool Saved File Directory Location `_ +* `Setting Data Stored Persistently on Cache `_ +* `Setting Persistent Spool Saved File Directory Location `_ +* `Setting Session Tag Name `_ \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst index 97cee4ecf..59fb9ac7a 100644 --- a/configuration_guides/generic_worker_flags.rst +++ b/configuration_guides/generic_worker_flags.rst @@ -5,4 +5,4 @@ Worker Generic Flags ************************* The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: - * `Persisting Your Cache Directory `_ \ No newline at end of file + * `Persisting Your Cache Directory `_ \ No newline at end of file From 5956468d1b8c57b9724f109fc4aecd658ee18772 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 26 Jul 2022 17:13:50 +0300 Subject: [PATCH 0147/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index a7cb3e68d..3370698cf 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -22,4 +22,6 @@ The following is an example of encrypting a new table: last_name TEXT(128), salary INT(6) ENCRYPT); -.. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. \ No newline at end of file +.. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. + +Note that the master key is hard-coded in the system and cannot be changed. From 027a982ceddb086857411d6f3d51ad073f020e76 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 10:59:03 +0300 Subject: [PATCH 0148/1892] Released 2021.2.1.24 --- feature_guides/index.rst | 1 + feature_guides/query_healer.rst | 34 +++++++++++++++ releases/2021.2.1.24.rst | 77 +++++++++++++++++++++++++++++++++ releases/2021.2_index.rst | 1 + 4 files changed, 113 insertions(+) create mode 100644 feature_guides/query_healer.rst create mode 100644 releases/2021.2.1.24.rst diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 2ca100a0f..6011d5e0b 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -11,6 +11,7 @@ This section describes the following features: :maxdepth: 1 :titlesonly: + query_healer key_evaluation data_encryption compression diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst new file mode 100644 index 000000000..7a2e0bc8d --- /dev/null +++ b/feature_guides/query_healer.rst @@ -0,0 +1,34 @@ +.. _query_healer: + +*********************** +Query Healer +*********************** +The **Query Healer** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +---------- +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. + +Configuring the Healer +------------------ +The following flags are required to configure the Query Healer: + + * **isHealerOn** - Enables the Query Healer. + + :: + + * **healerMaxInactivityHours** - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. + +For more information, see the following Administration Worker flags: + + * :ref:`is_healer_on` + + :: + + * :ref:`healerMaxInactivityHours \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst new file mode 100644 index 000000000..7d8a1fd28 --- /dev/null +++ b/releases/2021.2.1.24.rst @@ -0,0 +1,77 @@ +.. _2021.2.1.24: + +************************** +Release Notes 2021.2.1.24 +************************** +The 2021.2.1.24 release notes were released on xx/xx/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2021.2.1.24 Release Notes includes a query maintenance feature. + +New Features +---------- +The 2021.2.1.24 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Query Healer +************ +The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. + +For more information, see :ref:`query_healer`. + +Known Issues +--------- +The following table lists the known issues for Version 2021.2.1.24: + ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+====================================================================================================================================+ +| SQ-10071 | An error occurred on existing subqueries with ``TEXT`` and ``VARCHAR`` equality conditions. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10606 | Queries were getting stuck in the queue for a prolonged time. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10691 | The DB schema identifier was causing an error when running queries from joins suite. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10902 | Inserting a null value into non-null column was causing SQream to crash. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10918 | The Workload Manager was only assigning jobs sequentially, delaying user SQLs assigned to workers running very large jobs. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10955 | Metadata filters were not being applied when users filtered by nullable dates using ``dateadd`` | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11088 | Specific workers caused low performance during compilation. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The Resolved Issues section is not relevant for Version 2021.2.1.24. + +Operations and Configuration Changes +-------- +No relevant operations and configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +Version 2021.2.1.24 includes no deprecated features. + +End of Support +------- +The End of Support section is not relevant to Version 2021.2.1.24. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2021.2.1.24 diff --git a/releases/2021.2_index.rst b/releases/2021.2_index.rst index 77a22b0ae..9bee5fd66 100644 --- a/releases/2021.2_index.rst +++ b/releases/2021.2_index.rst @@ -13,5 +13,6 @@ The 2021.2 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2021.2.1.24 2021.2.1 2021.2 \ No newline at end of file From 30f98c94e945de893f18b2a60f8dfbe7c9a9db4c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:02:26 +0300 Subject: [PATCH 0149/1892] Fixed release date --- releases/2021.2.1.24.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 7d8a1fd28..125092f0e 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2021.2.1.24 ************************** -The 2021.2.1.24 release notes were released on xx/xx/2022 and describe the following: +The 2021.2.1.24 release notes were released on 7/28/2022 and describe the following: .. contents:: :local: From 284c11bbd151ff9d63d9797bf103197a538467b1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:15:54 +0300 Subject: [PATCH 0150/1892] Added missing flags --- configuration_guides/admin_worker_flags.rst | 10 ++++++---- .../healer_max_inactivity_hours.rst | 14 ++++++++++++++ configuration_guides/is_healer_on.rst | 14 ++++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 configuration_guides/healer_max_inactivity_hours.rst create mode 100644 configuration_guides/is_healer_on.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index cd1a527d5..a3ca2710a 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -5,7 +5,9 @@ Worker Administration Flags ************************* The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Total Device Memory Usage in SQream Instance `_ -* `Enabling Manually Setting Reported IP `_ -* `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ \ No newline at end of file +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ +* `Assigning Local Network IP `_ +* `Assigning Local Network IP `_ +* `Assigning Local Network IP `_ \ No newline at end of file diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst new file mode 100644 index 000000000..730bd16ef --- /dev/null +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -0,0 +1,14 @@ +.. _healer_max_inactivity_hours + +************************* +Query Healer +************************* +The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The following describes the ``healerMaxInactivityHours`` flag: + +* **Data type** - size_t +* **Default value** - ``5`` +* **Allowed values** - 1-4000000000 + +For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst new file mode 100644 index 000000000..8b90654ec --- /dev/null +++ b/configuration_guides/is_healer_on.rst @@ -0,0 +1,14 @@ +.. _is_healer_on: + +************************* +Enabling the Query Healer +************************* +The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. + +The following describes the ``is_healer_on`` flag: + +* **Data type** - boolean +* **Default value** - ``true`` +* **Allowed values** - ``true``, ``false`` + +For related flags, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file From a7a03e2341991417303d52844440b1f0a50cee5b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:18:30 +0300 Subject: [PATCH 0151/1892] Update healer_max_inactivity_hours.rst --- configuration_guides/healer_max_inactivity_hours.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst index 730bd16ef..d05d46014 100644 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -1,4 +1,4 @@ -.. _healer_max_inactivity_hours +.. _healer_max_inactivity_hours: ************************* Query Healer From 1d47c5e558e3b57126a3f7d83010026d48af290a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:20:55 +0300 Subject: [PATCH 0152/1892] REmoved key evaluation --- feature_guides/index.rst | 1 - feature_guides/key_evaluation.rst | 13 ---- .../key_evaluation_operational_modes.rst | 70 ------------------- feature_guides/key_evaluation_overview.rst | 16 ----- 4 files changed, 100 deletions(-) delete mode 100644 feature_guides/key_evaluation.rst delete mode 100644 feature_guides/key_evaluation_operational_modes.rst delete mode 100644 feature_guides/key_evaluation_overview.rst diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 6011d5e0b..d70ceb705 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,7 +12,6 @@ This section describes the following features: :titlesonly: query_healer - key_evaluation data_encryption compression python_functions diff --git a/feature_guides/key_evaluation.rst b/feature_guides/key_evaluation.rst deleted file mode 100644 index e016e68c7..000000000 --- a/feature_guides/key_evaluation.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. _key_evaluation: - -************************** -Key Evaluation -************************** -The **Key Evaluation** section describes the following: - -.. toctree:: - :maxdepth: 4 - :titlesonly: - - key_evaluation_overview - key_evaluation_operational_modes \ No newline at end of file diff --git a/feature_guides/key_evaluation_operational_modes.rst b/feature_guides/key_evaluation_operational_modes.rst deleted file mode 100644 index feb4fd9c1..000000000 --- a/feature_guides/key_evaluation_operational_modes.rst +++ /dev/null @@ -1,70 +0,0 @@ -.. _key_evaluation_operational_modes: - -************************** -Operational Modes -************************** -Key Evaluation can be used to do one of the following: - -**Comment** - *Do users initiate one of these modes, or do they occur in the background on their own? The answer to this question determines whether key evaluation belongs in Feature Guides or Operational Guides.* - -.. contents:: - :local: - :depth: 1 - -View All Problematic Chunk Keys ----------- -You can use the **View** mode to find all problematic keys in the database for all databases and/or tables. - -The following shows the View command options: - -.. code-block:: - - $ select  keys_evaluate ('view'); - -.. code-block:: - - $ select  keys_evaluate ('view', 'master'); - -.. code-block:: - - $ select  keys_evaluate ('view', 'master', 'public.tbl'); - -Find and Clean Problematic Keys from Storage ----------- -You can use the **Clean Storage** mode to find all problematic keys located in the Storage for all databases. - -The following shows the Clean Storage command: - -.. code-block:: - - $ select  keys_evaluate ('clean_storage'); - -.. note:: This mode backs up the levelDB to the **backup** folder in the cluster before finding and cleaning problematic keys from your storage. - -Find and Clean Problematic Keys from a Database ----------- -You can use the **Clean Database** mode to find and clean all problematic keys located for a specific database and/or table. - -The following shows the Clean Database command options: - -.. code-block:: - - $ select keys_evaluate ('clean_database','master'); - -.. code-block:: - - $ select keys_evaluate ('clean_database','master', 'public.tbl'); - -.. note:: This mode backs up the levelDB to the **backup** folder in the cluster before finding and cleaning problematic keys from your database. - -Clean Specifically Defined Chunk Keys ----------- -**Comment** - *Currently not supported. Remove until further notice?* - -You can use the **Clean Chunk Key** mode to clean a specific problematic chunk key. **Comment** - *Note: data_diag vs keys_evaluate.* - -The following shows the Clean Chunk Key command options: - -.. code-block:: - - $ select data_diag (12, ''); \ No newline at end of file diff --git a/feature_guides/key_evaluation_overview.rst b/feature_guides/key_evaluation_overview.rst deleted file mode 100644 index 3d3aabf8a..000000000 --- a/feature_guides/key_evaluation_overview.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _key_evaluation_overview: - -************************** -Overview -************************** -The **Key Evaluation** feature resolves conflicts caused by ingesting and deleting data at the same time. Although this rarely occurs, it causes the leveldb to restore keys pointing to deleted data. In turn, this causes SQream metadata to search for deleted files. - -An indication that this conflict has occurred is SQream's inability to retrieve deleted data pointers, generating the type of error shown below: - -.. code-block:: console - - Internal Runtime Error *** Error opening [errno 2 No such file or directory] file name /mnt/disk1/sqream_cluster/databases/******/tables/289/17/17-391270 - -In addition, key evaluation prevents the database from creating phantom keys, which are duplicate chunk keys generated when data is ingested. Under normal circumstances ingesting data creates incrementing chunk keys. - -**Comment** - *Please confirm the reason I provided based on my understanding of the source doc.* \ No newline at end of file From 100d27230010fef969978571cb048dd43d78c091 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:26:58 +0300 Subject: [PATCH 0153/1892] Fixed link --- feature_guides/query_healer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 7a2e0bc8d..4d9b9e998 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -31,4 +31,4 @@ For more information, see the following Administration Worker flags: :: - * :ref:`healerMaxInactivityHours \ No newline at end of file + * :ref:`healer_max_inactivity_hours \ No newline at end of file From 34ec04726ada8871613cdf4090e073615232b5f0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:41:16 +0300 Subject: [PATCH 0154/1892] Update query_healer.rst --- feature_guides/query_healer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 4d9b9e998..4b7120db2 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -31,4 +31,4 @@ For more information, see the following Administration Worker flags: :: - * :ref:`healer_max_inactivity_hours \ No newline at end of file + * :ref:`healer_max_inactivity_hours` \ No newline at end of file From f4220cf1d4f71be492061949de2e17effa457d6d Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:48:46 +0300 Subject: [PATCH 0155/1892] Update admin_worker_flags.rst --- configuration_guides/admin_worker_flags.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index a3ca2710a..35edaf4ff 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -9,5 +9,5 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ -* `Assigning Local Network IP `_ -* `Assigning Local Network IP `_ \ No newline at end of file +* `Enabling the Query Healer `_ +* `Configuring the Query Healer `_ \ No newline at end of file From b3c547958ab046c4e819f759ee4cda988bad5239 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 11:59:10 +0300 Subject: [PATCH 0156/1892] Update healer_max_inactivity_hours.rst --- configuration_guides/healer_max_inactivity_hours.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst index d05d46014..56ddb78fc 100644 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -1,7 +1,7 @@ .. _healer_max_inactivity_hours: ************************* -Query Healer +Configuring the Query Healer ************************* The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. From e2dbe63ebe42fb20aad7e4cdb2e826f4e3856f42 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 12:02:16 +0300 Subject: [PATCH 0157/1892] Update admin_worker_flags.rst --- configuration_guides/admin_worker_flags.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 35edaf4ff..def1e8dac 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -9,5 +9,5 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ -* `Enabling the Query Healer `_ +* `Enabling the Query Healer `_ * `Configuring the Query Healer `_ \ No newline at end of file From 55c2ae428cc8d95f40e0588bf01a55b54a1f3a36 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 12:08:47 +0300 Subject: [PATCH 0158/1892] Update admin_worker_flags.rst --- configuration_guides/admin_worker_flags.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index def1e8dac..5725fc507 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -5,9 +5,9 @@ Worker Administration Flags ************************* The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Total Device Memory Usage in SQream Instance `_ -* `Enabling Manually Setting Reported IP `_ -* `Setting Port Used for Metadata Server Connection `_ +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ * `Enabling the Query Healer `_ -* `Configuring the Query Healer `_ \ No newline at end of file +* `Configuring the Query Healer `_ \ No newline at end of file From 207472f01f0713446f202e6146dc80d551c70c67 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 12:15:37 +0300 Subject: [PATCH 0159/1892] Added log example --- feature_guides/query_healer.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 4b7120db2..07e2dc0e4 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -13,6 +13,12 @@ Overview ---------- The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. +The following is an example of a log record for a query stuck in the query detection phase for more than five hours: + + .. code-block:: console + + 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours + Configuring the Healer ------------------ The following flags are required to configure the Query Healer: From c5f344027a90af81ffaf7e8ecea154a7f6cb08b8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 12:47:04 +0300 Subject: [PATCH 0160/1892] Update query_healer.rst --- feature_guides/query_healer.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 07e2dc0e4..cb50549b8 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -15,9 +15,9 @@ The **Query Healer** periodically examines the progress of running statements, c The following is an example of a log record for a query stuck in the query detection phase for more than five hours: - .. code-block:: console +.. code-block:: console - 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours + 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours Configuring the Healer ------------------ From 664e4fe191aab8deafce010b68399c944655791b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 14:06:46 +0300 Subject: [PATCH 0161/1892] Created and Published 2022.1.1 Including all related documentation updates. --- configuration_guides/admin_worker_flags.rst | 5 +- configuration_guides/login_max_retries.rst | 11 + operational_guides/access_control.rst | 587 +----------------- .../access_control_departmental_example.rst | 185 ++++++ .../access_control_managing_roles.rst | 124 ++++ .../access_control_overview.rst | 20 + .../access_control_password_policy.rst | 42 ++ .../access_control_permissions.rst | 218 +++++++ releases/2022.1.1.rst | 115 ++++ releases/2022.1_index.rst | 17 + 10 files changed, 744 insertions(+), 580 deletions(-) create mode 100644 configuration_guides/login_max_retries.rst create mode 100644 operational_guides/access_control_departmental_example.rst create mode 100644 operational_guides/access_control_managing_roles.rst create mode 100644 operational_guides/access_control_overview.rst create mode 100644 operational_guides/access_control_password_policy.rst create mode 100644 operational_guides/access_control_permissions.rst create mode 100644 releases/2022.1.1.rst create mode 100644 releases/2022.1_index.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 5725fc507..453c66af8 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -8,6 +8,7 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Setting Total Device Memory Usage in SQream Instance `_ * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ +* `Assigning Local Network IP `_ * `Enabling the Query Healer `_ -* `Configuring the Query Healer `_ \ No newline at end of file +* `Configuring the Query Healer `_ +* `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst new file mode 100644 index 000000000..bf3ae6d40 --- /dev/null +++ b/configuration_guides/login_max_retries.rst @@ -0,0 +1,11 @@ +.. _login_max_retries: + +************************* +Adjusting Permitted Log-in Attempts +************************* +The ``loginMaxRetries`` flag sets the permitted log-in attempts. + +The following describes the ``loginMaxRetries`` flag: + +* **Data type** - size_t +* **Default value** - ``5`` \ No newline at end of file diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index ffe687213..bd25d0d99 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -4,581 +4,12 @@ Access Control ************** -.. contents:: - :local: - :depth: 1 - -Overview -========== -Access control provides authentication and authorization in SQream DB. SQream DB manages authentication and authorization using a role-based access control system (RBAC), like ANSI SQL and other SQL products. - -SQream DB has a default permissions system which is inspired by Postgres, but with more power. In most cases, this allows an administrator to set things up so that every object gets permissions set automatically. In SQream DB, users log in from any worker which verifies their roles and permissions from the metadata server. Each statement issues commands as the currently logged in role. - -Roles are defined at the cluster level, meaning they are valid for all databases in the cluster. To bootstrap SQream DB, a new install will always have one ``SUPERUSER`` role, typically named ``sqream``. To create more roles, you should first connect as this role. - -The following: - -* **Role** - a role can be a user, a group, or both. Roles can own database objects (e.g. tables), and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. - - :: - -* **Authentication** - verifying the identity of the role. User roles have usernames (:term:`role names`) and passwords. - - :: - -* **Authorization** - checking the role has permissions to do a particular thing. The :ref:`grant` command is used for this. - -Managing Roles -===== -Roles are used for both users and groups. Roles are global across all databases in the SQream DB cluster. To use a ``ROLE`` as a user, it should have a password, the login permission, and connect permissions to the relevant databases. - -The Roles section describes the following role-related operations: - -.. contents:: - :local: - :depth: 1 - -Creating New Roles (Users) ------------------------------- -A user role can log in to the database, so it should have ``LOGIN`` permissions, as well as a password. - -For example: - -.. code-block:: postgres - - CREATE ROLE role_name ; - GRANT LOGIN to role_name ; - GRANT PASSWORD 'new_password' to role_name ; - GRANT CONNECT ON DATABASE database_name to role_name ; - -Examples: - -.. code-block:: postgres - - CREATE ROLE new_role_name ; - GRANT LOGIN TO new_role_name; - GRANT PASSWORD 'my_password' TO new_role_name; - GRANT CONNECT ON DATABASE master TO new_role_name; - -A database role may have a number of permissions that define what tasks it can perform. These are assigned using the :ref:`grant` command. - -Dropping Users ---------------- - -.. code-block:: postgres - - DROP ROLE role_name ; - -Examples: - -.. code-block:: postgres - - DROP ROLE admin_role ; - -Altering a User Name ------------------------- - -Renaming a user's role: - -.. code-block:: postgres - - ALTER ROLE role_name RENAME TO new_role_name ; - -Examples: - -.. code-block:: postgres - - ALTER ROLE admin_role RENAME TO copy_role ; - -.. _change_password: - -Changing User Passwords --------------------------- - -To change a user role's password, grant the user a new password. - -.. code-block:: postgres - - GRANT PASSWORD 'new_password' TO rhendricks; - -.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. - -Altering Public Role Permissions ------------ - -There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. - -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. - - -Altering Role Membership (Groups) -------------------------- - -Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. - -To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. - -The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. - -.. code-block:: postgres - - CREATE ROLE my_group; - -Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: - -.. code-block:: postgres - - -- Add my_user to this group - GRANT my_group TO my_user; - - -To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. - -All member roles then inherit the permissions from the group. For example: - -.. code-block:: postgres - - -- Grant all group users connect permissions - GRANT CONNECT ON DATABASE a_database TO my_group; - - -- Grant all permissions on tables in public schema - GRANT ALL ON all tables IN schema public TO my_group; - -Removing users and permissions can be done with the ``REVOKE`` command: - -.. code-block:: postgres - - -- remove my_other_user from this group - REVOKE my_group FROM my_other_user; - -.. _permissions_table: - -Permissions -=========== -The following table displays the access control permissions: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Object/layer - - Permission - - Description - - * - all databases - - ``LOGIN`` - - use role to log into the system (the role also needs connect permission on the database it is connecting to) - - * - all databases - - ``PASSWORD`` - - the password used for logging into the system - - * - all databases - - ``SUPERUSER`` - - no permission restrictions on any activity - - * - database - - ``SUPERUSER`` - - no permission restrictions on any activity within that database (this does not include modifying roles or permissions) - - * - database - - ``CONNECT`` - - connect to the database - - * - database - - ``CREATE`` - - create schemas in the database - - * - database - - ``CREATE FUNCTION`` - - create and drop functions - - * - schema - - ``USAGE`` - - allows additional permissions within the schema - - * - schema - - ``CREATE`` - - create tables in the schema - - * - table - - ``SELECT`` - - :ref:`select` from the table - - * - table - - ``INSERT`` - - :ref:`insert` into the table - - * - table - - ``UPDATE`` - - :ref:`update` the value of certain columns in existing rows without creating a table - - * - table - - ``DELETE`` - - :ref:`delete` and :ref:`truncate` on the table - - * - table - - ``DDL`` - - drop and alter on the table - - * - table - - ``ALL`` - - all the table permissions - - * - function - - ``EXECUTE`` - - use the function - - * - function - - ``DDL`` - - drop and alter on the function - - * - function - - ``ALL`` - - all function permissions - -GRANT ------ - -:ref:`grant` gives permissions to a role, shown in the following syntax example: - -.. code-block:: postgres - - -- Grant permissions at the instance/ storage cluster level: - GRANT - - { SUPERUSER - | LOGIN - | PASSWORD '' - } - TO [, ...] - - -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} - - ON DATABASE [, ...] - TO [, ...] - - -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} - ON SCHEMA [, ...] - TO [, ...] - - -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} - ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} - TO [, ...] - - -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name - TO role; - - -- Allows role2 to use permissions granted to role1 - GRANT [, ...] - TO - - -- Also allows the role2 to grant role1 to other roles: - GRANT [, ...] - TO - WITH ADMIN OPTION - -The following are some ``GRANT`` examples: - -.. code-block:: postgres - - GRANT LOGIN,superuser TO admin; - - GRANT CREATE FUNCTION ON database master TO admin; - - GRANT SELECT ON TABLE admin.table1 TO userA; - - GRANT EXECUTE ON FUNCTION my_function TO userA; - - GRANT ALL ON FUNCTION my_function TO userA; - - GRANT DDL ON admin.main_table TO userB; - - GRANT ALL ON all tables IN schema public TO userB; - - GRANT admin TO userC; - - GRANT superuser ON schema demo TO userA - - GRANT admin_role TO userB; - -REVOKE ------- - -:ref:`revoke` removes permissions from a role, shown in the following syntax example: - -.. code-block:: postgres - - -- Revoke permissions at the instance/ storage cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD - } - FROM [, ...] - - -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} - ON DATABASE [, ...] - FROM [, ...] - - -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} - ON SCHEMA [, ...] - FROM [, ...] - - -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } - ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA - - [, ...] } - FROM [, ...] - - -- Removes access to permissions in role1 by role 2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -- Removes permissions to grant role1 to additional roles from role2 - REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION - - -Examples: - -.. code-block:: postgres - - REVOKE superuser on schema demo from userA; - - REVOKE delete on admin.table1 from userB; - - REVOKE login from role_test; - - REVOKE CREATE FUNCTION FROM admin; - -Default Permissions -------------------- - -The default permissions system (See :ref:`alter_default_permissions`) -can be used to automatically grant permissions to newly -created objects (See the departmental example below for one way it can be used). - -A default permissions rule looks for a schema being created, or a -table (possibly by schema), and is table to grant any permission to -that object to any role. This happens when the create table or create -schema statement is run. - - -.. code-block:: postgres - - - ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { TABLES | SCHEMAS } - { grant_clause | DROP grant_clause} - TO ROLE { role_name | public }; - - grant_clause ::= - GRANT - { CREATE FUNCTION - | SUPERUSER - | CONNECT - | CREATE - | USAGE - | SELECT - | INSERT - | UPDATE - | DELETE - | DDL - | EXECUTE - | ALL - } - - -Departmental Example -======================= - -You work in a company with several departments. - -The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. - -The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. - -A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. - -In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. - -.. figure:: /_static/images/access_control_department_example.png - :scale: 60 % - - Our departmental example has four user group roles and seven users roles - -There will be a group for this schema for each of the following: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Group - - Activities - - * - database designers - - create, alter and drop tables - - * - updaters - - insert and delete data - - * - readers - - read data - - * - security officers - - add and remove users from these groups - -Setting up the department permissions ------------------------------------------- - -As a superuser, you connect to the system and run the following: - -.. code-block:: postgres - - -- create the groups - - CREATE ROLE my_schema_security_officers; - CREATE ROLE my_schema_database_designers; - CREATE ROLE my_schema_updaters; - CREATE ROLE my_schema_readers; - - -- grant permissions for each role - -- we grant permissions for existing objects here too, - -- so you don't have to start with an empty schema - - -- security officers - - GRANT connect ON DATABASE my_database TO my_schema_security_officers; - GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; - - GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; - GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; - - -- database designers - - GRANT connect ON DATABASE my_database TO my_schema_database_designers; - GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; - - GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; - - -- updaters - - GRANT connect ON DATABASE my_database TO my_schema_updaters; - GRANT usage ON SCHEMA my_schema TO my_schema_updaters; - - GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; - - -- readers - - GRANT connect ON DATABASE my_database TO my_schema_readers; - GRANT usage ON SCHEMA my_schema TO my_schema_readers; - - GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; - GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; - - - -- create the default permissions for new objects - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; - - -- For every table created by my_schema_database_designers, give access to my_schema_readers: - - ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema - FOR TABLES GRANT SELECT TO my_schema_readers; - -.. note:: - * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. - - * - By default, any new object created will not be accessible by our new ``my_schema_readers`` group. - Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. - - If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that - you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. - -Creating new users in the departments ------------------------------------------ - -After the group roles have been created, you can now create user roles for each of your users. - -.. code-block:: postgres - - -- create the new database designer users - - CREATE ROLE ecodd; - GRANT LOGIN TO ecodd; - GRANT PASSWORD 'ecodds_secret_password' TO ecodd; - GRANT CONNECT ON DATABASE my_database TO ecodd; - GRANT my_schema_database_designers TO ecodd; - - CREATE ROLE ebachmann; - GRANT LOGIN TO ebachmann; - GRANT PASSWORD 'another_secret_password' TO ebachmann; - GRANT CONNECT ON DATABASE my_database TO ebachmann; - GRANT my_database_designers TO ebachmann; - - -- If a user already exists, we can assign that user directly to the group - - GRANT my_schema_updaters TO rhendricks; - - -- Create users in the readers group - - CREATE ROLE jbarker; - GRANT LOGIN TO jbarker; - GRANT PASSWORD 'action_jack' TO jbarker; - GRANT CONNECT ON DATABASE my_database TO jbarker; - GRANT my_schema_readers TO jbarker; - - CREATE ROLE lbream; - GRANT LOGIN TO lbream; - GRANT PASSWORD 'artichoke123' TO lbream; - GRANT CONNECT ON DATABASE my_database TO lbream; - GRANT my_schema_readers TO lbream; - - CREATE ROLE pgregory; - GRANT LOGIN TO pgregory; - GRANT PASSWORD 'c1ca6a' TO pgregory; - GRANT CONNECT ON DATABASE my_database TO pgregory; - GRANT my_schema_readers TO pgregory; - - -- Create users in the security officers group - - CREATE ROLE hoover; - GRANT LOGIN TO hoover; - GRANT PASSWORD 'mintchip' TO hoover; - GRANT CONNECT ON DATABASE my_database TO hoover; - GRANT my_schema_security_officers TO hoover; - - -.. todo: - create some example users - show that they have the right permission - try out the with admin option. we can't really do a security officer because - only superusers can create users and logins. see what can be done - need 1-2 users in each group, for at least 2 schemas/departments - this example will be very big just to show what this setup can do ... - example: a security officer for a department which will only have - read only access to a schema can only get that with admin option - access granted to them - -After this setup: - -* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers -* Updaters will be able to insert and delete to existing and new tables -* Readers will be able to read from existing and new tables - -All this will happen without having to run any more ``GRANT`` statements. - -Any security officer will be able to add and remove users from these -groups. Creating and dropping login users themselves must be done by a -superuser. +.. toctree:: + :maxdepth: 1 + :titlesonly: + + access_control_overview + access_control_managing_roles + access_control_permissions + access_control_password_policy + access_control_departmental_example \ No newline at end of file diff --git a/operational_guides/access_control_departmental_example.rst b/operational_guides/access_control_departmental_example.rst new file mode 100644 index 000000000..0a6b55e54 --- /dev/null +++ b/operational_guides/access_control_departmental_example.rst @@ -0,0 +1,185 @@ +.. _access_control_departmental_example: + +************** +Departmental Example +************** + +You work in a company with several departments. + +The example below shows you how to manage permissions in a database shared by multiple departments, where each department has different roles for the tables by schema. It walks you through how to set the permissions up for existing objects and how to set up default permissions rules to cover newly created objects. + +The concept is that you set up roles for each new schema with the correct permissions, then the existing users can use these roles. + +A superuser must do new setup for each new schema which is a limitation, but superuser permissions are not needed at any other time, and neither are explicit grant statements or object ownership changes. + +In the example, the database is called ``my_database``, and the new or existing schema being set up to be managed in this way is called ``my_schema``. + +Our departmental example has four user group roles and seven users roles + +There will be a group for this schema for each of the following: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Group + - Activities + + * - database designers + - create, alter and drop tables + + * - updaters + - insert and delete data + + * - readers + - read data + + * - security officers + - add and remove users from these groups + +Setting up the department permissions +------------------------------------------ + +As a superuser, you connect to the system and run the following: + +.. code-block:: postgres + + -- create the groups + + CREATE ROLE my_schema_security_officers; + CREATE ROLE my_schema_database_designers; + CREATE ROLE my_schema_updaters; + CREATE ROLE my_schema_readers; + + -- grant permissions for each role + -- we grant permissions for existing objects here too, + -- so you don't have to start with an empty schema + + -- security officers + + GRANT connect ON DATABASE my_database TO my_schema_security_officers; + GRANT usage ON SCHEMA my_schema TO my_schema_security_officers; + + GRANT my_schema_database_designers TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_updaters TO my_schema_security_officers WITH ADMIN OPTION; + GRANT my_schema_readers TO my_schema_security_officers WITH ADMIN OPTION; + + -- database designers + + GRANT connect ON DATABASE my_database TO my_schema_database_designers; + GRANT usage ON SCHEMA my_schema TO my_schema_database_designers; + + GRANT create,ddl ON SCHEMA my_schema TO my_schema_database_designers; + + -- updaters + + GRANT connect ON DATABASE my_database TO my_schema_updaters; + GRANT usage ON SCHEMA my_schema TO my_schema_updaters; + + GRANT SELECT,INSERT,DELETE ON ALL TABLES IN SCHEMA my_schema TO my_schema_updaters; + + -- readers + + GRANT connect ON DATABASE my_database TO my_schema_readers; + GRANT usage ON SCHEMA my_schema TO my_schema_readers; + + GRANT SELECT ON ALL TABLES IN SCHEMA my_schema TO my_schema_readers; + GRANT EXECUTE ON ALL FUNCTIONS TO my_schema_readers; + + + -- create the default permissions for new objects + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT,INSERT,DELETE TO my_schema_updaters; + + -- For every table created by my_schema_database_designers, give access to my_schema_readers: + + ALTER DEFAULT PERMISSIONS FOR my_schema_database_designers IN my_schema + FOR TABLES GRANT SELECT TO my_schema_readers; + +.. note:: + * This process needs to be repeated by a user with ``SUPERUSER`` permissions each time a new schema is brought into this permissions management approach. + + * + By default, any new object created will not be accessible by our new ``my_schema_readers`` group. + Running a ``GRANT SELECT ...`` only affects objects that already exist in the schema or database. + + If you're getting a ``Missing the following permissions: SELECT on table 'database.public.tablename'`` error, make sure that + you've altered the default permissions with the ``ALTER DEFAULT PERMISSIONS`` statement. + +Creating new users in the departments +----------------------------------------- + +After the group roles have been created, you can now create user roles for each of your users. + +.. code-block:: postgres + + -- create the new database designer users + + CREATE ROLE ecodd; + GRANT LOGIN TO ecodd; + GRANT PASSWORD 'ecodds_secret_password' TO ecodd; + GRANT CONNECT ON DATABASE my_database TO ecodd; + GRANT my_schema_database_designers TO ecodd; + + CREATE ROLE ebachmann; + GRANT LOGIN TO ebachmann; + GRANT PASSWORD 'another_secret_password' TO ebachmann; + GRANT CONNECT ON DATABASE my_database TO ebachmann; + GRANT my_database_designers TO ebachmann; + + -- If a user already exists, we can assign that user directly to the group + + GRANT my_schema_updaters TO rhendricks; + + -- Create users in the readers group + + CREATE ROLE jbarker; + GRANT LOGIN TO jbarker; + GRANT PASSWORD 'action_jack' TO jbarker; + GRANT CONNECT ON DATABASE my_database TO jbarker; + GRANT my_schema_readers TO jbarker; + + CREATE ROLE lbream; + GRANT LOGIN TO lbream; + GRANT PASSWORD 'artichoke123' TO lbream; + GRANT CONNECT ON DATABASE my_database TO lbream; + GRANT my_schema_readers TO lbream; + + CREATE ROLE pgregory; + GRANT LOGIN TO pgregory; + GRANT PASSWORD 'c1ca6a' TO pgregory; + GRANT CONNECT ON DATABASE my_database TO pgregory; + GRANT my_schema_readers TO pgregory; + + -- Create users in the security officers group + + CREATE ROLE hoover; + GRANT LOGIN TO hoover; + GRANT PASSWORD 'mintchip' TO hoover; + GRANT CONNECT ON DATABASE my_database TO hoover; + GRANT my_schema_security_officers TO hoover; + + +.. todo: + create some example users + show that they have the right permission + try out the with admin option. we can't really do a security officer because + only superusers can create users and logins. see what can be done + need 1-2 users in each group, for at least 2 schemas/departments + this example will be very big just to show what this setup can do ... + example: a security officer for a department which will only have + read only access to a schema can only get that with admin option + access granted to them + +After this setup: + +* Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers +* Updaters will be able to insert and delete to existing and new tables +* Readers will be able to read from existing and new tables + +All this will happen without having to run any more ``GRANT`` statements. + +Any security officer will be able to add and remove users from these +groups. Creating and dropping login users themselves must be done by a +superuser. \ No newline at end of file diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst new file mode 100644 index 000000000..373b9a212 --- /dev/null +++ b/operational_guides/access_control_managing_roles.rst @@ -0,0 +1,124 @@ +.. _access_control_managing_roles: + +************** +Managing Roles +************** +Roles are used for both users and groups, and are global across all databases in the SQream cluster. For a ``ROLE`` to be used as a user, it requires a password and log-in and connect permissionss to the relevant databases. + +The Managing Roles section describes the following role-related operations: + +.. contents:: + :local: + :depth: 1 + +Creating New Roles (Users) +------------------------------ +A user role logging in to the database requires ``LOGIN`` permissions and as a password. + +The following is the syntax for creating a new role: + +.. code-block:: postgres + + CREATE ROLE ; + GRANT LOGIN to ; + GRANT PASSWORD <'new_password'> to ; + GRANT CONNECT ON DATABASE to ; + +The following is an example of creating a new role: + +.. code-block:: postgres + + CREATE ROLE new_role_name ; + GRANT LOGIN TO new_role_name; + GRANT PASSWORD 'my_password' to new_role_name; + GRANT CONNECT ON DATABASE master to new_role_name; + +A database role may have a number of permissions that define what tasks it can perform, which are assigned using the :ref:`grant` command. + +Dropping a User +------------------------------ +The following is the syntax for dropping a user: + +.. code-block:: postgres + + DROP ROLE ; + +The following is an example of dropping a user: + +.. code-block:: postgres + + DROP ROLE admin_role ; + +Altering a User Name +------------------------------ +The following is the syntax for altering a user name: + +.. code-block:: postgres + + ALTER ROLE RENAME TO ; + +The following is an example of altering a user name: + +.. code-block:: postgres + + ALTER ROLE admin_role RENAME TO copy_role ; + +Changing a User Password +------------------------------ +You can change a user role's password by granting the user a new password. + +The following is an example of changing a user password: + +.. code-block:: postgres + + GRANT PASSWORD <'new_password'> TO rhendricks; + +.. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. + +Altering Public Role Permissions +------------------------------ + +There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. + +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. + + +Altering Role Membership (Groups) +------------------------------ + +Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. + +To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. + +The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. + +.. code-block:: postgres + + CREATE ROLE my_group; + +Once the group role exists, you can add user roles (members) using the ``GRANT`` command. For example: + +.. code-block:: postgres + + -- Add my_user to this group + GRANT my_group TO my_user; + + +To manage object permissions like databases and tables, you would then grant permissions to the group-level role (see :ref:`the permissions table` below. + +All member roles then inherit the permissions from the group. For example: + +.. code-block:: postgres + + -- Grant all group users connect permissions + GRANT CONNECT ON DATABASE a_database TO my_group; + + -- Grant all permissions on tables in public schema + GRANT ALL ON all tables IN schema public TO my_group; + +Removing users and permissions can be done with the ``REVOKE`` command: + +.. code-block:: postgres + + -- remove my_other_user from this group + REVOKE my_group FROM my_other_user; \ No newline at end of file diff --git a/operational_guides/access_control_overview.rst b/operational_guides/access_control_overview.rst new file mode 100644 index 000000000..080797fec --- /dev/null +++ b/operational_guides/access_control_overview.rst @@ -0,0 +1,20 @@ +.. _access_control_overview: + +************** +Overview +************** +Access control refers to SQream's authentication and authorization operations, managed using a **Role-Based Access Control (RBAC)** system, such as ANSI SQL or other SQL products. SQream's default permissions system is similar to Postgres, but is more powerful. SQream's method lets administrators prepare the system to automatically provide objects with their required permissions. + +SQream users can log in from any worker, which verify their roles and permissions from the metadata server. Each statement issues commands as the role that you're currently logged into. Roles are defined at the cluster level, and are valid for all databases in the cluster. To bootstrap SQream, new installations require one ``SUPERUSER`` role, typically named ``sqream``. You can only create new roles by connecting as this role. + +Access control refers to the following basic concepts: + + * **Role** - A role can be a user, a group, or both. Roles can own database objects (such as tables) and can assign permissions on those objects to other roles. Roles can be members of other roles, meaning a user role can inherit permissions from its parent role. + + :: + + * **Authentication** - Verifies the identity of the role. User roles have usernames (or **role names**) and passwords. + + :: + + * **Authorization** - Checks that a role has permissions to perform a particular operation, such as the :ref:`grant` command. \ No newline at end of file diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst new file mode 100644 index 000000000..10a4f697f --- /dev/null +++ b/operational_guides/access_control_password_policy.rst @@ -0,0 +1,42 @@ +.. _access_control_password_policy: + +************** +Password Policy +************** +As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: + +* At least eight characters long. + + :: + +* Mandatory upper and lowercase letters. + + :: + +* At least one numeric character. + + :: + +* May not include a username. + + :: + +* Must include at least one special character, such as **?**, **!**, **$**, etc. + +You can create a password through the Studio graphic interface or through the CLI, as in the following example command: + +.. code-block:: console + + CREATE ROLE user_a ; + GRANT LOGIN to user_a ; + GRANT PASSWORD 'BBAu47?fqPL' to user_a ; + +Creating a password that does not comply with the above requirements generates an error message with a request to modify it. + +Unsuccessfully attempting to log in three times displays the following message: + +.. code-block:: console + + The user is locked. please contact your system administrator to reset the password and regain access functionality. + +For more information, see :ref:`login_max_retries`. diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst new file mode 100644 index 000000000..5afc23009 --- /dev/null +++ b/operational_guides/access_control_permissions.rst @@ -0,0 +1,218 @@ +.. _access_control_permissions: + +************** +Permissions +************** + +The following table displays the access control permissions: + ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Permission** | **Description** | ++====================+=========================================================================================================================+ +| **Object/Layer: All Databases** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``LOGIN`` | use role to log into the system (the role also needs connect permission on the database it is connecting to) | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``PASSWORD`` | the password used for logging into the system | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | no permission restrictions on any activity | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Database** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | no permission restrictions on any activity within that database (this does not include modifying roles or permissions) | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CONNECT`` | connect to the database | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | create schemas in the database | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE FUNCTION``| create and drop functions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Schema** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | allows additional permissions within the schema | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | create tables in the schema | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Table** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | :ref:`select` from the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``INSERT`` | :ref:`insert` into the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``UPDATE`` | UPDATE the value of certain columns in existing rows without creating a table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | drop and alter on the table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | all the table permissions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Function** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``EXECUTE`` | use the function | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | drop and alter on the function | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | all function permissions | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ + + + + +GRANT +----- + +:ref:`grant` gives permissions to a role. + +.. code-block:: postgres + + -- Grant permissions at the instance/ storage cluster level: + GRANT + + { SUPERUSER + | LOGIN + | PASSWORD '' + } + TO [, ...] + + -- Grant permissions at the database level: + GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} + + ON DATABASE [, ...] + TO [, ...] + + -- Grant permissions at the schema level: + GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ + PERMISSIONS ]} + ON SCHEMA [, ...] + TO [, ...] + + -- Grant permissions at the object level: + GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} + ON { TABLE [, ...] | ALL TABLES IN SCHEMA [, ...]} + TO [, ...] + + -- Grant execute function permission: + GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name + TO role; + + -- Allows role2 to use permissions granted to role1 + GRANT [, ...] + TO + + -- Also allows the role2 to grant role1 to other roles: + GRANT [, ...] + TO + WITH ADMIN OPTION + +``GRANT`` examples: + +.. code-block:: postgres + + GRANT LOGIN,superuser TO admin; + + GRANT CREATE FUNCTION ON database master TO admin; + + GRANT SELECT ON TABLE admin.table1 TO userA; + + GRANT EXECUTE ON FUNCTION my_function TO userA; + + GRANT ALL ON FUNCTION my_function TO userA; + + GRANT DDL ON admin.main_table TO userB; + + GRANT ALL ON all tables IN schema public TO userB; + + GRANT admin TO userC; + + GRANT superuser ON schema demo TO userA + + GRANT admin_role TO userB; + +REVOKE +------ + +:ref:`revoke` removes permissions from a role. + +.. code-block:: postgres + + -- Revoke permissions at the instance/ storage cluster level: + REVOKE + { SUPERUSER + | LOGIN + | PASSWORD + } + FROM [, ...] + + -- Revoke permissions at the database level: + REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} + ON DATABASE [, ...] + FROM [, ...] + + -- Revoke permissions at the schema level: + REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} + ON SCHEMA [, ...] + FROM [, ...] + + -- Revoke permissions at the object level: + REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } + ON { [ TABLE ] [, ...] | ALL TABLES IN SCHEMA + + [, ...] } + FROM [, ...] + + -- Removes access to permissions in role1 by role 2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + -- Removes permissions to grant role1 to additional roles from role2 + REVOKE [, ...] FROM [, ...] WITH ADMIN OPTION + + +Examples: + +.. code-block:: postgres + + REVOKE superuser on schema demo from userA; + + REVOKE delete on admin.table1 from userB; + + REVOKE login from role_test; + + REVOKE CREATE FUNCTION FROM admin; + +Default permissions +------------------- + +The default permissions system (See :ref:`alter_default_permissions`) +can be used to automatically grant permissions to newly +created objects (See the departmental example below for one way it can be used). + +A default permissions rule looks for a schema being created, or a +table (possibly by schema), and is table to grant any permission to +that object to any role. This happens when the create table or create +schema statement is run. + + +.. code-block:: postgres + + + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { TABLES | SCHEMAS } + { grant_clause | DROP grant_clause} + TO ROLE { role_name | public }; + + grant_clause ::= + GRANT + { CREATE FUNCTION + | SUPERUSER + | CONNECT + | CREATE + | USAGE + | SELECT + | INSERT + | DELETE + | DDL + | EXECUTE + | ALL + } \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst new file mode 100644 index 000000000..8e90524ef --- /dev/null +++ b/releases/2022.1.1.rst @@ -0,0 +1,115 @@ +.. _2022.1.1: + +************************** +Release Notes 2022.1.1 +************************** +The 2022.1.1 patch release notes were released on 7/28/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The **Version Content** section is not relevant to the 2022.1.1 patch release notes. + +New Features +---------- +The 2022.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Automatically Identifying Schemas when Mapping Foreign Tables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +SQream can now automatically identify the corresponding schema, avoiding complex error-prone DDL operations, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. In addition, this feature improves user experience by letting you quickly load foreign tables without specifying hundred of columns. + +For more information, see :ref:`automatic_schema_identification`. + +Password Policy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +SQream has implemented a strong password policy required when accessing the CLI or Studio. + +For more information, see :ref:`access_control_password_policy`. + +Resolved Issues +--------- +The following table lists the issues that were resolved in the 2022.1.1 patch release: + ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+=======================================================================================================================+ +| SQ-6419 | An internal compiler error occurred when casting a numeric literal in an aggregation function. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10873 | Inserting 100K bytes into a ``TEXT`` column resulted in an unclear error message. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10886 | An internal compiler error occurred during the compilation process. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10892 | The error message displayed when ``UPDATE`` is run on a foreign table was corrected. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10955 | Unneeded reads occured when filtering by date. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ + +Known Issues +--------- +The **Known Issues** section is not relevant to Version 2022.1.1. + +Operations and Configuration Changes +-------- +The **Operations and Configuration Changes** section is not relevant to the 2022.1.1 patch release notes. + +Naming Changes +------- +The **Naming Changes** section is not relevant to the 2022.1.1 patch release notes. + +Deprecated Features +------- +The **Deprecated Features** section is not relevant to the 2022.1.1 patch release. + +End of Support +------- +The **End of Support** section is not relevant to the 2022.1.1 patch release. + +Upgrading to v2022.1.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst new file mode 100644 index 000000000..628b372aa --- /dev/null +++ b/releases/2022.1_index.rst @@ -0,0 +1,17 @@ +.. _2022.1_index: + +************************** +Release Notes 2022.1 +************************** +The 2022.1 Release Notes describe the following releases: + +.. contents:: + :local: + :depth: 1 + +.. toctree:: + :maxdepth: 1 + :glob: + + 2022.1.1 + 2022.1 \ No newline at end of file From 16eab5d2b00fbdb1ffe8b66329bca9efaa64650b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 14:18:06 +0300 Subject: [PATCH 0162/1892] Added 2022.1_index to main RN index --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index b1d065a9e..84024586e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1 + 2022.1_index 2021.2_index 2021.1_index 2020.3_index From 7d1d837fe0616a5dbc24cbb4c9eb12e3853a45b6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 14:24:05 +0300 Subject: [PATCH 0163/1892] Added Auto Schema Identification --- .../automatic_schema_identification.rst | 46 +++++++++++++++++++ feature_guides/index.rst | 1 + 2 files changed, 47 insertions(+) create mode 100644 feature_guides/automatic_schema_identification.rst diff --git a/feature_guides/automatic_schema_identification.rst b/feature_guides/automatic_schema_identification.rst new file mode 100644 index 000000000..e2089143e --- /dev/null +++ b/feature_guides/automatic_schema_identification.rst @@ -0,0 +1,46 @@ +.. _automatic_schema_identification: + +*********************** +Automatic Schema Identification +*********************** +The **Automatic Schema Identification** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +---------- +SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. + +Usage Notes +---------- +The automatic schema identification feature supports Parquet, ORC, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. + +Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. + +.. note:: When using this feature, SQream assumes that all files in the path use the same schema. + +Syntax +---------- +The following is the syntax for using the automatic schema identification feature: + +.. code-block:: console + + CREATE FOREIGN TABLE table_name + [FOREIGN DATA] WRAPPER fdw_name + [OPTIONS (...)]; + +Example +---------- +The following is an example of using the automatic schema identification feature: + +.. code-block:: console + + create foreign table parquet_table + wrapper parquet_fdw + options (location = '/tmp/file.parquet'); + +Permissions +---------- +The Automatic Schema Identification feature requires **Read** permissions. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index d70ceb705..d1a0c7fc3 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,6 +12,7 @@ This section describes the following features: :titlesonly: query_healer + automatic_schema_identification data_encryption compression python_functions From aa11873d48cbaecb9eeaa41e4a39a14d089f3bff Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 15:23:25 +0300 Subject: [PATCH 0164/1892] Updated --- .../automatic_schema_identification.rst | 46 ------------------- feature_guides/index.rst | 1 - releases/2022.1.1.rst | 6 --- 3 files changed, 53 deletions(-) delete mode 100644 feature_guides/automatic_schema_identification.rst diff --git a/feature_guides/automatic_schema_identification.rst b/feature_guides/automatic_schema_identification.rst deleted file mode 100644 index e2089143e..000000000 --- a/feature_guides/automatic_schema_identification.rst +++ /dev/null @@ -1,46 +0,0 @@ -.. _automatic_schema_identification: - -*********************** -Automatic Schema Identification -*********************** -The **Automatic Schema Identification** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview ----------- -SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. - -Usage Notes ----------- -The automatic schema identification feature supports Parquet, ORC, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. - -Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. - -.. note:: When using this feature, SQream assumes that all files in the path use the same schema. - -Syntax ----------- -The following is the syntax for using the automatic schema identification feature: - -.. code-block:: console - - CREATE FOREIGN TABLE table_name - [FOREIGN DATA] WRAPPER fdw_name - [OPTIONS (...)]; - -Example ----------- -The following is an example of using the automatic schema identification feature: - -.. code-block:: console - - create foreign table parquet_table - wrapper parquet_fdw - options (location = '/tmp/file.parquet'); - -Permissions ----------- -The Automatic Schema Identification feature requires **Read** permissions. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index d1a0c7fc3..d70ceb705 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,7 +12,6 @@ This section describes the following features: :titlesonly: query_healer - automatic_schema_identification data_encryption compression python_functions diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 8e90524ef..08843f380 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -21,12 +21,6 @@ The 2022.1 Release Notes include the following new features: :local: :depth: 1 -Automatically Identifying Schemas when Mapping Foreign Tables -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -SQream can now automatically identify the corresponding schema, avoiding complex error-prone DDL operations, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. In addition, this feature improves user experience by letting you quickly load foreign tables without specifying hundred of columns. - -For more information, see :ref:`automatic_schema_identification`. - Password Policy ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SQream has implemented a strong password policy required when accessing the CLI or Studio. From 4b0631f94889c9c1ef7c30c274ebacb372b8d131 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 15:34:57 +0300 Subject: [PATCH 0165/1892] REverted --- releases/2022.1.1.rst | 109 -------------------------------------- releases/2022.1_index.rst | 1 - releases/index.rst | 2 +- 3 files changed, 1 insertion(+), 111 deletions(-) delete mode 100644 releases/2022.1.1.rst diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst deleted file mode 100644 index 08843f380..000000000 --- a/releases/2022.1.1.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _2022.1.1: - -************************** -Release Notes 2022.1.1 -************************** -The 2022.1.1 patch release notes were released on 7/28/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------- -The **Version Content** section is not relevant to the 2022.1.1 patch release notes. - -New Features ----------- -The 2022.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Password Policy -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -SQream has implemented a strong password policy required when accessing the CLI or Studio. - -For more information, see :ref:`access_control_password_policy`. - -Resolved Issues ---------- -The following table lists the issues that were resolved in the 2022.1.1 patch release: - -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+=======================================================================================================================+ -| SQ-6419 | An internal compiler error occurred when casting a numeric literal in an aggregation function. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10873 | Inserting 100K bytes into a ``TEXT`` column resulted in an unclear error message. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10886 | An internal compiler error occurred during the compilation process. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10892 | The error message displayed when ``UPDATE`` is run on a foreign table was corrected. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10955 | Unneeded reads occured when filtering by date. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ - -Known Issues ---------- -The **Known Issues** section is not relevant to Version 2022.1.1. - -Operations and Configuration Changes --------- -The **Operations and Configuration Changes** section is not relevant to the 2022.1.1 patch release notes. - -Naming Changes -------- -The **Naming Changes** section is not relevant to the 2022.1.1 patch release notes. - -Deprecated Features -------- -The **Deprecated Features** section is not relevant to the 2022.1.1 patch release. - -End of Support -------- -The **End of Support** section is not relevant to the 2022.1.1 patch release. - -Upgrading to v2022.1.1 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 628b372aa..9c7b2b211 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,5 +13,4 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: - 2022.1.1 2022.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 84024586e..b1d065a9e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1_index + 2022.1 2021.2_index 2021.1_index 2020.3_index From ab5f5c6a3f3bf913e9f19cce2a6c6387e403e2d1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 15:58:22 +0300 Subject: [PATCH 0166/1892] Updated --- releases/2022.1_index.rst | 1 + releases/index.rst | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 9c7b2b211..628b372aa 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,4 +13,5 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.1 2022.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index b1d065a9e..84024586e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1 + 2022.1_index 2021.2_index 2021.1_index 2020.3_index From 98028f90d4a7d65a6df75d0a0bbcf3633c17df57 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 16:09:45 +0300 Subject: [PATCH 0167/1892] Create 2022.1.1.rst --- releases/2022.1.1.rst | 109 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 releases/2022.1.1.rst diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst new file mode 100644 index 000000000..08843f380 --- /dev/null +++ b/releases/2022.1.1.rst @@ -0,0 +1,109 @@ +.. _2022.1.1: + +************************** +Release Notes 2022.1.1 +************************** +The 2022.1.1 patch release notes were released on 7/28/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The **Version Content** section is not relevant to the 2022.1.1 patch release notes. + +New Features +---------- +The 2022.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Password Policy +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +SQream has implemented a strong password policy required when accessing the CLI or Studio. + +For more information, see :ref:`access_control_password_policy`. + +Resolved Issues +--------- +The following table lists the issues that were resolved in the 2022.1.1 patch release: + ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+=======================================================================================================================+ +| SQ-6419 | An internal compiler error occurred when casting a numeric literal in an aggregation function. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10873 | Inserting 100K bytes into a ``TEXT`` column resulted in an unclear error message. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10886 | An internal compiler error occurred during the compilation process. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10892 | The error message displayed when ``UPDATE`` is run on a foreign table was corrected. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ +| SQ-10955 | Unneeded reads occured when filtering by date. | ++-------------+-----------------------------------------------------------------------------------------------------------------------+ + +Known Issues +--------- +The **Known Issues** section is not relevant to Version 2022.1.1. + +Operations and Configuration Changes +-------- +The **Operations and Configuration Changes** section is not relevant to the 2022.1.1 patch release notes. + +Naming Changes +------- +The **Naming Changes** section is not relevant to the 2022.1.1 patch release notes. + +Deprecated Features +------- +The **Deprecated Features** section is not relevant to the 2022.1.1 patch release. + +End of Support +------- +The **End of Support** section is not relevant to the 2022.1.1 patch release. + +Upgrading to v2022.1.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.1 \ No newline at end of file From 41d91c9eb25c7627eae74b8c26abbbbc95e61970 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:18:51 +0300 Subject: [PATCH 0168/1892] Updated --- releases/2022.1.rst | 137 -------------------------------------- releases/2022.1_index.rst | 1 - releases/index.rst | 2 +- 3 files changed, 1 insertion(+), 139 deletions(-) delete mode 100644 releases/2022.1.rst diff --git a/releases/2022.1.rst b/releases/2022.1.rst deleted file mode 100644 index 3c5ae24e6..000000000 --- a/releases/2022.1.rst +++ /dev/null @@ -1,137 +0,0 @@ -.. _2022.1: - -************************** -Release Notes 2022.1 -************************** -The 2022.1 release notes were released on 7/19/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------- -The 2022.1 Release Notes describes the following: - -* Enhanced security features. -* New data manipulation command. -* Additional data ingestion format. - -New Features ----------- -The 2022.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Data Encryption -************ -SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. - -Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. - -For more information, see `Data Encryption `_. - -Update Feature -************ -SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. - -For more information, see `UPDATE `_. - -Avro Ingestion -************ -SQream now supports ingesting data from Avro files. - -For more information, see `Inserting Data from Avro `_. - -Known Issues ---------- -The following table lists the known issues for Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10629 | Inserting data into a table significantly slowed down running queries. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10659 | Using a comment generated a compile error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Resolved Issues ---------- -The following table lists the issues that were resolved in Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes --------- -No relevant operations and configuration changes were made. - -Naming Changes -------- -No relevant naming changes were made. - -Deprecated Features -------- -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. - -End of Support -------- -The End of Support section is not relevant to Version 2022.1. - -Upgrading to v2022.1 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1 diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 628b372aa..9c7b2b211 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,5 +13,4 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: - 2022.1.1 2022.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 84024586e..b1d065a9e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1_index + 2022.1 2021.2_index 2021.1_index 2020.3_index From e30d16380d31cc4ae9184406691e9d43881b3143 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:30:29 +0300 Subject: [PATCH 0169/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index b1d065a9e..84024586e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1 + 2022.1_index 2021.2_index 2021.1_index 2020.3_index From 0ba6ce89dd90cee3feedab870658b8a89dae46d4 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:32:24 +0300 Subject: [PATCH 0170/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index 84024586e..b1d065a9e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1_index + 2022.1 2021.2_index 2021.1_index 2020.3_index From 534c19e397a4ee85e1b50b6d7e3da3e4b9355a33 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:33:06 +0300 Subject: [PATCH 0171/1892] Update index.rst --- releases/index.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index b1d065a9e..b3cfb3900 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,8 +12,6 @@ Release Notes * - Version - Release Date - * - :ref:`2022.1` - - July 19, 2022 * - :ref:`2021.2` - September 13, 2021 * - :ref:`2021.1` @@ -32,7 +30,6 @@ Release Notes :glob: :hidden: - 2022.1 2021.2_index 2021.1_index 2020.3_index From 3f84a22424552289d179fd5024d945d23f2617b3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:36:17 +0300 Subject: [PATCH 0172/1892] Update index.rst --- releases/index.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/releases/index.rst b/releases/index.rst index b3cfb3900..b1d065a9e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,6 +12,8 @@ Release Notes * - Version - Release Date + * - :ref:`2022.1` + - July 19, 2022 * - :ref:`2021.2` - September 13, 2021 * - :ref:`2021.1` @@ -30,6 +32,7 @@ Release Notes :glob: :hidden: + 2022.1 2021.2_index 2021.1_index 2020.3_index From b649c40d4ea124d95ded76c3c151142c161e424a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 28 Jul 2022 18:40:49 +0300 Subject: [PATCH 0173/1892] Create 2022.1.rst --- releases/2022.1.rst | 137 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 releases/2022.1.rst diff --git a/releases/2022.1.rst b/releases/2022.1.rst new file mode 100644 index 000000000..cdd6d98c5 --- /dev/null +++ b/releases/2022.1.rst @@ -0,0 +1,137 @@ +.. _2022.1: + +************************** +Release Notes 2022.1 +************************** +The 2022.1 release notes were released on 7/19/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1 Release Notes describes the following: + +* Enhanced security features. +* New data manipulation command. +* Additional data ingestion format. + +New Features +---------- +The 2022.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Data Encryption +************ +SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. + +Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. + +For more information, see `Data Encryption `_. + +Update Feature +************ +SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. + +For more information, see `UPDATE `_. + +Avro Ingestion +************ +SQream now supports ingesting data from Avro files. + +For more information, see `Inserting Data from Avro `_. + +Known Issues +--------- +The following table lists the known issues for Version 2022.1: + ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10629 | Inserting data into a table significantly slowed down running queries. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10659 | Using a comment generated a compile error. | ++-------------+-------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1: + ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +No relevant operations and configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. + +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1. + +Upgrading to v2022.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 From 174f17de04347f32e5a8e6007e67be838b4580ff Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 10:12:57 +0300 Subject: [PATCH 0174/1892] Removed Healer Toggle (2022.1.1) --- configuration_guides/admin_worker_flags.rst | 1 - .../healer_max_inactivity_hours.rst | 4 +- configuration_guides/is_healer_on.rst | 14 --- feature_guides/query_healer.rst | 18 +-- releases/2022.1.1.rst | 109 ------------------ 5 files changed, 3 insertions(+), 143 deletions(-) delete mode 100644 configuration_guides/is_healer_on.rst delete mode 100644 releases/2022.1.1.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 453c66af8..6b7a74b9e 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -9,6 +9,5 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ -* `Enabling the Query Healer `_ * `Configuring the Query Healer `_ * `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst index 56ddb78fc..1ff8ddaa6 100644 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -9,6 +9,4 @@ The following describes the ``healerMaxInactivityHours`` flag: * **Data type** - size_t * **Default value** - ``5`` -* **Allowed values** - 1-4000000000 - -For related flags, see :ref:`is_healer_on`. \ No newline at end of file +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst deleted file mode 100644 index 8b90654ec..000000000 --- a/configuration_guides/is_healer_on.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _is_healer_on: - -************************* -Enabling the Query Healer -************************* -The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. - -The following describes the ``is_healer_on`` flag: - -* **Data type** - boolean -* **Default value** - ``true`` -* **Allowed values** - ``true``, ``false`` - -For related flags, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index cb50549b8..380b1558f 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -21,20 +21,6 @@ The following is an example of a log record for a query stuck in the query detec Configuring the Healer ------------------ -The following flags are required to configure the Query Healer: +The **healerMaxInactivityHours** is required define the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. - * **isHealerOn** - Enables the Query Healer. - - :: - - * **healerMaxInactivityHours** - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. - -The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. - -For more information, see the following Administration Worker flags: - - * :ref:`is_healer_on` - - :: - - * :ref:`healer_max_inactivity_hours` \ No newline at end of file +For more information, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst deleted file mode 100644 index 08843f380..000000000 --- a/releases/2022.1.1.rst +++ /dev/null @@ -1,109 +0,0 @@ -.. _2022.1.1: - -************************** -Release Notes 2022.1.1 -************************** -The 2022.1.1 patch release notes were released on 7/28/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------- -The **Version Content** section is not relevant to the 2022.1.1 patch release notes. - -New Features ----------- -The 2022.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Password Policy -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -SQream has implemented a strong password policy required when accessing the CLI or Studio. - -For more information, see :ref:`access_control_password_policy`. - -Resolved Issues ---------- -The following table lists the issues that were resolved in the 2022.1.1 patch release: - -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+=======================================================================================================================+ -| SQ-6419 | An internal compiler error occurred when casting a numeric literal in an aggregation function. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10873 | Inserting 100K bytes into a ``TEXT`` column resulted in an unclear error message. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10886 | An internal compiler error occurred during the compilation process. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10892 | The error message displayed when ``UPDATE`` is run on a foreign table was corrected. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ -| SQ-10955 | Unneeded reads occured when filtering by date. | -+-------------+-----------------------------------------------------------------------------------------------------------------------+ - -Known Issues ---------- -The **Known Issues** section is not relevant to Version 2022.1.1. - -Operations and Configuration Changes --------- -The **Operations and Configuration Changes** section is not relevant to the 2022.1.1 patch release notes. - -Naming Changes -------- -The **Naming Changes** section is not relevant to the 2022.1.1 patch release notes. - -Deprecated Features -------- -The **Deprecated Features** section is not relevant to the 2022.1.1 patch release. - -End of Support -------- -The **End of Support** section is not relevant to the 2022.1.1 patch release. - -Upgrading to v2022.1.1 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in **Step 7** of the Upgrading SQream Version procedure. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file From 5b4e90d3f75caea97e4036fd38c3a93c2350ef52 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 10:23:34 +0300 Subject: [PATCH 0175/1892] Removed reference to Healer configuration --- configuration_guides/admin_worker_flags.rst | 1 - configuration_guides/healer_max_inactivity_hours.rst | 12 ------------ feature_guides/query_healer.rst | 4 +--- 3 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 configuration_guides/healer_max_inactivity_hours.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 6b7a74b9e..6be021d70 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -9,5 +9,4 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ -* `Configuring the Query Healer `_ * `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst deleted file mode 100644 index 1ff8ddaa6..000000000 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _healer_max_inactivity_hours: - -************************* -Configuring the Query Healer -************************* -The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. - -The following describes the ``healerMaxInactivityHours`` flag: - -* **Data type** - size_t -* **Default value** - ``5`` -* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 380b1558f..667a91ed8 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -21,6 +21,4 @@ The following is an example of a log record for a query stuck in the query detec Configuring the Healer ------------------ -The **healerMaxInactivityHours** is required define the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. - -For more information, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file +The **healerMaxInactivityHours** is required define the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. \ No newline at end of file From 9de62ba18c3006361b0c3433828fd767ff5a51e1 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 10:35:01 +0300 Subject: [PATCH 0176/1892] Update 2021.2.1.24.rst --- releases/2021.2.1.24.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 125092f0e..fe21d40c0 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -25,7 +25,7 @@ Query Healer ************ The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. -For more information, see :ref:`query_healer`. +For more information, see `Query Healer `_. Known Issues --------- From 93000b924307a192a334e7cdbec8b458e8604e5e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 13:27:15 +0300 Subject: [PATCH 0177/1892] Testing links --- releases/2021.1.2.rst | 6 +- releases/2021.2.1.24.rst | 2 +- releases/2021.2.1.rst | 4 +- releases/2021.2.rst | 4 +- releases/2022.1.rst | 10 +- sqream_studio_5.4.3/Version_5.3.3.txt | 898 ++++++++++++++++++++++++++ 6 files changed, 911 insertions(+), 13 deletions(-) create mode 100644 sqream_studio_5.4.3/Version_5.3.3.txt diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index 448b047df..5ccd878d8 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -40,17 +40,17 @@ String Literals Containing ASCII Characters Interepreted as TEXT ************ SQream now interprets all string literals, including those containing ASCII characters, as ``text``. -For more information, see `String Types `_. +For more information, see `String Types `_. Decimal Literals Interpreted as Numeric Columns ************ SQream now interprets literals containing decimal points as ``numeric`` instead of as ``double``. -For more information, see `Data Types `_. +For more information, see `Data Types `_. Roles Area Added to Studio Version 5.3.3 **************** -The **Roles** area has been added to `Studio version 5.3.3 `_. From the Roles area users can create and assign roles and manage user permissions. +The **Roles** area has been added to `Studio version 5.3.3 `_. From the Roles area users can create and assign roles and manage user permissions. Resolved Issues ------------- diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index fe21d40c0..f92cfda00 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -25,7 +25,7 @@ Query Healer ************ The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. -For more information, see `Query Healer `_. +For more information, see `Query Healer `_. Known Issues --------- diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index 3afba3093..c7e1dbada 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -21,7 +21,7 @@ CREATE TABLE ************ SQream now supports duplicating the column structure of an existing table using the ``LIKE`` clause. -For more information, see `Duplicating the Column Structure of an Existing Table `_. +For more information, see `Duplicating the Column Structure of an Existing Table `_. PERCENTILE FUNCTIONS ************ @@ -41,7 +41,7 @@ Delete Optimization ************ The ``DELETE`` statement can now delete values that contain multi-table conditions. -For more information, see `Deleting Values that Contain Multi-Table Conditions `_. +For more information, see `Deleting Values that Contain Multi-Table Conditions `_. For more information, see :ref:`regexp_replace`. diff --git a/releases/2021.2.rst b/releases/2021.2.rst index 1bd6c6223..cce1675dc 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -33,8 +33,8 @@ SQream now uses a new configuration system based on centralized configuration ac For more information, see the following: -* `Configuration `_ - describes how to configure your instance of SQream from a centralized location. -* `SQream Studio 5.4.2 `_ - configure your instance of SQream from Studio. +* `Configuration `_ - describes how to configure your instance of SQream from a centralized location. +* `SQream Studio 5.4.2 `_ - configure your instance of SQream from Studio. Qualifying Schemas Without Providing an Alias ************ diff --git a/releases/2022.1.rst b/releases/2022.1.rst index cdd6d98c5..085108a43 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -37,13 +37,13 @@ Update Feature ************ SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. -For more information, see `UPDATE `_. +For more information, see `UPDATE `_. Avro Ingestion ************ SQream now supports ingesting data from Avro files. -For more information, see `Inserting Data from Avro `_. +For more information, see `Inserting Data from Avro `_. Known Issues --------- @@ -87,7 +87,7 @@ Deprecated Features ------- In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. -If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. End of Support ------- @@ -127,11 +127,11 @@ Upgrading to v2022.1 $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. .. toctree:: :maxdepth: 2 :glob: :hidden: - 2022.1 + 2022.1 \ No newline at end of file diff --git a/sqream_studio_5.4.3/Version_5.3.3.txt b/sqream_studio_5.4.3/Version_5.3.3.txt new file mode 100644 index 000000000..458302aad --- /dev/null +++ b/sqream_studio_5.4.3/Version_5.3.3.txt @@ -0,0 +1,898 @@ +.. _acceleration_studio_version_5.3.3: + +**************************** +SQream Acceleration Studio 5.3.3 +**************************** + +The SQream Studio is a web-based client for use with SQream DB. The Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream DB clusters. + + +.. contents:: This page describes the following: + :depth: 3 + +Getting Started +================== + +.. _setting_up_and_starting_studio: + + +Setting Up and Starting Studio +---------------- + +Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. + + + + + + + +Logging In to Studio +--------------- +**To log in to SQream Studio:** + +1. Open a browser to the host on **port 8080**. + + For example, if your machine IP address is ``192.168.0.100``, insert the IP address into the browser as shown below: + + .. code-block:: console + + $ http://192.168.0.100:8080 + +2. Fill in your SQream DB login credentials. These are the same credentials used for `SQream CLI Reference `_ or JDBC. + + When you sign in, the License Warning is displayed. + +Navigating Studio's Main Features +------------- +When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. + +From here you can navigate between the main areas of the Studio: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Dashboard` + - Only users with **superuser** permissions have access to the Dashboard. + * - :ref:`Editor` + - All users have access to the Editor and to databases that they have permissions for. + * - :ref:`Logs` + - Only users with the **superuser** permissions have access to the logs. + * - :ref:`Roles` + - Lets you create users and manage user permissions. + +By clicking the user icon, you can also use it for logging out and viewing the following: + +* User information +* Connection type +* SQream version +* SQream Studio version +* Data size limitations +* Log out + + + +.. _back_to_dashboard: + +.. _studio_dashboard: + +Monitoring Workers and Services from the Dashboard +============================== +The **Dashboard** is used for the following: + +* Monitoring cluster storage and system health. +* Viewing, monitoring, and adding defined service queues. +* Viewing and managing worker status and add workers. + +You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. + +The following is a brief description of the Dashboard panels: + +.. list-table:: + :widths: 10 25 65 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Data Storage panel` + - Used to monitor cluster storage. + * - 2 + - :ref:`Services panel` + - Used for viewing and monitoring the defined `service queues `_. + * - 3 + - :ref:`Workers panel` + - Monitors system health and shows each Sqreamd worker running in the cluster. + * - 4 + - :ref:`License information` + - Shows the remaining amount of days left on your license. + + +.. _data_storage_panel: + +Displaying System Disk Usage from the Data Storage Panel +----------------------- +The **Data Storage** area displays your system's total disk usage (percentage) and data storage (donut graph). + +Your data storage is shows as the following four components: + +* **Data** – Storage occupied by databases in SQream DB. +* **Free** – Free storage space. +* **Deleted** – Storage that is temporarily occupied, but has not been reclaimed. For more information, see `Deleting Data `_. The **deleted** value is estimated and may not be accurate. +* **Other** – Storage used by other applications. On a dedicated SQream DB cluster this should be near zero. + +.. _administration_storage_database: + +You can show more information by clicking the expand arrow on the Data Storage panel. + +.. image:: /_static/images/studio_dashboard_expand_data_storage_5.3.0.png + +The expanded Data Storage panel can be used to drill down into each database's storage footprint, and displays a breakdown of how much storage each database in the cluster uses. + +The database information is displayed in a table and shows the following: + +* **Database name** - the name of the database. +* **Raw Size** – the estimated size of (uncompressed) raw data in the database. +* **Storage Size** – the physical size of the compressed data. +* **Ratio** – the effective compression ratio +* **Deleted Data** – Storage that is temporarily occupied, but has not been reclaimed. + +Below the table, an interactive line graph displays the database storage trends. By default, the line graph displays the total storage for all databases. You can show a particular database's graph by clicking it in the table. You can also change the line graph's timespan by selecting one from the timespan dropdown menu. + +.. image:: /_static/images/studio_dashboard_expand_data_storage_3_5.3.0.png + +:ref:`Back to Dashboard` + +.. _services_panel: + +Subscribing to Workers from the Services Panel +-------------------------- +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. + +.. image:: /_static/images/studio_dashboard_services_panel_5.3.0.png + +The Dashboard includes the four panes shown below: + +.. image:: /_static/images/studio_dashboard_service_queue_5.3.0.png + +The following is a brief description of each pane: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - No. + - Description + * - 1 + - Adds a worker to the selected service. + * - 2 + - Shows the service name. + * - 3 + - Shows a trend graph of queued statements loaded over time. + * - 4 + - Adds a service. + * - 5 + - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). + +Adding A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a service by clicking **+ Add** and defining the service name. + +.. note:: If you do not associate a worker with the new service, it will not be created. + +You can manage workers from the **Workers** panel. For more information on managing workers, see :ref:`Workers`. + +:ref:`Back to Dashboard` + +.. _workers_panel: + +Managing Workers from the Workers Panel +------------ +From the **Workers** panel you can do the following: + +* :ref:`View workers ` +* :ref:`Add a worker to a service` +* :ref:`View a worker's active query information` +* :ref:`View a worker's execution plan` + +.. _view_workers: + +Viewing Workers +^^^^^^^^ +The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. + +From the **Scale** dropdown menu you can set the time scale of the displayed information +You can hover over segments in the status bar to see the date and time corresponding to each activity type: + +* **Idle** – the worker is idle and available for statements. +* **Compiling** – the worker is compiling a statement and is preparing for execution. +* **Executing** – the worker is executing a statement after compilation. +* **Stopped** – the worker was stopped (either deliberately or due to an error). +* **Waiting** – the worker was waiting on an object locked by another worker. + +.. _add_worker_to_service: + +Adding A Worker to A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a worker to a service by clicking the **add** button. + +.. image:: /_static/images/studio_dashboard_add_worker_to_service_5.3.0.png + +Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. + + +.. _view_worker_query_information: + +Viewing A Worker's Active Query Information +^^^^^^^^^^^^^^^^^^^^^ +You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. + + +Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. + +Viewing A Worker's Host Utilization +^^^^^^^^^^^^^^^^^^^^^ + +While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. + +.. image:: /_static/images/studio_dashboard_show_cpu_gpu_graph_5.3.0.png + +The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. + +Error notifications related to statements are displayed as shown in the figure below, and you can hover over them for more information about the error. + +.. image:: /_static/images/studio_dashboard_notification_error_5.3.0.png + +.. _view_worker_execution_plan: + +Viewing a Worker's Execution Plan +^^^^^^^^^^^^^^^^^^^^^ + +Clicking the ellipsis in a service shows the following additional options: + +* **Stop Query** - stops the query. +* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. + +For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Managing Worker Status +^^^^^^^^^^^^^^^^^^^^^ + +In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. + +.. image:: /_static/images/stop_restart_worker.png + +Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. + + + + +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle + +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle + +:ref:`Back to Dashboard` + + + +.. _license_information: + +License Information +---------------------- +The license information is a counter showing the amount of time in days remaining on the license. + +:ref:`Back to Dashboard` + + +.. _studio_editor: + +.. _editor_top: + +Executing Statements and Running Queries from the Editor +================= +The **Editor** is used for the following: + +* Selecting an active database and executing queries. +* Performing statement-related operations and showing metadata. +* Executing pre-defined queries. +* Writing queries and statements and viewing query results. + +The following is a brief description of the Editor panels: + + +.. list-table:: + :widths: 10 34 56 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Toolbar` + - Used to select the active database you want to work on, limit the number of rows, save query, etc. + * - 2 + - :ref:`Database Tree and System Queries panel` + - Shows a heirarchy tree of databases, views, tables, and columns + * - 3 + - :ref:`Statement panel` + - Used for writing queries and statements + * - 4 + - :ref:`Results panel` + - Shows query results and execution information. + + +.. _studio_editor_db_tree: + +.. _top: + +.. _studio_editor_toolbar: + +Executing Statements from the Toolbar +------------- + +The following figure shows the **Toolbar** pane: + +.. image:: /_static/images/studio_editor_toolbar_5.3.0.png + +You can access the following from the Toolbar pane: + +* **Database dropdown list** - select a database that you want to run statements on. + +* **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. + +* **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: + + * **Statements** - executes the statement at the location of the cursor. + * **Selected** - executes only the highlighted text. This mode should be used when executing subqueries or sections of large queries (as long as they are valid SQLs). + * **All** - executes all statements in a selected tab. + +For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. + +* **Format SQL** - Lets you reformat and reindent statements. + +* **Download query** - Lets you download query text to your computer. + +* **Open query** - Lets you upload query text from your computer. + +* **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. + +:ref:`Back to Editor` + +Performing Statement-Related Operations from the Database Tree +--------------- +From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). + +The following figure shows the **Database Tree** and **System Queries** panel, with the Database Tree tab selected. + +.. image:: /_static/images/studio_database_tree_system_queries_panel_5053.png + +The following figure shows the database object functions in the **calcs** table object. + +.. image:: /_static/images/studio_database_object_operations_5030.png + +The database object functions are used to perform the following: + + + * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. + * The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. + * The **additional operations** |icon-dots| - displays the following additional options: + + + + + +.. list-table:: + :widths: 30 70 + :header-rows: 1 + + * - Function + - Description + * - Insert statement + - Generates an `INSERT `_ statement for the selected table in the editing area. + * - Delete statement + - Generates a `DELETE `_ statement for the selected table in the editing area. + * - Create Table As statement + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + * - Rename statement + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + * - Adding column statement + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + * - Truncate table statement + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + * - Drop table statement + - Generates a ``DROP`` statement for the selected object in the editing area. + * - Table DDL + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See also `Seeing System Objects as DDL `_. + * - DDL Optimizer + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + + + + + +Optimizing Database Tables Using the DDL Optimizer +^^^^^^^^^^^^^^^^^^^^^ +The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. + +As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. + +The following table describes the DDL Optimizer screen: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - Column area + - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. + * - Optimization area + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. + * - Run Optimizer + - Starts the optimization process. + +Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. The figure below shows the **calcs Optimized** tab for the optimized **calcs** table. + +For more information, see `Optimization and Best Practices `_. + +:ref:`Back to top` + +Executing Pre-Defined Queries from the System Queries Panel +--------------- +The **System Queries** panel lets you execute pre-defined queries and includes the following system query types: + +* **Catalog queries** - used for analyzing table compression rates, users and permissions, etc. +* **Admin queries** - queries related to available (describe the functionality in a general way). Queries useful for SQream database management: + + + + + +Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. + + +.. _studio_editor_statement_area: + +Writing Statements and Queries from the Statement Panel +---------------- +The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completing. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. + +The following table shows the statement statuses: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Status + - Description + * - Pending + - The statement is pending. + * - In queue + - The statement is waiting for execution. + * - Initializing + - The statement has entered execution checks. + * - Executing + - The statement is executing. + * - Statement stopped + - The statement has been stopped. + +You can add and name new tabs for each statement that you need to execute, and Studio preserves your created tabs when you switch between databases. You can add new tabs by clicking |icon-plus| , which creates a new tab to the right with a default name of SQL and an increasing number. This helps you keep track of your statements. + +.. image:: /_static/images/statement_pane_adding_statement_5.3.0.png + +You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. + +.. tip:: If this is your first time using SQream, see `First steps with SQream DB `_. + + +.. Keyboard shortcuts +.. ^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. + +.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword + +.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. + +.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab + +.. _studio_editor_results: + +:ref:`Back to Editor` + + +Viewing Statement and Query Results from the Results Panel +------------------------------------ +The results pane shows statment and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. + +.. image:: /_static/images/studio_editor_results_5053.png + +By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. + +The following is a brief description of the elements on the Results panel views: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Results view` + - Lets you view search query results. + * - :ref:`Execution Details view` + - Lets you view execution details, such as statement ID, number of rows, and averge number of rows in chunk. + * - :ref:`SQL view` + - Lets you see the SQL view. + * - :ref:`Save results to clipboard` + - Lets you save your search results to the clipboard to paste into another text editor. + * - :ref:`Save results to local file` + - Lets you save your search query results to a local file. + +.. _results_view: + + + +Searching Query Results in the Results View +^^^^^^^^^^^^ +The **Results view** lets you view search query results. + +From this view you can also do the following: + +* View the amount of time (in seconds) taken for a query to finish executing. +* Switch and scroll between tabs. +* Close all tabs at once. +* Enable keeping tabs by selecting **Keep tabs**. +* Sort column results. + +In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. + +.. _running_parallel_statements: + +Running Parallel Statements +^^^^^^^^^^^^ +While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. + +The following shows the syntax for running parallel statements: + +.. code-block:: console + + $ @@ parallel + $ $$ + $ select 1; + $ select 2; + $ select 3; + $ $$ + +The following figure shows the parallel statement syntax in the Editor: + +.. image:: /_static/images/running_parallel_statements.png + +.. _execution_details_view: + +Execution Details View +^^^^^^^^^^^^ +The **Execution Details** view lets you view a query’s execution plan for monitoring purposes. Most importantly, the Execution Details view highlights rows based on how long they ran relative to the entire query. + +This can be seen in the **timeSum** column as follows: + +* **Rows highlighted red** - longest runtime +* **Rows highlighted orange** - medium runtime +* **Rows highlighted yellow** - shortest runtime + +.. image:: /_static/images/execution_details_view_3.png + + + +.. _sql_view: + +Viewing Wrapped Strings in the SQL View +^^^^^^^^^^^^ +The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuititively structured snapshot of it. + +The following figure shows the SQL view: + +.. image:: /_static/images/sql_view_5.0.3.png + +.. _save_results_to_clipboard: + +Saving Results to the Clipboard +^^^^^^^^^^^^ +The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. + + +.. _save_results_to_local_file: + +Saving Results to a Local File +^^^^^^^^^^^^ +The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. + +Analyzing Results +---------------------------- + +When results are produced, a **Generate CREATE statement** button is displayed. Clicking this button creates a new tab with an optimized :ref:`create_table` statement, and an :ref:`insert` statement to copy the data to the new table. + +.. _logs: + +.. _logs_top: + +:ref:`Back to Editor` + +Viewing Logs +============ +The **Logs** screen is used for viewing logs and includes the following elements: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Filter area` + - Lets you filter the data shown in the table. + * - :ref:`Query tab` + - Shows basic query information logs, such as query number and the time the query was run. + * - :ref:`Session tab` + - Shows basic session information logs, such as session ID and user name. + * - :ref:`System tab` + - Shows all system logs. + * - :ref:`Log lines tab` + - Shows the total amount of log lines. + + +.. _filter: + +Filtering Table Data +------------- +From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). + + +Some filters require you to type text to define the filter. + +.. image:: /_static/images/logs_filters_5.3.0.png + +Other filters require you to select an item from a dropdown menu: + +* INFO +* WARNING +* ERROR +* FATAL +* SYSTEM + +You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. + +.. _queries: + +:ref:`Back to Viewing Logs` + + +Viewing Query Logs +---------- +The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. + +From the Queries area you can see and sort by the following: + +* Query ID +* Start time +* Query +* Compilation duration +* Execution duration +* Total duration +* Details (execution details, error details, successful query details) + +In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. + +:ref:`Back to Viewing Logs` + +.. _sessions: + +Viewing Session Logs +---------- +The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. + +From here you can see and sort by the following: + +* Timestamp +* Connection ID +* Username +* Client IP +* Login (Success or Failed) +* Duration (of session) +* Configuration Changes + +In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. + +:ref:`Back to Viewing Logs` + +.. _system: + +Viewing System Logs +---------- +The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. + +From here you can see and sort by the following: + +* Timestamp +* Log type +* Message + +In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. + +:ref:`Back to Viewing Logs` + +.. _log_lines: + +Viewing All Log Lines +---------- +The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. + +From here you can see and sort by the following: + +* Timestamp +* Message level +* Worker hostname +* Worker port +* Connection ID +* Database name +* User name +* Statement ID + +In the **LOG LINES** table, you can click on any of the items to set them as your filters. + +:ref:`Back to Viewing Logs` + +:ref:`Back to Editor` + +.. _roles: + +Creating, Assigning, and Managing Roles and Permissions +============ +Overview +--------------- +In the **Roles** area you can create and assign roles and manage user permissions. + +The **Type** column displays one of the following assigned role types: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Role Type + - Description + * - Groups + - Roles with no users. + * - Enabled users + - Users with log-in permissions and a password. + * - Disabled users + - Users with log-in permissions and with a disabled password. An admin may disable a user's password permissions to temporary disable access to the system. + +.. note:: If you disable a password, when you enable it you have to create a new one. + + +Viewing Information About a Role +-------------------- +Clicking a role in the roles table displays the following information: + + * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. + * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. + * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. + +Creating a New Role +-------------------- +You can create a new role by clicking **New Role**. + +.. image:: /_static/images/role_button.png + +An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. + +Clicking **New Role** lets you do the following: + + * Add and assign a role name (required) + * Enable or disable log-in permissions for the role. + * Set a password. + * Assign or delete parent roles. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. + +Editing a Role +-------------------- +Once you've created a role, clicking the **Edit Role** button lets you do the following: + + * Edit the role name. + * Enable or disable log-in permissions. + * Set a password. + * Assign or delete parent roles. + * Assign a role **administrator** permissions. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +Deleting a Role +----------------- +Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. From d002f318c28dd2ace824bd21d26618768cfe4044 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 15:54:01 +0300 Subject: [PATCH 0178/1892] Removed password policy --- operational_guides/access_control.rst | 1 - .../access_control_password_policy.rst | 42 ------------------- 2 files changed, 43 deletions(-) delete mode 100644 operational_guides/access_control_password_policy.rst diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index bd25d0d99..88a14d71b 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -11,5 +11,4 @@ Access Control access_control_overview access_control_managing_roles access_control_permissions - access_control_password_policy access_control_departmental_example \ No newline at end of file diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst deleted file mode 100644 index 10a4f697f..000000000 --- a/operational_guides/access_control_password_policy.rst +++ /dev/null @@ -1,42 +0,0 @@ -.. _access_control_password_policy: - -************** -Password Policy -************** -As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: - -* At least eight characters long. - - :: - -* Mandatory upper and lowercase letters. - - :: - -* At least one numeric character. - - :: - -* May not include a username. - - :: - -* Must include at least one special character, such as **?**, **!**, **$**, etc. - -You can create a password through the Studio graphic interface or through the CLI, as in the following example command: - -.. code-block:: console - - CREATE ROLE user_a ; - GRANT LOGIN to user_a ; - GRANT PASSWORD 'BBAu47?fqPL' to user_a ; - -Creating a password that does not comply with the above requirements generates an error message with a request to modify it. - -Unsuccessfully attempting to log in three times displays the following message: - -.. code-block:: console - - The user is locked. please contact your system administrator to reset the password and regain access functionality. - -For more information, see :ref:`login_max_retries`. From 0dcf869e40e8545f6e745ae29cd29298f41f2629 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 17:40:00 +0300 Subject: [PATCH 0179/1892] Links --- releases/2020.3.rst | 14 +++++--------- releases/2021.1.2.rst | 4 ++-- releases/2021.1.rst | 14 +++++++------- releases/2021.2.1.24.rst | 12 ++++++------ releases/2021.2.1.rst | 8 ++++---- 5 files changed, 24 insertions(+), 28 deletions(-) diff --git a/releases/2020.3.rst b/releases/2020.3.rst index b51a9955d..eb8ca8f62 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -26,9 +26,12 @@ The following list describes the new features: * ``TEXT`` is ramping up with new features (previously only available with VARCHARs): - * :ref:`substring`, :ref:`lower`, :ref:`ltrim`, :ref:`charindex`, :ref:`replace`, etc. + * `SUBSTRING `_ + * `LTRIM `_ + * `CHARINDEX `_ + * `REPLACE `_ - * Binary operators - :ref:`concat`, :ref:`like`, etc. + * Binary operators - `CONCAT `_ , `REPLACE `_ , etc. * Casts to and from ``TEXT`` @@ -100,10 +103,3 @@ Upgrading to v2020.3 Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. Contact your account manager to get the latest release of SQream. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2020.3 diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index 5ccd878d8..e163c987d 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -48,9 +48,9 @@ SQream now interprets literals containing decimal points as ``numeric`` instead For more information, see `Data Types `_. -Roles Area Added to Studio Version 5.3.3 +Roles Area Added to Studio Version 5.4.3 **************** -The **Roles** area has been added to `Studio version 5.3.3 `_. From the Roles area users can create and assign roles and manage user permissions. +The **Roles** area has been added to `Studio version 5.3.3 `_. From the Roles area users can create and assign roles and manage user permissions. Resolved Issues ------------- diff --git a/releases/2021.1.rst b/releases/2021.1.rst index 15824d5d5..389655262 100644 --- a/releases/2021.1.rst +++ b/releases/2021.1.rst @@ -40,7 +40,7 @@ SQream now supports Numeric Data types for the following operations: * All aggregation types (not including Window functions). * Scalar functions (not including some trigonometric and logarithmic functions). -For more information, see `Numeric Data Types `_. +For more information, see `Numeric Data Types `_. Text Data Type ************ @@ -54,14 +54,14 @@ SQream now supports TEXT data types in all operations, which is default string d * Support text columns in queries with multiple distinct aggregates. * Text literal support for all functions. -For more information, see `String Types `_. +For more information, see `String Types `_. Supports Scalar Subqueries ************ SQream now supports running initial scalar subqueries. -For more information, see `Subqueries `_. +For more information, see `Subqueries `_. Literal Arguments ************ @@ -72,7 +72,7 @@ Simple Scalar SQL UDFs ************ SQream now supports simple scalar SQL UDF's. -For more information, see `Simple Scalar SQL UDF’s `_. +For more information, see `Simple Scalar SQL UDF’s `_. Logging Enhancements ************ @@ -91,7 +91,7 @@ Improved Presented License Information ************ SQream now displays information related to data size limitations, expiration date, type of license shown by the new UF. The **Utility Function (UF)** name is ``get_license_info()``. -For more information, see `GET_LICENSE_INFO `_. +For more information, see `GET_LICENSE_INFO `_. @@ -171,7 +171,7 @@ Operations and Configuration Changes Recommended SQream Configuration on Cloud ************ -For more information about AWS, see `Amazon S3 `_. +For more information about AWS, see `Amazon S3 `_. @@ -183,7 +183,7 @@ SQream now has a new ``runtimeGlobalFlags`` flag called ``WriteToFileThreads``. This flag configures the number of threads in the **WriteToFile** function. The default value is ``16``. -For more information about the ``runtimeGlobalFlags`` flag, see the **Runtime Global Flags** table in `Configuration `_. +For more information about the ``runtimeGlobalFlags`` flag, see the **Runtime Global Flags** table in `Configuration `_. diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index f92cfda00..1d5407d89 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -15,7 +15,7 @@ The 2021.2.1.24 Release Notes includes a query maintenance feature. New Features ---------- -The 2021.2.1.24 Release Notes include the following new features: +The 2021.2.1.24 Release Notes include the following new features: .. contents:: :local: @@ -25,7 +25,7 @@ Query Healer ************ The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. -For more information, see `Query Healer `_. +For more information, see `Query Healer `_. Known Issues --------- @@ -53,9 +53,9 @@ Resolved Issues --------- The Resolved Issues section is not relevant for Version 2021.2.1.24. -Operations and Configuration Changes --------- -No relevant operations and configuration changes were made. +Operational and Configuration Changes +------- +No relevant operational or configuration changes were made. Naming Changes ------- @@ -74,4 +74,4 @@ The End of Support section is not relevant to Version 2021.2.1.24. :glob: :hidden: - 2021.2.1.24 + 2021.2.1.24 \ No newline at end of file diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index c7e1dbada..c476bd2d5 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -21,7 +21,7 @@ CREATE TABLE ************ SQream now supports duplicating the column structure of an existing table using the ``LIKE`` clause. -For more information, see `Duplicating the Column Structure of an Existing Table `_. +For more information, see `Duplicating the Column Structure of an Existing Table `_. PERCENTILE FUNCTIONS ************ @@ -35,15 +35,15 @@ REGEX REPLACE ************ SQream now supports the ``REGEXP_REPLACE`` function for finding and replacing text column substrings. -For more information, see :ref:`regexp_replace`. +For more information, see `REGEX_REPLACE `_. Delete Optimization ************ The ``DELETE`` statement can now delete values that contain multi-table conditions. -For more information, see `Deleting Values that Contain Multi-Table Conditions `_. +For more information, see `Deleting Values that Contain Multi-Table Conditions `_. -For more information, see :ref:`regexp_replace`. +For more information, see `REGEX_REPLACE `_. Performance Enhancements ------ From 4c79df05607c298193c873538bc82c089cb4726b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 18:35:05 +0300 Subject: [PATCH 0180/1892] Links --- releases/2021.2.1.rst | 10 +++++----- releases/2021.2.rst | 8 ++------ 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index c476bd2d5..2988d98f6 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -27,15 +27,15 @@ PERCENTILE FUNCTIONS ************ SQream now supports the following aggregation functions: -* :ref:`percentile_cont` -* :ref:`percentile_disc` -* :ref:`mode` +* `PERCENTILE_CONT `_ +* `PERCENTILE_DISC `_ +* `MODE `_ REGEX REPLACE ************ SQream now supports the ``REGEXP_REPLACE`` function for finding and replacing text column substrings. -For more information, see `REGEX_REPLACE `_. +For more information, see `REGEX_REPLACE `_. Delete Optimization ************ @@ -43,7 +43,7 @@ The ``DELETE`` statement can now delete values that contain multi-table conditio For more information, see `Deleting Values that Contain Multi-Table Conditions `_. -For more information, see `REGEX_REPLACE `_. +For more information, see `REGEX_REPLACE `_. Performance Enhancements ------ diff --git a/releases/2021.2.rst b/releases/2021.2.rst index cce1675dc..a46762f01 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -34,17 +34,13 @@ SQream now uses a new configuration system based on centralized configuration ac For more information, see the following: * `Configuration `_ - describes how to configure your instance of SQream from a centralized location. -* `SQream Studio 5.4.2 `_ - configure your instance of SQream from Studio. +* `SQream Studio 5.4.3 `_ - configure your instance of SQream from Studio. Qualifying Schemas Without Providing an Alias ************ When running queries, SQream now supports qualifying schemas without providing an alias. -For more information, see :ref:`create_schema`. - - - - +For more information, see `SQream Studio 5.4.3 `_. Double-Quotations Supported When Importing and Exporting CSVs ************ From 82abd5b5a6d0243f88e149a1f30d00483dd15990 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 18:46:32 +0300 Subject: [PATCH 0181/1892] Links --- releases/2021.1.2.rst | 2 +- releases/2021.2.1.rst | 10 +++++----- releases/2021.2.rst | 15 ++++++++------- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index e163c987d..8945a0261 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -50,7 +50,7 @@ For more information, see `Data Types `_. From the Roles area users can create and assign roles and manage user permissions. +The **Roles** area has been added to `Studio version 5.4.3 `_. From the Roles area users can create and assign roles and manage user permissions. Resolved Issues ------------- diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index 2988d98f6..e1a01a147 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -27,15 +27,15 @@ PERCENTILE FUNCTIONS ************ SQream now supports the following aggregation functions: -* `PERCENTILE_CONT `_ -* `PERCENTILE_DISC `_ -* `MODE `_ +* `PERCENTILE_CONT `_ +* `PERCENTILE_DISC `_ +* `MODE `_ REGEX REPLACE ************ SQream now supports the ``REGEXP_REPLACE`` function for finding and replacing text column substrings. -For more information, see `REGEX_REPLACE `_. +For more information, see `REGEX_REPLACE `_. Delete Optimization ************ @@ -43,7 +43,7 @@ The ``DELETE`` statement can now delete values that contain multi-table conditio For more information, see `Deleting Values that Contain Multi-Table Conditions `_. -For more information, see `REGEX_REPLACE `_. +For more information, see `REGEX_REPLACE `_. Performance Enhancements ------ diff --git a/releases/2021.2.rst b/releases/2021.2.rst index a46762f01..800b8c863 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -34,13 +34,13 @@ SQream now uses a new configuration system based on centralized configuration ac For more information, see the following: * `Configuration `_ - describes how to configure your instance of SQream from a centralized location. -* `SQream Studio 5.4.3 `_ - configure your instance of SQream from Studio. +* `SQream Studio 5.4.3 `_ - configure your instance of SQream from Studio. Qualifying Schemas Without Providing an Alias ************ When running queries, SQream now supports qualifying schemas without providing an alias. -For more information, see `SQream Studio 5.4.3 `_. +For more information, see `SQream Studio 5.4.3 `_. Double-Quotations Supported When Importing and Exporting CSVs ************ @@ -48,9 +48,10 @@ When importing and exporting CSVs, SQream now supports using quotation character For more information, see the following: -* :ref:`copy_from` +* `COPY_FROM `_ + +* `COPY_TO `_ -* :ref:`copy_to` Note the following: @@ -128,7 +129,7 @@ NVARCHAR Data Type Renamed TEXT The ``NVARCHAR`` data type has been renamed ``TEXT``. -For more information on the ``TEXT`` data type, see `String (TEXT) `_ +For more information on the ``TEXT`` data type, see `String (TEXT) `_ End of Support ------ @@ -159,13 +160,13 @@ For more information on upgrading your SQream version, see `Upgrading SQream Ver Upgrading Your Client Drivers ************ -For more information on the client drivers for version 2021.2, see `Client Drivers for 2021.2 `_. +For more information on the client drivers for version 2021.2, see `Client Drivers for 2021.2 `_. Configuring Your Instance of SQream ************ A new configuration method is used starting with Version 2021.2. -For more information about configuring your instance of SQream, see :ref:`configuration`. +For more information about configuring your instance of SQream, see `Client Drivers for 2021.2 `_. .. toctree:: :maxdepth: 2 From f72cf319f80d4b3a2aa1b03000eeeac4e25c0ce7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 31 Jul 2022 19:12:27 +0300 Subject: [PATCH 0182/1892] Fixed link --- releases/2021.1.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index 8945a0261..750420260 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -40,7 +40,7 @@ String Literals Containing ASCII Characters Interepreted as TEXT ************ SQream now interprets all string literals, including those containing ASCII characters, as ``text``. -For more information, see `String Types `_. +For more information, see `String Types `_. Decimal Literals Interpreted as Numeric Columns ************ From c6cb8164225ddfd101bd43aa787965bf9e72ee54 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 1 Aug 2022 12:09:01 +0300 Subject: [PATCH 0183/1892] Corrected driver links --- connecting_to_sqream/client_drivers/index.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 79d1fd176..b230faaef 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,14 +18,14 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) - * `JDBC driver `_ + * `JDBC driver `_ .. _tableau_connector: * **Tableau**: * `Tableau connector `_ - SQream (.taco) - * `Tableau manual installation `_ + * `Tableau manual installation `_ .. _powerbi_connector: @@ -33,7 +33,7 @@ The following are applicable to all operating systems: * **Power BI**: * `Power BI PowerQuery connector `_ - SQream (.mez) - * `Power BI manual installation `_ + * `Power BI manual installation `_ Windows @@ -53,12 +53,12 @@ Linux The following are applicable to Linux: * `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines :: * `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines :: From edcf3ce813e7ce9b41a52782397006848cf93f3e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 1 Aug 2022 13:35:35 +0300 Subject: [PATCH 0184/1892] corrected links --- releases/2021.2.rst | 5 ++++- releases/2022.1.rst | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/releases/2021.2.rst b/releases/2021.2.rst index 800b8c863..c4174a3aa 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -89,7 +89,10 @@ Note the following: For more information, see the following statements: -* :ref:`copy_from` +* `COPY_FROM `_ + +* `CREATE_FOREIGN_TABLE `_ + * :ref:`create_foreign_table` diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 085108a43..3d1517371 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -31,7 +31,7 @@ SQream now supports data encryption mechanisms in accordance with **General Data Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. -For more information, see `Data Encryption `_. +For more information, see `Data Encryption `_. Update Feature ************ From 2f95101378fdcf6f73f57e738f699a96ef8759dd Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 1 Aug 2022 19:03:59 +0300 Subject: [PATCH 0185/1892] Added External Storage Platforms --- .../hdfs.rst | 0 external_storage_platforms/index.rst | 25 +++++++++++++++++++ .../s3.rst | 0 index.rst | 1 + operational_guides/external_data.rst | 25 ------------------- operational_guides/index.rst | 1 - 6 files changed, 26 insertions(+), 26 deletions(-) rename {operational_guides => external_storage_platforms}/hdfs.rst (100%) create mode 100644 external_storage_platforms/index.rst rename {operational_guides => external_storage_platforms}/s3.rst (100%) delete mode 100644 operational_guides/external_data.rst diff --git a/operational_guides/hdfs.rst b/external_storage_platforms/hdfs.rst similarity index 100% rename from operational_guides/hdfs.rst rename to external_storage_platforms/hdfs.rst diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst new file mode 100644 index 000000000..92c35ee63 --- /dev/null +++ b/external_storage_platforms/index.rst @@ -0,0 +1,25 @@ +.. _external_storage_platforms: + +*********************** +External Storage Platforms +*********************** +SQream supports the following external storage platforms: + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + s3 + hdfs + +For more information, see the following: + +* :ref:`foreign_tables` + + :: + +* :ref:`copy_from` + + :: + +* :ref:`copy_to` diff --git a/operational_guides/s3.rst b/external_storage_platforms/s3.rst similarity index 100% rename from operational_guides/s3.rst rename to external_storage_platforms/s3.rst diff --git a/index.rst b/index.rst index bc5c25c2c..0f418c2fb 100644 --- a/index.rst +++ b/index.rst @@ -100,6 +100,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu installation_guides/index data_ingestion/index connecting_to_sqream/index + external_storage_platforms/index loading_and_unloading_data/index feature_guides/index operational_guides/index diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst deleted file mode 100644 index 8bf51f108..000000000 --- a/operational_guides/external_data.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. _external_data: - -********************************** -Working with External Data -********************************** -SQream supports the following external data sources: - -.. toctree:: - :maxdepth: 1 - :titlesonly: - - s3 - hdfs - -For more information, see the following: - -* :ref:`external_tables` - - :: - -* :ref:`copy_from` - - :: - -* :ref:`copy_to` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 9deb0835c..25e2cdff2 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -14,7 +14,6 @@ This section summarizes the following operational guides: access_control creating_or_cloning_a_storage_cluster - external_data foreign_tables delete_guide exporting_data From 637d7f74b1c40e4624bced96b28af440c7f1bff5 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 2 Aug 2022 11:10:27 +0300 Subject: [PATCH 0186/1892] Fixed links. --- releases/2021.2.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/releases/2021.2.rst b/releases/2021.2.rst index c4174a3aa..2140dc6be 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -91,10 +91,7 @@ For more information, see the following statements: * `COPY_FROM `_ -* `CREATE_FOREIGN_TABLE `_ - - -* :ref:`create_foreign_table` +* `CREATE_FOREIGN_TABLE `_ Performance Enhancements ------ @@ -159,7 +156,7 @@ When upgrading from a SQream version earlier than 2021.2 you must upgrade your s $ cat /etc/sqream/sqream1_config.json |grep cluster $ ./upgrade_storage -For more information on upgrading your SQream version, see `Upgrading SQream Version `_. +For more information on upgrading your SQream version, see `Upgrading SQream Version `_. Upgrading Your Client Drivers ************ From b65ab1f10b30ddfa0ab646a9704da87ddd4cabe0 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 2 Aug 2022 12:17:56 +0300 Subject: [PATCH 0187/1892] Reinstated Healer configuration flags Removed login max retries flag (it's for 2022.1.1). --- configuration_guides/admin_worker_flags.rst | 3 ++- .../healer_max_inactivity_hours.rst | 14 ++++++++++++++ configuration_guides/is_healer_on.rst | 14 ++++++++++++++ feature_guides/query_healer.rst | 12 +++++++++++- 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 configuration_guides/healer_max_inactivity_hours.rst create mode 100644 configuration_guides/is_healer_on.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index 6be021d70..d58dad687 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -9,4 +9,5 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Enabling Manually Setting Reported IP `_ * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ -* `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file +* `Enabling the Query Healer `_ +* `Configuring the Query Healer `_ \ No newline at end of file diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst new file mode 100644 index 000000000..d05d46014 --- /dev/null +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -0,0 +1,14 @@ +.. _healer_max_inactivity_hours: + +************************* +Query Healer +************************* +The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The following describes the ``healerMaxInactivityHours`` flag: + +* **Data type** - size_t +* **Default value** - ``5`` +* **Allowed values** - 1-4000000000 + +For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst new file mode 100644 index 000000000..8b90654ec --- /dev/null +++ b/configuration_guides/is_healer_on.rst @@ -0,0 +1,14 @@ +.. _is_healer_on: + +************************* +Enabling the Query Healer +************************* +The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. + +The following describes the ``is_healer_on`` flag: + +* **Data type** - boolean +* **Default value** - ``true`` +* **Allowed values** - ``true``, ``false`` + +For related flags, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 667a91ed8..8f0b56d08 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -19,6 +19,16 @@ The following is an example of a log record for a query stuck in the query detec 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours +The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. + Configuring the Healer ------------------ -The **healerMaxInactivityHours** is required define the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. \ No newline at end of file +The following **Administration Worker** flags are required to configure the Query Healer: + + * :ref:`is_healer_on` - Enables the Query Healer. + + :: + + * :ref:`healer_max_inactivity_hours` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. \ No newline at end of file From 307fba9a817b840cbc901500db43da96f6fe4897 Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 2 Aug 2022 15:24:32 +0300 Subject: [PATCH 0188/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 3370698cf..65f03ab5e 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -23,5 +23,3 @@ The following is an example of encrypting a new table: salary INT(6) ENCRYPT); .. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. - -Note that the master key is hard-coded in the system and cannot be changed. From ed492d74ac4aa33abbe63b6b38ead278fe7e34fc Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 2 Aug 2022 16:34:18 +0300 Subject: [PATCH 0189/1892] Created and populated 2022.1.1 - NOT PUBLISHED --- _static/images/new_2022.1.1.png | Bin 0 -> 3259 bytes _static/images/new_dark_gray_2022.1.1.png | Bin 0 -> 2867 bytes _static/images/new_gray_2022.1.1.png | Bin 0 -> 3842 bytes configuration_guides/admin_worker_flags.rst | 19 ++- configuration_guides/login_max_retries.rst | 7 +- feature_guides/compression.rst | 8 + operational_guides/access_control.rst | 1 + .../access_control_password_policy.rst | 63 ++++++++ .../sql_statements/dml_commands/update.rst | 149 +++++++++++++++++- releases/2022.1.1.rst | 136 ++++++++++++++++ releases/2022.1_index.rst | 1 + releases/index.rst | 2 +- 12 files changed, 373 insertions(+), 13 deletions(-) create mode 100644 _static/images/new_2022.1.1.png create mode 100644 _static/images/new_dark_gray_2022.1.1.png create mode 100644 _static/images/new_gray_2022.1.1.png create mode 100644 operational_guides/access_control_password_policy.rst create mode 100644 releases/2022.1.1.rst diff --git a/_static/images/new_2022.1.1.png b/_static/images/new_2022.1.1.png new file mode 100644 index 0000000000000000000000000000000000000000..2ffb80039be7a7a4ac7605f8271045e4d0138185 GIT binary patch literal 3259 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 Ef=gpok^lez literal 0 HcmV?d00001 diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index d58dad687..edbc71465 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -3,11 +3,18 @@ ************************* Worker Administration Flags ************************* + +.. |icon-new_gray_2022.1.1| image:: /_static/images/new_gray_2022.1.1.png + :align: middle + :width: 110 + + The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Total Device Memory Usage in SQream Instance `_ -* `Enabling Manually Setting Reported IP `_ -* `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ -* `Enabling the Query Healer `_ -* `Configuring the Query Healer `_ \ No newline at end of file +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ +* `Assigning Local Network IP `_ +* `Enabling the Query Healer `_ +* `Configuring the Query Healer `_ +* `Adjusting the Permitted Log-In Attempts `_ |icon-new_gray_2022.1.1| \ No newline at end of file diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst index bf3ae6d40..af236c9c3 100644 --- a/configuration_guides/login_max_retries.rst +++ b/configuration_guides/login_max_retries.rst @@ -3,7 +3,12 @@ ************************* Adjusting Permitted Log-in Attempts ************************* -The ``loginMaxRetries`` flag sets the permitted log-in attempts. + +.. |icon-new_2022.1.1| image:: /_static/images/new_2022.1.1.png + :align: middle + :width: 110 + +The ``loginMaxRetries`` flag |icon-new_2022.1.1| sets the permitted log-in attempts. The following describes the ``loginMaxRetries`` flag: diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 96c051ff4..ce5e922b6 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -4,6 +4,10 @@ Compression *********************** +.. |icon-new_dark_gray_2022.1.1.png| image:: /_static/images/new_dark_gray_2022.1.1.png + :align: middle + :width: 110 + SQream DB uses compression and encoding techniques to optimize query performance and save on disk space. Encoding @@ -89,6 +93,10 @@ Compression strategies - Integer types - Optimized RLE + Delta type for built-in :ref:`identity columns`. - GPU + * - ``zlib`` |icon-new_dark_gray_2022.1.1.png| + - All types + - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. + - CPU .. _specifying_compressions: diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index 88a14d71b..d5d32394e 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -11,4 +11,5 @@ Access Control access_control_overview access_control_managing_roles access_control_permissions + access_control_password_policy access_control_departmental_example \ No newline at end of file diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst new file mode 100644 index 000000000..0a17f833e --- /dev/null +++ b/operational_guides/access_control_password_policy.rst @@ -0,0 +1,63 @@ +.. _access_control_password_policy: + +************** +Password Policy (New!) +************** + +.. |icon-new_gray_2022.1.1| image:: /_static/images/new_gray_2022.1.1.png + :align: middle + :width: 110 + +As part of our compliance with GDPR standards |icon-new_gray_2022.1.1| SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: + +* At least eight characters long. + + :: + +* Mandatory upper and lowercase letters. + + :: + +* At least one numeric character. + + :: + +* May not include a username. + + :: + +* Must include at least one special character, such as **?**, **!**, **$**, etc. + +You can create a password through the Studio graphic interface or through the CLI, as in the following example command: + +.. code-block:: console + + CREATE ROLE user_a ; + GRANT LOGIN to user_a ; + GRANT PASSWORD 'BBAu47?fqPL' to user_a ; + +Creating a password that does not comply with the above requirements generates the following error message: + +.. code-block:: console + + The password you attempt to create does not comply with SQream security requirements. Please follow the requirements below: + + * At least 8 characters long. + + * Must include both upper and lower case letters. + + * Must include at least one numeric character. + + * Must not include your username. + + * Must include at least one “special” character (?, !, $, etc.). + +.. note:: When a new user created in Studio, a message is displayed to help you determine what the constraints are. + +Unsuccessfully attempting to log in three times displays the following message: + +.. code-block:: console + + The user is locked. please contact your system administrator to reset the password and regain access functionality. + +For more information, see :ref:`login_max_retries`. \ No newline at end of file diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index d0f545017..b804d6c37 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -3,9 +3,9 @@ ********************** UPDATE ********************** -The **UPDATE** statement page |icon-new_2022.1| describes the following: +The **UPDATE** statement page describes the following: -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png +.. |icon-new_2022.1.1| image:: /_static/images/new_2022.1.1.png :align: middle :width: 110 @@ -35,6 +35,7 @@ The following is the correct syntax for the ``UPDATE`` command: UPDATE target_table_name [[AS] alias1] SET column_name = expression [,...] + [FROM additional_table_name [[AS] alias2][,...]] [WHERE condition] The following is the correct syntax for triggering a clean-up: @@ -60,10 +61,14 @@ The following table describes the ``UPDATE`` parameters: * - ``column_name`` - Specifies the column containing the data to be updated. * - ``additional_table_name`` - - Additional tables used in the WHERE condition for performing complex joins. + - Specifies the column containing the data to be updated. + * - ``FROM`` |icon-new_2022.1.1| + - For making complex joins, specifies additional tables to be used in the WHERE condition. ``FROM`` is similar to the ``FROM`` clause in a ``DELETE`` statement. * - ``condition`` - Specifies the condition for updating the data. +.. note:: A single table can appear **both** as a ``DELETE`` target *and* as a ``FROM`` table. This can be useful for deleting data based on self-join conditions. A ``SET`` clause can contain columns from tables specified in a ``FROM`` clause. For example, using the join ``WHERE`` condition updates rows in the target tables with the values of one of the matching rows. + .. note:: Similar to a ``DELETE`` statement, an ``UPDATE`` statement may leave some uncleaned data behind, which requires a clean-up operation. Examples @@ -74,6 +79,30 @@ The **Examples** section includes the following examples: :local: :depth: 1 +Updating an Entire Table +----------------- +The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: + +.. image:: /_static/images/delete_optimization.png + +The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 WHERE true; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; + Performing Simple Updates ----------------- The following is an example of performing a simple update: @@ -81,9 +110,102 @@ The following is an example of performing a simple update: .. code-block:: postgres UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; + +Updating Tables that Contain Multi-Table Conditions +----------------- +The following shows an example of updating tables that contain multi-table conditions: -Triggering a Clean-Up +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + 1 + WHERE EXISTS ( + SELECT 1 FROM countries + WHERE countries.id=bands.country_id + AND country.name = 'Sweden' + ); + +Updating Tables that Contain Multi-Table Conditions using the FROM Clause +----------------- +The following shows an example of updating tables that contain multi-table conditions using the ``FROM`` clause: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + + CASE + WHEN c.name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c + +You can also write the statement above using the FROM clause: + +.. code-block:: psql + + UPDATE bands + SET records_sold = records_sold + 1 + FROM countries + WHERE countries.id=bands.country_id AND country.name = 'Sweden'; + +Updating Tables that Contain Multi-Table Expressions +----------------- +The following shows an example of updating tables that contain multi-table expressions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + + CASE + WHEN c.name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c + +Identifying and Cleaning Up Tables --------------------------------------- +The following section shows examples of each phase required for cleaning up tables: + +* :ref:`Listing tables that require clean-up` +* :ref:`Identifying clean-up predicates` +* :ref:`Triggering a clean-up` + +.. _listing_tables_that_require_cleanup: + +Listing Tables that Require Clean-Up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing tables that require clean-up: + +.. code-block:: psql + + farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + GROUP BY 1; + cool_animals + + 1 row + +.. _identifying_cleanup_predicates: + +Identifying Clean-Up Predicates +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following shows an example of listing the clean-up predicates: + +.. code-block:: psql + + farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp + JOIN sqream_catalog.tables t + ON dp.table_id = t.table_id + WHERE t.table_name = 'cool_animals'; + weight > 1000 + + 1 row + +.. _triggering_a_cleanup: + +Triggering a Clean-Up +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following section shows an example of triggering a clean-up: .. code-block:: psql @@ -98,10 +220,27 @@ The following is an example of the output generated from the above: * **column_id** - 1 * **extent_ID** - 0 +Security and Access Control +============= +Executing an ``UPDATE`` statement requires the following: + +* Both ``UPDATE`` and ``SELECT`` permissions on the target table. + + :: + +* The ``SELECT`` permission for each additional table referenced in the the statement (either in the ``FROM`` clause or in a ``WHERE`` subquery expression). + +For more information, navigate to the **Access Control** page and see `Permissions `_. + +file:///C:/Users/Yaniv/sqream_docs/_build/html/operational_guides/access_control_permissions.html + Locking and Concurrency ============= Executing the ``UPDATE`` statement obtains an exclusive ``UPDATE`` lock on the target table. Permissions ============= -Executing an ``UPDATE`` statement requires both ``UPDATE`` and ``SELECT`` permissions on the target table. \ No newline at end of file +Executing an ``UPDATE`` statement requires the following permissions: + +* Both ``UPDATE`` and ``SELECT`` permissions on the target table. +* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst new file mode 100644 index 000000000..15fcd8c42 --- /dev/null +++ b/releases/2022.1.1.rst @@ -0,0 +1,136 @@ +.. _2022.1.1: + +************************** +Release Notes 2022.1.1 +************************** +The 2022.1.1 release notes were released on 7/19/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.1 Release Notes describes the following: + +* Enhanced security features. +* New data manipulation command. +* Additional data ingestion format. + +New Features +---------- +The 2022.1.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Update Feature +************ +SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. + +For more information, see `UPDATE `_. + +file:///C:/Users/Yaniv/sqream_docs/_build/html/reference/sql/sql_statements/dml_commands/update.html?highlight=update + +Password Policy +************ +In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. + +For more information, see `Password Policy `_. + +file:///C:/Users/Yaniv/sqream_docs/_build/html/operational_guides/access_control_password_policy.html?highlight=password%20policy + +Compression +************ + +SQream now supports the **zlib** compression format. + +For more information, see `Compression `_. + +file:///C:/Users/Yaniv/sqream_docs/_build/html/feature_guides/compression.html#compression-strategies + +Known Issues +--------- +The following table lists the known issues for Version 2022.1.1: + ++-------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+================================================================================================+ +| SQ-6419 | An internal compiler error occurred when casting Numeric literals in an aggregation function. | ++-------------+------------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.1: + ++-------------+----------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+========================================================================================+ +| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | ++-------------+----------------------------------------------------------------------------------------+ +| SQ-10955 | No metadata filters were applied when filtering by a nullable date using ``dateadd``. | ++-------------+----------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. + +For more information, see `Adjusting the Permitted Log-In Attempts `_. + +https://docs.sqream.com/en/latest/configuration_guides/login_max_retries.html + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +No features were deprecated for Version 2022.1.1. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1.1. + +Upgrading to v2022.1.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 9c7b2b211..628b372aa 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,4 +13,5 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.1 2022.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index b1d065a9e..84024586e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -32,7 +32,7 @@ Release Notes :glob: :hidden: - 2022.1 + 2022.1_index 2021.2_index 2021.1_index 2020.3_index From 3239b338af16ae2262dc98ece1b5626d567a84fc Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 2 Aug 2022 17:08:37 +0300 Subject: [PATCH 0190/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 65f03ab5e..0eec64bc7 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -7,19 +7,20 @@ The following is the syntax for encrypting a new table: .. code-block:: console - CREATE TABLE ( - <(maximum string length)>, - - last_name <(maximum string length)>, - salary (<(maximum string length)>) ENCRYPT); + CREATE TABLE

( + NOT NULL ENCRYPT, + ENCRYPT, + , + ENCRYPT); The following is an example of encrypting a new table: .. code-block:: console CREATE TABLE client_name ( - first_name TEXT(128), - last_name TEXT(128), - salary INT(6) ENCRYPT); + id BIGINT NOT NULL ENCRYPT, + first_name TEXT ENCRYPT, + last_name TEXT, + salary INT ENCRYPT); .. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. From 14d029d853ac26bda98622b282d649a22c17a89e Mon Sep 17 00:00:00 2001 From: YanivGerowitz <82020437+YanivGerowitz@users.noreply.github.com> Date: Tue, 2 Aug 2022 18:13:08 +0300 Subject: [PATCH 0191/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 0eec64bc7..bba431aec 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -23,4 +23,12 @@ The following is an example of encrypting a new table: last_name TEXT, salary INT ENCRYPT); -.. note:: Users without permissions cannot view the entire table as long as at least one column is encrypted. The (unique) encryption/decryption key is relevant only at the system level and is not held by users. +.. note:: Because encryption is not associated with any role, users with **Read** or **Insert** permissions can read tables containing encrypted data. + +.. warning:: Your performance degradation increases in correlation with the amount of added columns. + +You cannot encrypt more than three columns. Attempting to encrypt more than three columns displays the following error message: + +.. code-block:: console + + Error preparing statement: Cannot create a table with more than three encrypted columns. From c020e61055c97b51fabb9aa5f62436a31593ae95 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 2 Aug 2022 19:11:31 +0300 Subject: [PATCH 0192/1892] Added Avro --- data_ingestion/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index fae7824c7..c11d47faa 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -14,5 +14,6 @@ The **Data Ingestion Sources** provides information about the following: csv parquet orc + oracle -For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file +For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file From 53070e875581b3fbf71c51432e28a558ae48798c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 3 Aug 2022 16:14:36 +0300 Subject: [PATCH 0193/1892] Added Table (Jenny's request) --- .../access_control_password_policy.rst | 2 +- .../sql_statements/dml_commands/update.rst | 121 +----------------- releases/2022.1.1.rst | 19 +-- releases/2022.1_index.rst | 54 +++++++- 4 files changed, 57 insertions(+), 139 deletions(-) diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst index 0a17f833e..6d9d989f2 100644 --- a/operational_guides/access_control_password_policy.rst +++ b/operational_guides/access_control_password_policy.rst @@ -1,7 +1,7 @@ .. _access_control_password_policy: ************** -Password Policy (New!) +Password Security Compliance (New!) ************** .. |icon-new_gray_2022.1.1| image:: /_static/images/new_gray_2022.1.1.png diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index b804d6c37..7c1b8c8b8 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -78,31 +78,7 @@ The **Examples** section includes the following examples: .. contents:: :local: :depth: 1 - -Updating an Entire Table ------------------ -The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: - -.. image:: /_static/images/delete_optimization.png - -The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 WHERE true; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; - + Performing Simple Updates ----------------- The following is an example of performing a simple update: @@ -125,87 +101,8 @@ The following shows an example of updating tables that contain multi-table condi AND country.name = 'Sweden' ); -Updating Tables that Contain Multi-Table Conditions using the FROM Clause ------------------ -The following shows an example of updating tables that contain multi-table conditions using the ``FROM`` clause: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + - CASE - WHEN c.name = 'Israel' THEN 2 - ELSE 1 - END - FROM countries c - -You can also write the statement above using the FROM clause: - -.. code-block:: psql - - UPDATE bands - SET records_sold = records_sold + 1 - FROM countries - WHERE countries.id=bands.country_id AND country.name = 'Sweden'; - -Updating Tables that Contain Multi-Table Expressions ------------------ -The following shows an example of updating tables that contain multi-table expressions: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + - CASE - WHEN c.name = 'Israel' THEN 2 - ELSE 1 - END - FROM countries c - -Identifying and Cleaning Up Tables ---------------------------------------- -The following section shows examples of each phase required for cleaning up tables: - -* :ref:`Listing tables that require clean-up` -* :ref:`Identifying clean-up predicates` -* :ref:`Triggering a clean-up` - -.. _listing_tables_that_require_cleanup: - -Listing Tables that Require Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing tables that require clean-up: - -.. code-block:: psql - - farm=> SELECT t.table_name FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - GROUP BY 1; - cool_animals - - 1 row - -.. _identifying_cleanup_predicates: - -Identifying Clean-Up Predicates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following shows an example of listing the clean-up predicates: - -.. code-block:: psql - - farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp - JOIN sqream_catalog.tables t - ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; - weight > 1000 - - 1 row - -.. _triggering_a_cleanup: - Triggering a Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +----------------- The following section shows an example of triggering a clean-up: .. code-block:: psql @@ -220,20 +117,6 @@ The following is an example of the output generated from the above: * **column_id** - 1 * **extent_ID** - 0 -Security and Access Control -============= -Executing an ``UPDATE`` statement requires the following: - -* Both ``UPDATE`` and ``SELECT`` permissions on the target table. - - :: - -* The ``SELECT`` permission for each additional table referenced in the the statement (either in the ``FROM`` clause or in a ``WHERE`` subquery expression). - -For more information, navigate to the **Access Control** page and see `Permissions `_. - -file:///C:/Users/Yaniv/sqream_docs/_build/html/operational_guides/access_control_permissions.html - Locking and Concurrency ============= Executing the ``UPDATE`` statement obtains an exclusive ``UPDATE`` lock on the target table. diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 15fcd8c42..517c11042 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -27,29 +27,22 @@ The 2022.1.1 Release Notes include the following new features: Update Feature ************ -SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. +The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. For more information, see `UPDATE `_. -file:///C:/Users/Yaniv/sqream_docs/_build/html/reference/sql/sql_statements/dml_commands/update.html?highlight=update - -Password Policy +Password Security Compliance ************ In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. -For more information, see `Password Policy `_. - -file:///C:/Users/Yaniv/sqream_docs/_build/html/operational_guides/access_control_password_policy.html?highlight=password%20policy +For more information, see :ref:`access_control_password_policy`. Compression ************ - SQream now supports the **zlib** compression format. For more information, see `Compression `_. -file:///C:/Users/Yaniv/sqream_docs/_build/html/feature_guides/compression.html#compression-strategies - Known Issues --------- The following table lists the known issues for Version 2022.1.1: @@ -69,7 +62,7 @@ The following table lists the issues that were resolved in Version 2022.1.1: +=============+========================================================================================+ | SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | +-------------+----------------------------------------------------------------------------------------+ -| SQ-10955 | No metadata filters were applied when filtering by a nullable date using ``dateadd``. | +| SQ-10892 | An unclear message was displayed when users ran ``UPDATE`` on foreign tables. | +-------------+----------------------------------------------------------------------------------------+ Operations and Configuration Changes @@ -78,8 +71,6 @@ The ``login_max_retries`` configuration flag is required for adjusting the permi For more information, see `Adjusting the Permitted Log-In Attempts `_. -https://docs.sqream.com/en/latest/configuration_guides/login_max_retries.html - Naming Changes ------- No relevant naming changes were made. @@ -133,4 +124,4 @@ Upgrading to v2022.1.1 :glob: :hidden: - 2022.1.1.1 \ No newline at end of file + 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 628b372aa..76d9e0e7c 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -5,13 +5,57 @@ Release Notes 2022.1 ************************** The 2022.1 Release Notes describe the following releases: -.. contents:: - :local: - :depth: 1 - .. toctree:: :maxdepth: 1 :glob: 2022.1.1 - 2022.1 \ No newline at end of file + 2022.1 + +You can also use the following tables for a summary of the new features in Version 2022.1 according to month: + +.. contents:: + :local: + :depth: 1 + +August 2022 +================== +The following enhancements were introduced in :ref:`August 2022 (2022.1.1) <2022.1.1>`: + +.. list-table:: + :widths: 20 20 60 + :header-rows: 1 + + * - Topic + - Feature + - Description + * - **Reference Guides** + - :ref:`update` + - The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. + * - **Feature Guides** + - :ref:`compression` + - SQream supports compressing and decompressing data in and from the **ZLIB** format. + * - **Operational Guides** + - :ref:`Password Security Compliance` + - Integrated password security compliance measures when logging in to the CLI or Studio. + +July 2022 +================== +The following enhancements were introduced in :ref:`July 2022 (2022.1) <2022.1>`: + +.. list-table:: + :widths: 20 20 60 + :header-rows: 1 + + * - Topic + - Feature + - Description + * - **Feature Guides** + - :ref:`data_encryption` + - SQream has integrated data encryption mechanisms in accordance with General Data Protection Regulation (GDPR) standards. + * - **Data Ingestion** + - :ref:`avro` + - SSQream now supports ingesting data from Avro files. + * - **Reference Guides** + - :ref:`update` + - Supports modifying the value of certain columns in existing rows. \ No newline at end of file From c718d0ad427faced59301553fcf3c46a3c41692c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 3 Aug 2022 16:37:13 +0300 Subject: [PATCH 0194/1892] Modified tables --- .../sql/sql_statements/dml_commands/update.rst | 2 +- releases/2022.1_index.rst | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 7c1b8c8b8..6cc33f516 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -89,7 +89,7 @@ The following is an example of performing a simple update: Updating Tables that Contain Multi-Table Conditions ----------------- -The following shows an example of updating tables that contain multi-table conditions: +The following shows an example of updating tables that contain multi-table conditions |icon-new_2022.1.1|: .. code-block:: postgres diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 76d9e0e7c..16a7d80ef 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -23,21 +23,21 @@ August 2022 The following enhancements were introduced in :ref:`August 2022 (2022.1.1) <2022.1.1>`: .. list-table:: - :widths: 20 20 60 + :widths: 24 25 60 :header-rows: 1 * - Topic - Feature - Description - * - **Reference Guides** - - :ref:`update` - - The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. * - **Feature Guides** - :ref:`compression` - SQream supports compressing and decompressing data in and from the **ZLIB** format. * - **Operational Guides** - :ref:`Password Security Compliance` - Integrated password security compliance measures when logging in to the CLI or Studio. + * - **Reference Guides** + - :ref:`update` + - The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. July 2022 ================== @@ -50,12 +50,12 @@ The following enhancements were introduced in :ref:`July 2022 (2022.1) <2022.1>` * - Topic - Feature - Description + * - **Data Ingestion** + - :ref:`avro` + - SQream now supports ingesting data from Avro files. * - **Feature Guides** - :ref:`data_encryption` - SQream has integrated data encryption mechanisms in accordance with General Data Protection Regulation (GDPR) standards. - * - **Data Ingestion** - - :ref:`avro` - - SSQream now supports ingesting data from Avro files. * - **Reference Guides** - - :ref:`update` - - Supports modifying the value of certain columns in existing rows. \ No newline at end of file + - `UPDATE `_ + - The DML ``UPDATE`` statement has been introduced to support modifying the value of certain columns in existing rows. \ No newline at end of file From 08682c571b81bdd8c80b90869a4d79f7770fbcb6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 11:27:08 +0300 Subject: [PATCH 0195/1892] Updated menu --- feature_guides/data_encryption.rst | 3 ++- .../data_encryption_permissions.rst | 6 +++++ feature_guides/data_encryption_syntax.rst | 2 -- .../access_control_password_policy.rst | 24 +++++++++++++------ 4 files changed, 25 insertions(+), 10 deletions(-) create mode 100644 feature_guides/data_encryption_permissions.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index dbc6152ed..19aabb8e3 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -16,4 +16,5 @@ The **Data Encryption** page |icon-new_2022.1| describes the following: data_encryption_overview data_encryption_methods data_encryption_types - data_encryption_syntax \ No newline at end of file + data_encryption_syntax + data_encryption_permissions \ No newline at end of file diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst new file mode 100644 index 000000000..ba51f2501 --- /dev/null +++ b/feature_guides/data_encryption_permissions.rst @@ -0,0 +1,6 @@ +.. _data_encryption_permissions: + +*********************** +Permissions +*********************** +Because the Data Encryption feature does not require a role, users with **Read** and **Insert** permissions can read tables containing encrypted data. \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index bba431aec..56934378e 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -25,8 +25,6 @@ The following is an example of encrypting a new table: .. note:: Because encryption is not associated with any role, users with **Read** or **Insert** permissions can read tables containing encrypted data. -.. warning:: Your performance degradation increases in correlation with the amount of added columns. - You cannot encrypt more than three columns. Attempting to encrypt more than three columns displays the following error message: .. code-block:: console diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst index 6d9d989f2..fc845ebc4 100644 --- a/operational_guides/access_control_password_policy.rst +++ b/operational_guides/access_control_password_policy.rst @@ -8,27 +8,37 @@ Password Security Compliance (New!) :align: middle :width: 110 -As part of our compliance with GDPR standards |icon-new_gray_2022.1.1| SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: +As part of our compliance with GDPR standards |icon-new_gray_2022.1.1| SQream relies on a strong password policy when accessing the CLI or Studio. + +The following requirements apply when creating a password: * At least eight characters long. :: -* Mandatory upper and lowercase letters. +* At least one numeric character. :: -* At least one numeric character. +* Should not include a username. :: -* May not include a username. +* Must include at least one special character, such as **?**, **!**, **$**, etc. :: -* Must include at least one special character, such as **?**, **!**, **$**, etc. +* Mandatory upper and lowercase letters. + +The following is the syntax for creating a password: + +.. code-block:: console + + CREATE ROLE ; + GRANT LOGIN ; + GRANT PASSWORD <'password'> to ; -You can create a password through the Studio graphic interface or through the CLI, as in the following example command: +The following is an example of creating a password: .. code-block:: console @@ -52,7 +62,7 @@ Creating a password that does not comply with the above requirements generates t * Must include at least one “special” character (?, !, $, etc.). -.. note:: When a new user created in Studio, a message is displayed to help you determine what the constraints are. +.. note:: When a new user is created in Studio, a message is displayed to help you determine what the constraints are. Unsuccessfully attempting to log in three times displays the following message: From abc2245f25a0219ad6186d052b436001a5c798a6 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 13:58:14 +0300 Subject: [PATCH 0196/1892] Changed 5.4.3 to 5.4.6 --- index.rst | 2 +- reference/sql/sql_statements/index.rst | 2 + .../utility_commands/shutdown_server.rst | 115 ++ sqream_studio_5.4.3/Version_5.3.3.txt | 898 ---------------- .../configuring_your_instance_of_sqream.rst | 44 +- ...ing_and_managing_roles_and_permissions.rst | 196 ++-- ...ts_and_running_queries_from_the_editor.rst | 984 +++++++++--------- .../getting_started.rst | 126 +-- .../index.rst | 36 +- ...orkers_and_services_from_the_dashboard.rst | 530 +++++----- .../viewing_logs.rst | 244 ++--- 11 files changed, 1200 insertions(+), 1977 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/shutdown_server.rst delete mode 100644 sqream_studio_5.4.3/Version_5.3.3.txt rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/configuring_your_instance_of_sqream.rst (98%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/creating_assigning_and_managing_roles_and_permissions.rst (95%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/executing_statements_and_running_queries_from_the_editor.rst (92%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/getting_started.rst (92%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/index.rst (88%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/monitoring_workers_and_services_from_the_dashboard.rst (90%) rename {sqream_studio_5.4.3 => sqream_studio_5.4.6}/viewing_logs.rst (85%) diff --git a/index.rst b/index.rst index 0f418c2fb..23e2288c0 100644 --- a/index.rst +++ b/index.rst @@ -104,7 +104,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu loading_and_unloading_data/index feature_guides/index operational_guides/index - sqream_studio_5.4.3/index + sqream_studio_5.4.6/index architecture/index configuration_guides/index reference/index diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index d2b92b152..5cac43122 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -130,6 +130,8 @@ The following table shows the Utility commands: - Returns a list of active sessions across the cluster * - :ref:`SHOW VERSION` - Returns the system version for SQream DB + * - :ref:`SHUTDOWN SERVER` + - Performs a graceful server shutdown * - :ref:`STOP STATEMENT` - Stops or aborts an active statement diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst new file mode 100644 index 000000000..ac0c4dc96 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/shutdown_server.rst @@ -0,0 +1,115 @@ +.. _shutdown_server: + +******************** +SHUTDOWN SERVER +******************** +**Comment** - When finished, add command to Utility Commands > shutdown_server. + +The **SHUTDOWN_SERVER** guide describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=============== +SQream's current method for stopping the SQream server is running the ``shutdown_server ()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown, giving you more control over the following: + +* Preventing new queries from connecting to the server. + + :: + +* The amount of time to wait before shutting down the server. + + :: + +* Configurations related to shutting down the server. + +How Does it Work? +======================== +Running the ``SHUTDOWN_SERVER`` command does the following: + +* Prevents new queries from entering the server by doing the following: + + * Setting the SQream server to unavailable in the metadata server. **Comment** - *Is "unavailable" the official server setting?* + + :: + + * Unsubscribing the server from its service. + +* Preventing new connections from being made to the server - attempting to establish a connection with the server after initiating a graceful shutdown displays the "Server is shutting down, no new connections are possible at the moment" messsge. + + :: + +* Waiting for the statement queue to be cleared - the graceful shutdown waits for queries that have been compiled on the server to be cleared from the statement queue. During this time - start executing on other available servers. + +**Comment** - *The last bullet requires clarification.* + +Syntax +========== +The following is the syntax for using the ``SHUTDOWN_SERVER`` command: + +.. code-block:: postgres + + select shutdown_server([is_graceful, [timeout]]); + +**Comment** - *Is the below syntax correct?* + +.. code-block:: postgres + + select shutdown_server([true/false, [timeout]]); + +**Comment** - *Can you set the timeout as a flag in Studio, or only in the CLI?* + +Returns +========== +Running the ``shutdown_server`` command returns no output. + +Parameters +============ +The following table shows the ``shutdown_server`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Example + - Default + * - ``is_graceful`` + - Determines the method used to shut down the server. + - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. + - **Comment** - Is the default ``true`` or ``false``? + * - ``timeout`` + - Sets the maximum amount of minutes for the graceful shutdown method to run before the server is shut down using the standard method. + - ``30`` + - Five minutes. + +.. note:: Setting ``is_graceful`` to ``false`` and defining the ``timeout`` value shuts the server down mid-query after the defined time. + +It is possible to pass as the second argument the timeout in minutes after which a forceful shutdown will run, regardless of the progression of the graceful shutdown. + +**Comment** - *How can the above be true given the following, "Note that running forced shutdown with a timeout, i.e. select shutdown_server(false, 30) will return an error message; forced shutdown has no timeout timer"?* + +Note that you set the timeout value using the ``defaultGracefulShutdownTimeoutMinutes`` flag in Studio. + +For more information, see :ref:`graceful_shutdown`. + +**Comment** - *I have not yet created the ``graceful_shutdown`` configuration flag. I need to know what category it belongs in before doing so.* + +Like shutdown_server() graceful shutdown will stop any query currently running on the server. + +**Comment** - *The above makes it seem like it's a separate command, but that's not the case.* + +Relationship to Healer & Use Case +============================ +**Comment** - *Cannot document this section until I know what the Healer actually does.* + +Currently the Healer will not trigger a graceful shutdown upon detection of a stuck query. It will however log detection of such a query, prompting the user to run a graceful shutdown of the server, possibly saving existing queued queries. + +Permissions +============= +Using the ``shutdown_server`` command requires no special permissions. + +**Comment** - *Confirm.* \ No newline at end of file diff --git a/sqream_studio_5.4.3/Version_5.3.3.txt b/sqream_studio_5.4.3/Version_5.3.3.txt deleted file mode 100644 index 458302aad..000000000 --- a/sqream_studio_5.4.3/Version_5.3.3.txt +++ /dev/null @@ -1,898 +0,0 @@ -.. _acceleration_studio_version_5.3.3: - -**************************** -SQream Acceleration Studio 5.3.3 -**************************** - -The SQream Studio is a web-based client for use with SQream DB. The Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream DB clusters. - - -.. contents:: This page describes the following: - :depth: 3 - -Getting Started -================== - -.. _setting_up_and_starting_studio: - - -Setting Up and Starting Studio ----------------- - -Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. - - - - - - - -Logging In to Studio ---------------- -**To log in to SQream Studio:** - -1. Open a browser to the host on **port 8080**. - - For example, if your machine IP address is ``192.168.0.100``, insert the IP address into the browser as shown below: - - .. code-block:: console - - $ http://192.168.0.100:8080 - -2. Fill in your SQream DB login credentials. These are the same credentials used for `SQream CLI Reference `_ or JDBC. - - When you sign in, the License Warning is displayed. - -Navigating Studio's Main Features -------------- -When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. - -From here you can navigate between the main areas of the Studio: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Dashboard` - - Only users with **superuser** permissions have access to the Dashboard. - * - :ref:`Editor` - - All users have access to the Editor and to databases that they have permissions for. - * - :ref:`Logs` - - Only users with the **superuser** permissions have access to the logs. - * - :ref:`Roles` - - Lets you create users and manage user permissions. - -By clicking the user icon, you can also use it for logging out and viewing the following: - -* User information -* Connection type -* SQream version -* SQream Studio version -* Data size limitations -* Log out - - - -.. _back_to_dashboard: - -.. _studio_dashboard: - -Monitoring Workers and Services from the Dashboard -============================== -The **Dashboard** is used for the following: - -* Monitoring cluster storage and system health. -* Viewing, monitoring, and adding defined service queues. -* Viewing and managing worker status and add workers. - -You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. - -The following is a brief description of the Dashboard panels: - -.. list-table:: - :widths: 10 25 65 - :header-rows: 1 - - * - No. - - Element - - Description - * - 1 - - :ref:`Data Storage panel` - - Used to monitor cluster storage. - * - 2 - - :ref:`Services panel` - - Used for viewing and monitoring the defined `service queues `_. - * - 3 - - :ref:`Workers panel` - - Monitors system health and shows each Sqreamd worker running in the cluster. - * - 4 - - :ref:`License information` - - Shows the remaining amount of days left on your license. - - -.. _data_storage_panel: - -Displaying System Disk Usage from the Data Storage Panel ------------------------ -The **Data Storage** area displays your system's total disk usage (percentage) and data storage (donut graph). - -Your data storage is shows as the following four components: - -* **Data** – Storage occupied by databases in SQream DB. -* **Free** – Free storage space. -* **Deleted** – Storage that is temporarily occupied, but has not been reclaimed. For more information, see `Deleting Data `_. The **deleted** value is estimated and may not be accurate. -* **Other** – Storage used by other applications. On a dedicated SQream DB cluster this should be near zero. - -.. _administration_storage_database: - -You can show more information by clicking the expand arrow on the Data Storage panel. - -.. image:: /_static/images/studio_dashboard_expand_data_storage_5.3.0.png - -The expanded Data Storage panel can be used to drill down into each database's storage footprint, and displays a breakdown of how much storage each database in the cluster uses. - -The database information is displayed in a table and shows the following: - -* **Database name** - the name of the database. -* **Raw Size** – the estimated size of (uncompressed) raw data in the database. -* **Storage Size** – the physical size of the compressed data. -* **Ratio** – the effective compression ratio -* **Deleted Data** – Storage that is temporarily occupied, but has not been reclaimed. - -Below the table, an interactive line graph displays the database storage trends. By default, the line graph displays the total storage for all databases. You can show a particular database's graph by clicking it in the table. You can also change the line graph's timespan by selecting one from the timespan dropdown menu. - -.. image:: /_static/images/studio_dashboard_expand_data_storage_3_5.3.0.png - -:ref:`Back to Dashboard` - -.. _services_panel: - -Subscribing to Workers from the Services Panel --------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. - -.. image:: /_static/images/studio_dashboard_services_panel_5.3.0.png - -The Dashboard includes the four panes shown below: - -.. image:: /_static/images/studio_dashboard_service_queue_5.3.0.png - -The following is a brief description of each pane: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - No. - - Description - * - 1 - - Adds a worker to the selected service. - * - 2 - - Shows the service name. - * - 3 - - Shows a trend graph of queued statements loaded over time. - * - 4 - - Adds a service. - * - 5 - - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). - -Adding A Service -^^^^^^^^^^^^^^^^^^^^^ -You can add a service by clicking **+ Add** and defining the service name. - -.. note:: If you do not associate a worker with the new service, it will not be created. - -You can manage workers from the **Workers** panel. For more information on managing workers, see :ref:`Workers`. - -:ref:`Back to Dashboard` - -.. _workers_panel: - -Managing Workers from the Workers Panel ------------- -From the **Workers** panel you can do the following: - -* :ref:`View workers ` -* :ref:`Add a worker to a service` -* :ref:`View a worker's active query information` -* :ref:`View a worker's execution plan` - -.. _view_workers: - -Viewing Workers -^^^^^^^^ -The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. - -From the **Scale** dropdown menu you can set the time scale of the displayed information -You can hover over segments in the status bar to see the date and time corresponding to each activity type: - -* **Idle** – the worker is idle and available for statements. -* **Compiling** – the worker is compiling a statement and is preparing for execution. -* **Executing** – the worker is executing a statement after compilation. -* **Stopped** – the worker was stopped (either deliberately or due to an error). -* **Waiting** – the worker was waiting on an object locked by another worker. - -.. _add_worker_to_service: - -Adding A Worker to A Service -^^^^^^^^^^^^^^^^^^^^^ -You can add a worker to a service by clicking the **add** button. - -.. image:: /_static/images/studio_dashboard_add_worker_to_service_5.3.0.png - -Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. - - -.. _view_worker_query_information: - -Viewing A Worker's Active Query Information -^^^^^^^^^^^^^^^^^^^^^ -You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. - - -Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. - -Viewing A Worker's Host Utilization -^^^^^^^^^^^^^^^^^^^^^ - -While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. - -.. image:: /_static/images/studio_dashboard_show_cpu_gpu_graph_5.3.0.png - -The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. - -Error notifications related to statements are displayed as shown in the figure below, and you can hover over them for more information about the error. - -.. image:: /_static/images/studio_dashboard_notification_error_5.3.0.png - -.. _view_worker_execution_plan: - -Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^ - -Clicking the ellipsis in a service shows the following additional options: - -* **Stop Query** - stops the query. -* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. - -For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Managing Worker Status -^^^^^^^^^^^^^^^^^^^^^ - -In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. - -.. image:: /_static/images/stop_restart_worker.png - -Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. - - - - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle - -:ref:`Back to Dashboard` - - - -.. _license_information: - -License Information ----------------------- -The license information is a counter showing the amount of time in days remaining on the license. - -:ref:`Back to Dashboard` - - -.. _studio_editor: - -.. _editor_top: - -Executing Statements and Running Queries from the Editor -================= -The **Editor** is used for the following: - -* Selecting an active database and executing queries. -* Performing statement-related operations and showing metadata. -* Executing pre-defined queries. -* Writing queries and statements and viewing query results. - -The following is a brief description of the Editor panels: - - -.. list-table:: - :widths: 10 34 56 - :header-rows: 1 - - * - No. - - Element - - Description - * - 1 - - :ref:`Toolbar` - - Used to select the active database you want to work on, limit the number of rows, save query, etc. - * - 2 - - :ref:`Database Tree and System Queries panel` - - Shows a heirarchy tree of databases, views, tables, and columns - * - 3 - - :ref:`Statement panel` - - Used for writing queries and statements - * - 4 - - :ref:`Results panel` - - Shows query results and execution information. - - -.. _studio_editor_db_tree: - -.. _top: - -.. _studio_editor_toolbar: - -Executing Statements from the Toolbar -------------- - -The following figure shows the **Toolbar** pane: - -.. image:: /_static/images/studio_editor_toolbar_5.3.0.png - -You can access the following from the Toolbar pane: - -* **Database dropdown list** - select a database that you want to run statements on. - -* **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. - -* **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: - - * **Statements** - executes the statement at the location of the cursor. - * **Selected** - executes only the highlighted text. This mode should be used when executing subqueries or sections of large queries (as long as they are valid SQLs). - * **All** - executes all statements in a selected tab. - -For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. - -* **Format SQL** - Lets you reformat and reindent statements. - -* **Download query** - Lets you download query text to your computer. - -* **Open query** - Lets you upload query text from your computer. - -* **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. - -:ref:`Back to Editor` - -Performing Statement-Related Operations from the Database Tree ---------------- -From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). - -The following figure shows the **Database Tree** and **System Queries** panel, with the Database Tree tab selected. - -.. image:: /_static/images/studio_database_tree_system_queries_panel_5053.png - -The following figure shows the database object functions in the **calcs** table object. - -.. image:: /_static/images/studio_database_object_operations_5030.png - -The database object functions are used to perform the following: - - - * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. - * The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. - * The **additional operations** |icon-dots| - displays the following additional options: - - - - - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Function - - Description - * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. - * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. - * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. - * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. - * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. - * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. - * - Drop table statement - - Generates a ``DROP`` statement for the selected object in the editing area. - * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See also `Seeing System Objects as DDL `_. - * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. - - - - - -Optimizing Database Tables Using the DDL Optimizer -^^^^^^^^^^^^^^^^^^^^^ -The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. - -As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. - -The following table describes the DDL Optimizer screen: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Element - - Description - * - Column area - - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. - * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``VARCHAR`` fields), and the default percent buffer to add to ``VARCHAR`` lengths (10%). Attempts to determine field nullability. - * - Run Optimizer - - Starts the optimization process. - -Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. The figure below shows the **calcs Optimized** tab for the optimized **calcs** table. - -For more information, see `Optimization and Best Practices `_. - -:ref:`Back to top` - -Executing Pre-Defined Queries from the System Queries Panel ---------------- -The **System Queries** panel lets you execute pre-defined queries and includes the following system query types: - -* **Catalog queries** - used for analyzing table compression rates, users and permissions, etc. -* **Admin queries** - queries related to available (describe the functionality in a general way). Queries useful for SQream database management: - - - - - -Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. - - -.. _studio_editor_statement_area: - -Writing Statements and Queries from the Statement Panel ----------------- -The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completing. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. - -The following table shows the statement statuses: - -.. list-table:: - :widths: 45 160 - :header-rows: 1 - - * - Status - - Description - * - Pending - - The statement is pending. - * - In queue - - The statement is waiting for execution. - * - Initializing - - The statement has entered execution checks. - * - Executing - - The statement is executing. - * - Statement stopped - - The statement has been stopped. - -You can add and name new tabs for each statement that you need to execute, and Studio preserves your created tabs when you switch between databases. You can add new tabs by clicking |icon-plus| , which creates a new tab to the right with a default name of SQL and an increasing number. This helps you keep track of your statements. - -.. image:: /_static/images/statement_pane_adding_statement_5.3.0.png - -You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. - -.. tip:: If this is your first time using SQream, see `First steps with SQream DB `_. - - -.. Keyboard shortcuts -.. ^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. - -.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword - -.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. - -.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab - -.. _studio_editor_results: - -:ref:`Back to Editor` - - -Viewing Statement and Query Results from the Results Panel ------------------------------------- -The results pane shows statment and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. - -.. image:: /_static/images/studio_editor_results_5053.png - -By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. - -The following is a brief description of the elements on the Results panel views: - -.. list-table:: - :widths: 45 160 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Results view` - - Lets you view search query results. - * - :ref:`Execution Details view` - - Lets you view execution details, such as statement ID, number of rows, and averge number of rows in chunk. - * - :ref:`SQL view` - - Lets you see the SQL view. - * - :ref:`Save results to clipboard` - - Lets you save your search results to the clipboard to paste into another text editor. - * - :ref:`Save results to local file` - - Lets you save your search query results to a local file. - -.. _results_view: - - - -Searching Query Results in the Results View -^^^^^^^^^^^^ -The **Results view** lets you view search query results. - -From this view you can also do the following: - -* View the amount of time (in seconds) taken for a query to finish executing. -* Switch and scroll between tabs. -* Close all tabs at once. -* Enable keeping tabs by selecting **Keep tabs**. -* Sort column results. - -In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. - -.. _running_parallel_statements: - -Running Parallel Statements -^^^^^^^^^^^^ -While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. - -The following shows the syntax for running parallel statements: - -.. code-block:: console - - $ @@ parallel - $ $$ - $ select 1; - $ select 2; - $ select 3; - $ $$ - -The following figure shows the parallel statement syntax in the Editor: - -.. image:: /_static/images/running_parallel_statements.png - -.. _execution_details_view: - -Execution Details View -^^^^^^^^^^^^ -The **Execution Details** view lets you view a query’s execution plan for monitoring purposes. Most importantly, the Execution Details view highlights rows based on how long they ran relative to the entire query. - -This can be seen in the **timeSum** column as follows: - -* **Rows highlighted red** - longest runtime -* **Rows highlighted orange** - medium runtime -* **Rows highlighted yellow** - shortest runtime - -.. image:: /_static/images/execution_details_view_3.png - - - -.. _sql_view: - -Viewing Wrapped Strings in the SQL View -^^^^^^^^^^^^ -The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuititively structured snapshot of it. - -The following figure shows the SQL view: - -.. image:: /_static/images/sql_view_5.0.3.png - -.. _save_results_to_clipboard: - -Saving Results to the Clipboard -^^^^^^^^^^^^ -The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. - - -.. _save_results_to_local_file: - -Saving Results to a Local File -^^^^^^^^^^^^ -The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. - -Analyzing Results ----------------------------- - -When results are produced, a **Generate CREATE statement** button is displayed. Clicking this button creates a new tab with an optimized :ref:`create_table` statement, and an :ref:`insert` statement to copy the data to the new table. - -.. _logs: - -.. _logs_top: - -:ref:`Back to Editor` - -Viewing Logs -============ -The **Logs** screen is used for viewing logs and includes the following elements: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Filter area` - - Lets you filter the data shown in the table. - * - :ref:`Query tab` - - Shows basic query information logs, such as query number and the time the query was run. - * - :ref:`Session tab` - - Shows basic session information logs, such as session ID and user name. - * - :ref:`System tab` - - Shows all system logs. - * - :ref:`Log lines tab` - - Shows the total amount of log lines. - - -.. _filter: - -Filtering Table Data -------------- -From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). - - -Some filters require you to type text to define the filter. - -.. image:: /_static/images/logs_filters_5.3.0.png - -Other filters require you to select an item from a dropdown menu: - -* INFO -* WARNING -* ERROR -* FATAL -* SYSTEM - -You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. - -.. _queries: - -:ref:`Back to Viewing Logs` - - -Viewing Query Logs ----------- -The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. - -From the Queries area you can see and sort by the following: - -* Query ID -* Start time -* Query -* Compilation duration -* Execution duration -* Total duration -* Details (execution details, error details, successful query details) - -In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. - -:ref:`Back to Viewing Logs` - -.. _sessions: - -Viewing Session Logs ----------- -The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. - -From here you can see and sort by the following: - -* Timestamp -* Connection ID -* Username -* Client IP -* Login (Success or Failed) -* Duration (of session) -* Configuration Changes - -In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. - -:ref:`Back to Viewing Logs` - -.. _system: - -Viewing System Logs ----------- -The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. - -From here you can see and sort by the following: - -* Timestamp -* Log type -* Message - -In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. - -:ref:`Back to Viewing Logs` - -.. _log_lines: - -Viewing All Log Lines ----------- -The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. - -From here you can see and sort by the following: - -* Timestamp -* Message level -* Worker hostname -* Worker port -* Connection ID -* Database name -* User name -* Statement ID - -In the **LOG LINES** table, you can click on any of the items to set them as your filters. - -:ref:`Back to Viewing Logs` - -:ref:`Back to Editor` - -.. _roles: - -Creating, Assigning, and Managing Roles and Permissions -============ -Overview ---------------- -In the **Roles** area you can create and assign roles and manage user permissions. - -The **Type** column displays one of the following assigned role types: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Role Type - - Description - * - Groups - - Roles with no users. - * - Enabled users - - Users with log-in permissions and a password. - * - Disabled users - - Users with log-in permissions and with a disabled password. An admin may disable a user's password permissions to temporary disable access to the system. - -.. note:: If you disable a password, when you enable it you have to create a new one. - - -Viewing Information About a Role --------------------- -Clicking a role in the roles table displays the following information: - - * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. - * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. - * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. - -Creating a New Role --------------------- -You can create a new role by clicking **New Role**. - -.. image:: /_static/images/role_button.png - -An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. - -Clicking **New Role** lets you do the following: - - * Add and assign a role name (required) - * Enable or disable log-in permissions for the role. - * Set a password. - * Assign or delete parent roles. - * Add or delete permissions. - * Grant the selected user with superuser permissions. - -From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. - -When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. - -Editing a Role --------------------- -Once you've created a role, clicking the **Edit Role** button lets you do the following: - - * Edit the role name. - * Enable or disable log-in permissions. - * Set a password. - * Assign or delete parent roles. - * Assign a role **administrator** permissions. - * Add or delete permissions. - * Grant the selected user with superuser permissions. - -From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. - -Deleting a Role ------------------ -Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. diff --git a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst similarity index 98% rename from sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst rename to sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst index e5f4b11e5..2b334cbfa 100644 --- a/sqream_studio_5.4.3/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst @@ -1,23 +1,23 @@ -.. _configuring_your_instance_of_sqream: - -**************************** -Configuring Your Instance of SQream -**************************** -The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. - -Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. -Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. - -Editing Your Parameters -------------------------------- -When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. - -Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. - -You can hover over the **information** icon located on each parameter to read a short description of its behavior. - -Exporting and Importing Configuration Files -------------------------- -You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. - +.. _configuring_your_instance_of_sqream: + +**************************** +Configuring Your Instance of SQream +**************************** +The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. + +Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. +Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. + +Editing Your Parameters +------------------------------- +When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. + +Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. + +You can hover over the **information** icon located on each parameter to read a short description of its behavior. + +Exporting and Importing Configuration Files +------------------------- +You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. + For more information about configuring your instance of SQream, see `Configuration Guides `_. \ No newline at end of file diff --git a/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst similarity index 95% rename from sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst rename to sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst index 325563761..b87b6f2cf 100644 --- a/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst @@ -1,98 +1,98 @@ -.. _creating_assigning_and_managing_roles_and_permissions: - -.. _roles_5.4.3: - -**************************** -Creating, Assigning, and Managing Roles and Permissions -**************************** -The **Creating, Assigning, and Managing Roles and Permissions** describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview ---------------- -In the **Roles** area you can create and assign roles and manage user permissions. - -The **Type** column displays one of the following assigned role types: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Role Type - - Description - * - Groups - - Roles with no users. - * - Enabled users - - Users with log-in permissions and a password. - * - Disabled users - - Users with log-in permissions and with a disabled password. An admin may disable a user's password permissions to temporary disable access to the system. - -.. note:: If you disable a password, when you enable it you have to create a new one. - -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` - - -Viewing Information About a Role --------------------- -Clicking a role in the roles table displays the following information: - - * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. - - :: - - * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. - - :: - - * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. - -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` - - -Creating a New Role --------------------- -You can create a new role by clicking **New Role**. - - - -An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. - -Clicking **New Role** lets you do the following: - - * Add and assign a role name (required) - * Enable or disable log-in permissions for the role. - * Set a password. - * Assign or delete parent roles. - * Add or delete permissions. - * Grant the selected user with superuser permissions. - -From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. - -When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. - -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` - -Editing a Role --------------------- -Once you've created a role, clicking the **Edit Role** button lets you do the following: - - * Edit the role name. - * Enable or disable log-in permissions. - * Set a password. - * Assign or delete parent roles. - * Assign a role **administrator** permissions. - * Add or delete permissions. - * Grant the selected user with superuser permissions. - -From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. - -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` - -Deleting a Role ------------------ -Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. - -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file +.. _creating_assigning_and_managing_roles_and_permissions: + +.. _roles_5.4.6: + +**************************** +Creating, Assigning, and Managing Roles and Permissions +**************************** +The **Creating, Assigning, and Managing Roles and Permissions** describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +--------------- +In the **Roles** area you can create and assign roles and manage user permissions. + +The **Type** column displays one of the following assigned role types: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Role Type + - Description + * - Groups + - Roles with no users. + * - Enabled users + - Users with log-in permissions and a password. + * - Disabled users + - Users with log-in permissions and with a disabled password. An admin may disable a user's password permissions to temporary disable access to the system. + +.. note:: If you disable a password, when you enable it you have to create a new one. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + + +Viewing Information About a Role +-------------------- +Clicking a role in the roles table displays the following information: + + * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. + + :: + + * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. + + :: + + * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + + +Creating a New Role +-------------------- +You can create a new role by clicking **New Role**. + + + +An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. + +Clicking **New Role** lets you do the following: + + * Add and assign a role name (required) + * Enable or disable log-in permissions for the role. + * Set a password. + * Assign or delete parent roles. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + +Editing a Role +-------------------- +Once you've created a role, clicking the **Edit Role** button lets you do the following: + + * Edit the role name. + * Enable or disable log-in permissions. + * Set a password. + * Assign or delete parent roles. + * Assign a role **administrator** permissions. + * Add or delete permissions. + * Grant the selected user with superuser permissions. + +From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` + +Deleting a Role +----------------- +Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. + +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file diff --git a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst similarity index 92% rename from sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst rename to sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst index e1b6765eb..9640665da 100644 --- a/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst @@ -1,492 +1,492 @@ -.. _executing_statements_and_running_queries_from_the_editor: - -.. _editor_top_5.4.3: - -**************************** -Executing Statements and Running Queries from the Editor -**************************** -The **Editor** is used for the following: - -* Selecting an active database and executing queries. -* Performing statement-related operations and showing metadata. -* Executing pre-defined queries. -* Writing queries and statements and viewing query results. - -The following is a brief description of the Editor panels: - - -.. list-table:: - :widths: 10 34 56 - :header-rows: 1 - - * - No. - - Element - - Description - * - 1 - - :ref:`Toolbar` - - Used to select the active database you want to work on, limit the number of rows, save query, etc. - * - 2 - - :ref:`Database Tree and System Queries panel` - - Shows a hierarchy tree of databases, views, tables, and columns - * - 3 - - :ref:`Statement panel` - - Used for writing queries and statements - * - 4 - - :ref:`Results panel` - - Shows query results and execution information. - - - -.. _top_5.4.3: - -.. _studio_5.4.3_editor_toolbar: - -Executing Statements from the Toolbar -================ -You can access the following from the Toolbar pane: - -* **Database dropdown list** - select a database that you want to run statements on. - - :: - -* **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. - - :: - -* **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: - - * **Statements** - executes the statement at the location of the cursor. - * **Selected** - executes only the highlighted text. This mode should be used when executing subqueries or sections of large queries (as long as they are valid SQLs). - * **All** - executes all statements in a selected tab. - -* **Format SQL** - Lets you reformat and reindent statements. - - :: - -* **Download query** - Lets you download query text to your computer. - - :: - -* **Open query** - Lets you upload query text from your computer. - - :: - -* **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. - - -For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. - -:ref:`Back to Executing Statements and Running Queries from the Editor` - - -.. _studio_5.4.3_editor_db_tree: - -Performing Statement-Related Operations from the Database Tree -================ -From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). - - - - - -The database object functions are used to perform the following: - -* The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. - - :: - -* The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. - - :: - -* The **additional operations** |icon-dots| - displays the following additional options: - - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle - - -.. list-table:: - :widths: 30 70 - :header-rows: 1 - - * - Function - - Description - * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. - * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. - * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. - * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. - * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. - * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. - * - Drop table statement - - Generates a ``DROP`` statement for the selected object in the editing area. - * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. - * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. - -Optimizing Database Tables Using the DDL Optimizer ------------------------ -The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. - -As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. - -The following table describes the DDL Optimizer screen: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Element - - Description - * - Column area - - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. - * - Optimization area - - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. - * - Run Optimizer - - Starts the optimization process. - -Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. - -For more information, see `Optimization and Best Practices `_. - -Executing Pre-Defined Queries from the System Queries Panel ---------------- -The **System Queries** panel lets you execute predefined queries and includes the following system query types: - -* **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. - - :: - -* **Admin queries** - Queries useful for SQream database management. - -Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. - -.. _studio_5.4.3_editor_statement_area: - -Writing Statements and Queries from the Statement Panel -============== -The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completed. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. - -The auto-complete feature assists you when writing statements by suggesting statement options. - -The following table shows the statement statuses: - -.. list-table:: - :widths: 45 160 - :header-rows: 1 - - * - Status - - Description - * - Pending - - The statement is pending. - * - In queue - - The statement is waiting for execution. - * - Initializing - - The statement has entered execution checks. - * - Executing - - The statement is executing. - * - Statement stopped - - The statement has been stopped. - -You can add and name new tabs for each statement that you need to execute, and Studio preserves your created tabs when you switch between databases. You can add new tabs by clicking |icon-plus| , which creates a new tab to the right with a default name of SQL and an increasing number. This helps you keep track of your statements. - -You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. - -.. tip:: If this is your first time using SQream, see `Getting Started `_. - - -.. Keyboard shortcuts -.. ^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. - -.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword - -.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. - -.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab - -.. _studio_editor_results_5.4.3: - -:ref:`Back to Executing Statements and Running Queries from the Editor` - -.. _studio_5.4.3_editor_results: - -.. _results_panel_5.4.3: - -Viewing Statement and Query Results from the Results Panel -============== -The results panel shows statement and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. - -.. image:: /_static/images/results_panel.png - -The following is a brief description of the Results panel views highlighted in the figure above: - -.. list-table:: - :widths: 45 160 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Results view` - - Lets you view search query results. - * - :ref:`Execution Details view` - - Lets you analyze your query for troubleshooting and optimization purposes. - * - :ref:`SQL view` - - Lets you see the SQL view. - - -.. _results_view_5.4.3: - -:ref:`Back to Executing Statements and Running Queries from the Editor` - -Searching Query Results in the Results View ----------------- -The **Results view** lets you view search query results. - -From this view you can also do the following: - -* View the amount of time (in seconds) taken for a query to finish executing. -* Switch and scroll between tabs. -* Close all tabs at once. -* Enable keeping tabs by selecting **Keep tabs**. -* Sort column results. - -Saving Results to the Clipboard -^^^^^^^^^^^^ -The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. - -.. _save_results_to_local_file_5.4.3: - -Saving Results to a Local File -^^^^^^^^^^^^ -The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. - -In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. - -.. _running_parallel_statements_5.4.3: - -Running Parallel Statements -^^^^^^^^^^^^ -While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. - -The following shows the syntax for running parallel statements: - -.. code-block:: console - - $ @@ parallel - $ $$ - $ select 1; - $ select 2; - $ select 3; - $ $$ - - -:ref:`Back to Viewing Statement and Query Results from the Results Panel` - -.. _execution_details_view_5.4.3: - -.. _execution_tree_5.4.3: - -Execution Details View --------------- -The **Execution Details View** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview -^^^^^^^^^^^^ -Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. - -.. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. - -From this screen you can scroll in, out, and around the execution tree with the mouse to analyze all aspects of your query. You can navigate around the execution tree by dragging or by using the mini-map in the bottom right corner. - -.. image:: /_static/images/execution_tree_1.png - -You can also search for query data by pressing **Ctrl+F** or clicking the search icon |icon-search| in the search field in the top right corner and typing text. - -.. image:: /_static/images/search_field.png - -Pressing **Enter** takes you directly to the next result matching your search criteria, and pressing **Shift + Enter** takes you directly to the previous result. You can also search next and previous results using the up and down arrows. - -.. |icon-search| image:: /_static/images/studio_icon_search.png - :align: middle - -The nodes are color-coded based on the following: - -* **Slow nodes** - red -* **In progress nodes** - yellow -* **Completed nodes** - green -* **Pending nodes** - white -* **Currently selected node** - blue -* **Search result node** - purple (in the mini-map) - -The execution tree displays the same information as shown in the plain view in tree format. - -The Execution Tree tracks each phase of your query in real time as a vertical tree of nodes. Each node refers to an operation that occurred on the GPU or CPU. When a phase is completed, the next branch begins to its right until the entire query is complete. Joins are displayed as two parallel branches merged together in a node called **Join**, as shown in the figure above. The nodes are connected by a line indicating the number of rows passed from one node to the next. The width of the line indicates the amount of rows on a logarithmic scale. - -Each node displays a number displaying its **node ID**, its **type**, **table name** (if relevant), **status**, and **runtime**. The nodes are color-coded for easy identification. Green nodes indicate **completed nodes**, yellow indicates **nodes in progress**, and red indicates **slowest nodes**, typically joins, as shown below: - -.. image:: /_static/images/nodes.png - -Viewing Query Statistics -^^^^^^^^^^^^ -The following statistical information is displayed in the top left corner, as shown in the figure above: - -* **Query Statistics**: - - * **Elapsed** - the total time taken for the query to complete. - * **Result rows** - the amount of rows fetched. - * **Running nodes completion** - * **Total query completion** - the amount of the total execution tree that was executed (nodes marked green). - -* **Slowest Nodes** information is displayed in the top right corner in red text. Clicking the slowest node centers automatically on that node in the execution tree. - -You can also view the following **Node Statistics** in the top right corner for each individual node by clicking a node: - -.. list-table:: - :widths: 45 160 - :header-rows: 1 - - * - Element - - Description - * - Node type - - Shows the node type. - * - Status - - Shows the execution status. - * - Time - - The total time taken to execute. - * - Rows - - Shows the number of produced rows passed to the next node. - * - Chunks - - Shows number of produced chunks. - * - Average rows per chunk - - Shows the number of average rows per chunk. - * - Table (for **ReadTable** and joins only) - - Shows the table name. - * - Write (for joins only) - - Shows the total date size written to the disk. - * - Read (for **ReadTable** and joins only) - - Shows the total data size read from the disk. - -Note that you can scroll the Node Statistics table. You can also download the execution plan table in .csv format by clicking the download arrow |icon-download| in the upper-right corner. - -.. |icon-download| image:: /_static/images/studio_icon_download.png - :align: middle - -Using the Plain View -^^^^^^^^^^^^ -You can use the **Plain View** instead of viewing the execution tree by clicking **Plain View** |icon-plain| in the top right corner. The plain view displays the same information as shown in the execution tree in table format. - -.. |icon-plain| image:: /_static/images/studio_icon_plain.png - :align: middle - - - - -The plain view lets you view a query’s execution plan for monitoring purposes and highlights rows based on how long they ran relative to the entire query. - -This can be seen in the **timeSum** column as follows: - -* **Rows highlighted red** - longest runtime -* **Rows highlighted orange** - medium runtime -* **Rows highlighted yellow** - shortest runtime - -:ref:`Back to Viewing Statement and Query Results from the Results Panel` - -.. _sql_view_5.4.3: - -Viewing Wrapped Strings in the SQL View ------------------- -The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. - -.. _save_results_to_clipboard_5.4.3: - -:ref:`Back to Viewing Statement and Query Results from the Results Panel` - -:ref:`Back to Executing Statements and Running Queries from the Editor` +.. _executing_statements_and_running_queries_from_the_editor: + +.. _editor_top_5.4.6: + +**************************** +Executing Statements and Running Queries from the Editor +**************************** +The **Editor** is used for the following: + +* Selecting an active database and executing queries. +* Performing statement-related operations and showing metadata. +* Executing pre-defined queries. +* Writing queries and statements and viewing query results. + +The following is a brief description of the Editor panels: + + +.. list-table:: + :widths: 10 34 56 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Toolbar` + - Used to select the active database you want to work on, limit the number of rows, save query, etc. + * - 2 + - :ref:`Database Tree and System Queries panel` + - Shows a hierarchy tree of databases, views, tables, and columns + * - 3 + - :ref:`Statement panel` + - Used for writing queries and statements + * - 4 + - :ref:`Results panel` + - Shows query results and execution information. + + + +.. _top_5.4.6: + +.. _studio_5.4.6_editor_toolbar: + +Executing Statements from the Toolbar +================ +You can access the following from the Toolbar pane: + +* **Database dropdown list** - select a database that you want to run statements on. + + :: + +* **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. + + :: + +* **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: + + * **Statements** - executes the statement at the location of the cursor. + * **Selected** - executes only the highlighted text. This mode should be used when executing subqueries or sections of large queries (as long as they are valid SQLs). + * **All** - executes all statements in a selected tab. + +* **Format SQL** - Lets you reformat and reindent statements. + + :: + +* **Download query** - Lets you download query text to your computer. + + :: + +* **Open query** - Lets you upload query text from your computer. + + :: + +* **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. + + +For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. + +:ref:`Back to Executing Statements and Running Queries from the Editor` + + +.. _studio_5.4.6_editor_db_tree: + +Performing Statement-Related Operations from the Database Tree +================ +From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). + + + + + +The database object functions are used to perform the following: + +* The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. + + :: + +* The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. + + :: + +* The **additional operations** |icon-dots| - displays the following additional options: + + +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle + +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle + + +.. list-table:: + :widths: 30 70 + :header-rows: 1 + + * - Function + - Description + * - Insert statement + - Generates an `INSERT `_ statement for the selected table in the editing area. + * - Delete statement + - Generates a `DELETE `_ statement for the selected table in the editing area. + * - Create Table As statement + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + * - Rename statement + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + * - Adding column statement + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + * - Truncate table statement + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + * - Drop table statement + - Generates a ``DROP`` statement for the selected object in the editing area. + * - Table DDL + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + * - DDL Optimizer + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + +Optimizing Database Tables Using the DDL Optimizer +----------------------- +The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. + +As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. + +The following table describes the DDL Optimizer screen: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - Column area + - Shows the column **names** and **column types** from the selected table. You can scroll down or to the right/left for long column lists. + * - Optimization area + - Shows the number of rows to sample as the basis for running an optimization, the default setting (1,000,000) when running an optimization (this is also the overhead threshold used when analyzing ``TEXT`` fields), and the default percent buffer to add to ``TEXT`` lengths (10%). Attempts to determine field nullability. + * - Run Optimizer + - Starts the optimization process. + +Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. + +For more information, see `Optimization and Best Practices `_. + +Executing Pre-Defined Queries from the System Queries Panel +--------------- +The **System Queries** panel lets you execute predefined queries and includes the following system query types: + +* **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. + + :: + +* **Admin queries** - Queries useful for SQream database management. + +Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. + +.. _studio_5.4.6_editor_statement_area: + +Writing Statements and Queries from the Statement Panel +============== +The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completed. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. + +The auto-complete feature assists you when writing statements by suggesting statement options. + +The following table shows the statement statuses: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Status + - Description + * - Pending + - The statement is pending. + * - In queue + - The statement is waiting for execution. + * - Initializing + - The statement has entered execution checks. + * - Executing + - The statement is executing. + * - Statement stopped + - The statement has been stopped. + +You can add and name new tabs for each statement that you need to execute, and Studio preserves your created tabs when you switch between databases. You can add new tabs by clicking |icon-plus| , which creates a new tab to the right with a default name of SQL and an increasing number. This helps you keep track of your statements. + +You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. + +.. tip:: If this is your first time using SQream, see `Getting Started `_. + + +.. Keyboard shortcuts +.. ^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. + +.. :kbd:`Ctrl` + :kbd:`Space` - Auto-complete the current keyword + +.. :kbd:`Ctrl` + :kbd:`↑` - Switch to next tab. + +.. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab + +.. _studio_editor_results_5.4.6: + +:ref:`Back to Executing Statements and Running Queries from the Editor` + +.. _studio_5.4.6_editor_results: + +.. _results_panel_5.4.6: + +Viewing Statement and Query Results from the Results Panel +============== +The results panel shows statement and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. + +.. image:: /_static/images/results_panel.png + +The following is a brief description of the Results panel views highlighted in the figure above: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Results view` + - Lets you view search query results. + * - :ref:`Execution Details view` + - Lets you analyze your query for troubleshooting and optimization purposes. + * - :ref:`SQL view` + - Lets you see the SQL view. + + +.. _results_view_5.4.6: + +:ref:`Back to Executing Statements and Running Queries from the Editor` + +Searching Query Results in the Results View +---------------- +The **Results view** lets you view search query results. + +From this view you can also do the following: + +* View the amount of time (in seconds) taken for a query to finish executing. +* Switch and scroll between tabs. +* Close all tabs at once. +* Enable keeping tabs by selecting **Keep tabs**. +* Sort column results. + +Saving Results to the Clipboard +^^^^^^^^^^^^ +The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. + +.. _save_results_to_local_file_5.4.6: + +Saving Results to a Local File +^^^^^^^^^^^^ +The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. + +In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. + +.. _running_parallel_statements_5.4.6: + +Running Parallel Statements +^^^^^^^^^^^^ +While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. + +The following shows the syntax for running parallel statements: + +.. code-block:: console + + $ @@ parallel + $ $$ + $ select 1; + $ select 2; + $ select 3; + $ $$ + + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +.. _execution_details_view_5.4.6: + +.. _execution_tree_5.4.6: + +Execution Details View +-------------- +The **Execution Details View** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +^^^^^^^^^^^^ +Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. + +.. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. + +From this screen you can scroll in, out, and around the execution tree with the mouse to analyze all aspects of your query. You can navigate around the execution tree by dragging or by using the mini-map in the bottom right corner. + +.. image:: /_static/images/execution_tree_1.png + +You can also search for query data by pressing **Ctrl+F** or clicking the search icon |icon-search| in the search field in the top right corner and typing text. + +.. image:: /_static/images/search_field.png + +Pressing **Enter** takes you directly to the next result matching your search criteria, and pressing **Shift + Enter** takes you directly to the previous result. You can also search next and previous results using the up and down arrows. + +.. |icon-search| image:: /_static/images/studio_icon_search.png + :align: middle + +The nodes are color-coded based on the following: + +* **Slow nodes** - red +* **In progress nodes** - yellow +* **Completed nodes** - green +* **Pending nodes** - white +* **Currently selected node** - blue +* **Search result node** - purple (in the mini-map) + +The execution tree displays the same information as shown in the plain view in tree format. + +The Execution Tree tracks each phase of your query in real time as a vertical tree of nodes. Each node refers to an operation that occurred on the GPU or CPU. When a phase is completed, the next branch begins to its right until the entire query is complete. Joins are displayed as two parallel branches merged together in a node called **Join**, as shown in the figure above. The nodes are connected by a line indicating the number of rows passed from one node to the next. The width of the line indicates the amount of rows on a logarithmic scale. + +Each node displays a number displaying its **node ID**, its **type**, **table name** (if relevant), **status**, and **runtime**. The nodes are color-coded for easy identification. Green nodes indicate **completed nodes**, yellow indicates **nodes in progress**, and red indicates **slowest nodes**, typically joins, as shown below: + +.. image:: /_static/images/nodes.png + +Viewing Query Statistics +^^^^^^^^^^^^ +The following statistical information is displayed in the top left corner, as shown in the figure above: + +* **Query Statistics**: + + * **Elapsed** - the total time taken for the query to complete. + * **Result rows** - the amount of rows fetched. + * **Running nodes completion** + * **Total query completion** - the amount of the total execution tree that was executed (nodes marked green). + +* **Slowest Nodes** information is displayed in the top right corner in red text. Clicking the slowest node centers automatically on that node in the execution tree. + +You can also view the following **Node Statistics** in the top right corner for each individual node by clicking a node: + +.. list-table:: + :widths: 45 160 + :header-rows: 1 + + * - Element + - Description + * - Node type + - Shows the node type. + * - Status + - Shows the execution status. + * - Time + - The total time taken to execute. + * - Rows + - Shows the number of produced rows passed to the next node. + * - Chunks + - Shows number of produced chunks. + * - Average rows per chunk + - Shows the number of average rows per chunk. + * - Table (for **ReadTable** and joins only) + - Shows the table name. + * - Write (for joins only) + - Shows the total date size written to the disk. + * - Read (for **ReadTable** and joins only) + - Shows the total data size read from the disk. + +Note that you can scroll the Node Statistics table. You can also download the execution plan table in .csv format by clicking the download arrow |icon-download| in the upper-right corner. + +.. |icon-download| image:: /_static/images/studio_icon_download.png + :align: middle + +Using the Plain View +^^^^^^^^^^^^ +You can use the **Plain View** instead of viewing the execution tree by clicking **Plain View** |icon-plain| in the top right corner. The plain view displays the same information as shown in the execution tree in table format. + +.. |icon-plain| image:: /_static/images/studio_icon_plain.png + :align: middle + + + + +The plain view lets you view a query’s execution plan for monitoring purposes and highlights rows based on how long they ran relative to the entire query. + +This can be seen in the **timeSum** column as follows: + +* **Rows highlighted red** - longest runtime +* **Rows highlighted orange** - medium runtime +* **Rows highlighted yellow** - shortest runtime + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +.. _sql_view_5.4.6: + +Viewing Wrapped Strings in the SQL View +------------------ +The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. + +.. _save_results_to_clipboard_5.4.6: + +:ref:`Back to Viewing Statement and Query Results from the Results Panel` + +:ref:`Back to Executing Statements and Running Queries from the Editor` diff --git a/sqream_studio_5.4.3/getting_started.rst b/sqream_studio_5.4.6/getting_started.rst similarity index 92% rename from sqream_studio_5.4.3/getting_started.rst rename to sqream_studio_5.4.6/getting_started.rst index 3b9644cdc..6b328ae67 100644 --- a/sqream_studio_5.4.3/getting_started.rst +++ b/sqream_studio_5.4.6/getting_started.rst @@ -1,61 +1,65 @@ -.. _getting_started: - -**************************** -Getting Started with SQream Acceleration Studio 5.4.3 -**************************** -Setting Up and Starting Studio ----------------- -Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. - -Logging In to Studio ---------------- -**To log in to SQream Studio:** - -1. Open a browser to the host on **port 8080**. - - For example, if your machine IP address is ``192.168.0.100``, insert the IP address into the browser as shown below: - - .. code-block:: console - - $ http://192.168.0.100:8080 - -2. Fill in your SQream DB login credentials. These are the same credentials used for :ref:`sqream sql` or JDBC. - - When you sign in, the License Warning is displayed. - -Navigating Studio's Main Features -------------- -When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. - -From here you can navigate between the main areas of the Studio: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Dashboard` - - Lets you monitor system health and manage queues and workers. - * - :ref:`Editor` - - Lets you select databases, perform statement operations, and write and execute queries. - * - :ref:`Logs` - - Lets you view usage logs. - * - :ref:`Roles` - - Lets you create users and manage user permissions. - * - :ref:`Configuration` - - Lets you configure your instance of SQream. - -By clicking the user icon, you can also use it for logging out and viewing the following: - -* User information -* Connection type -* SQream version -* SQream Studio version -* License expiration date -* License storage capacity -* Log out - -.. _back_to_dashboard_5.4.3: - -.. _studio_dashboard_5.4.3: +.. _getting_started: + +**************************** +Getting Started with SQream Acceleration Studio 5.4.6 +**************************** +Setting Up and Starting Studio +---------------- + +:ref:`installing-sqream-db-docker` + + +Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. + +Logging In to Studio +--------------- +**To log in to SQream Studio:** + +1. Open a browser to the host on **port 8080**. + + For example, if your machine IP address is ``192.168.0.100``, insert the IP address into the browser as shown below: + + .. code-block:: console + + $ http://192.168.0.100:8080 + +2. Fill in your SQream DB login credentials. These are the same credentials used for :ref:`sqream sql` or JDBC. + + When you sign in, the License Warning is displayed. + +Navigating Studio's Main Features +------------- +When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. + +From here you can navigate between the main areas of the Studio: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Dashboard` + - Lets you monitor system health and manage queues and workers. + * - :ref:`Editor` + - Lets you select databases, perform statement operations, and write and execute queries. + * - :ref:`Logs` + - Lets you view usage logs. + * - :ref:`Roles` + - Lets you create users and manage user permissions. + * - :ref:`Configuration` + - Lets you configure your instance of SQream. + +By clicking the user icon, you can also use it for logging out and viewing the following: + +* User information +* Connection type +* SQream version +* SQream Studio version +* License expiration date +* License storage capacity +* Log out + +.. _back_to_dashboard_5.4.6: + +.. _studio_dashboard_5.4.6: diff --git a/sqream_studio_5.4.3/index.rst b/sqream_studio_5.4.6/index.rst similarity index 88% rename from sqream_studio_5.4.3/index.rst rename to sqream_studio_5.4.6/index.rst index ac607b121..83fd6d224 100644 --- a/sqream_studio_5.4.3/index.rst +++ b/sqream_studio_5.4.6/index.rst @@ -1,19 +1,19 @@ -.. _sqream_studio_5.4.3: - -********************************** -SQream Acceleration Studio 5.4.3 -********************************** -The SQream Acceleration Studio is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. - -This section describes how to use the SQream Accleration Studio version 5.4.3: - -.. toctree:: - :maxdepth: 1 - :glob: - - getting_started - monitoring_workers_and_services_from_the_dashboard - executing_statements_and_running_queries_from_the_editor - viewing_logs - creating_assigning_and_managing_roles_and_permissions +.. _sqream_studio_5.4.6: + +********************************** +SQream Acceleration Studio 5.4.6 +********************************** +The SQream Acceleration Studio is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. + +This section describes how to use the SQream Accleration Studio version 5.4.6: + +.. toctree:: + :maxdepth: 1 + :glob: + + getting_started + executing_statements_and_running_queries_from_the_editor + monitoring_workers_and_services_from_the_dashboard + viewing_logs + creating_assigning_and_managing_roles_and_permissions configuring_your_instance_of_sqream \ No newline at end of file diff --git a/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst similarity index 90% rename from sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst rename to sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst index e30962f37..00ec30eda 100644 --- a/sqream_studio_5.4.3/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst @@ -1,265 +1,265 @@ -.. _monitoring_workers_and_services_from_the_dashboard: - -.. _back_to_dashboard_5.4.3: - -**************************** -Monitoring Workers and Services from the Dashboard -**************************** -The **Dashboard** is used for the following: - -* Monitoring system health. -* Viewing, monitoring, and adding defined service queues. -* Viewing and managing worker status and add workers. - -The following is an image of the Dashboard: - -.. image:: /_static/images/dashboard.png - -You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. - -The following is a brief description of the Dashboard panels: - -.. list-table:: - :widths: 10 25 65 - :header-rows: 1 - - * - No. - - Element - - Description - * - 1 - - :ref:`Services panel` - - Used for viewing and monitoring the defined service queues. - * - 2 - - :ref:`Workers panel` - - Monitors system health and shows each Sqreamd worker running in the cluster. - * - 3 - - :ref:`License information` - - Shows the remaining amount of days left on your license. - - -.. _data_storage_panel_5.4.3: - - - -:ref:`Back to Monitoring Workers and Services from the Dashboard` - -.. _services_panel_5.4.3: - -Subscribing to Workers from the Services Panel --------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. - - - -The following is a brief description of each pane: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - No. - - Description - * - 1 - - Adds a worker to the selected service. - * - 2 - - Shows the service name. - * - 3 - - Shows a trend graph of queued statements loaded over time. - * - 4 - - Adds a service. - * - 5 - - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). - -Adding A Service -^^^^^^^^^^^^^^^^^^^^^ -You can add a service by clicking **+ Add** and defining the service name. - -.. note:: If you do not associate a worker with the new service, it will not be created. - -You can manage workers from the **Workers** panel. For more information about managing workers, see the following: - -* :ref:`Managing Workers from the Workers Panel` -* `Workers `_ - -:ref:`Back to Monitoring Workers and Services from the Dashboard` - -.. _workers_panel_5.4.3: - -Managing Workers from the Workers Panel ------------- -From the **Workers** panel you can do the following: - -* :ref:`View workers ` -* :ref:`Add a worker to a service` -* :ref:`View a worker's active query information` -* :ref:`View a worker's execution plan` - -.. _view_workers_5.4.3: - -Viewing Workers -^^^^^^^^ -The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. - -From the **Scale** dropdown menu you can set the time scale of the displayed information -You can hover over segments in the status bar to see the date and time corresponding to each activity type: - -* **Idle** – the worker is idle and available for statements. -* **Compiling** – the worker is compiling a statement and is preparing for execution. -* **Executing** – the worker is executing a statement after compilation. -* **Stopped** – the worker was stopped (either deliberately or due to an error). -* **Waiting** – the worker was waiting on an object locked by another worker. - -.. _add_worker_to_service_5.4.3: - -Adding A Worker to A Service -^^^^^^^^^^^^^^^^^^^^^ -You can add a worker to a service by clicking the **add** button. - - - -Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. - - -.. _view_worker_query_information_5.4.3: - -Viewing A Worker's Active Query Information -^^^^^^^^^^^^^^^^^^^^^ -You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. - - -Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. - -Viewing A Worker's Host Utilization -^^^^^^^^^^^^^^^^^^^^^ - -While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. - - - -The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. - -Error notifications related to statements are displayed, and you can hover over them for more information about the error. - - -.. _view_worker_execution_plan_5.4.3: - -Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^ - -Clicking the ellipsis in a service shows the following additional options: - -* **Stop Query** - stops the query. -* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. - -For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Managing Worker Status -^^^^^^^^^^^^^^^^^^^^^ - -In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. - - -Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. - - - - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle - -:ref:`Back to Monitoring Workers and Services from the Dashboard` - - - -.. _license_information_5.4.3: - -License Information ----------------------- -The license information section shows the following: - - * The amount of time in days remaining on the license. - * The license storage capacity. - -.. image:: /_static/images/license_storage_capacity.png - - -:ref:`Back to Monitoring Workers and Services from the Dashboard` +.. _monitoring_workers_and_services_from_the_dashboard: + +.. _back_to_dashboard_5.4.6: + +**************************** +Monitoring Workers and Services from the Dashboard +**************************** +The **Dashboard** is used for the following: + +* Monitoring system health. +* Viewing, monitoring, and adding defined service queues. +* Viewing and managing worker status and add workers. + +The following is an image of the Dashboard: + +.. image:: /_static/images/dashboard.png + +You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. + +The following is a brief description of the Dashboard panels: + +.. list-table:: + :widths: 10 25 65 + :header-rows: 1 + + * - No. + - Element + - Description + * - 1 + - :ref:`Services panel` + - Used for viewing and monitoring the defined service queues. + * - 2 + - :ref:`Workers panel` + - Monitors system health and shows each Sqreamd worker running in the cluster. + * - 3 + - :ref:`License information` + - Shows the remaining amount of days left on your license. + + +.. _data_storage_panel_5.4.6: + + + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + +.. _services_panel_5.4.6: + +Subscribing to Workers from the Services Panel +-------------------------- +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. + + + +The following is a brief description of each pane: + +.. list-table:: + :widths: 10 90 + :header-rows: 1 + + * - No. + - Description + * - 1 + - Adds a worker to the selected service. + * - 2 + - Shows the service name. + * - 3 + - Shows a trend graph of queued statements loaded over time. + * - 4 + - Adds a service. + * - 5 + - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). + +Adding A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a service by clicking **+ Add** and defining the service name. + +.. note:: If you do not associate a worker with the new service, it will not be created. + +You can manage workers from the **Workers** panel. For more information about managing workers, see the following: + +* :ref:`Managing Workers from the Workers Panel` +* `Workers `_ + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + +.. _workers_panel_5.4.6: + +Managing Workers from the Workers Panel +------------ +From the **Workers** panel you can do the following: + +* :ref:`View workers ` +* :ref:`Add a worker to a service` +* :ref:`View a worker's active query information` +* :ref:`View a worker's execution plan` + +.. _view_workers_5.4.6: + +Viewing Workers +^^^^^^^^ +The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. + +From the **Scale** dropdown menu you can set the time scale of the displayed information +You can hover over segments in the status bar to see the date and time corresponding to each activity type: + +* **Idle** – the worker is idle and available for statements. +* **Compiling** – the worker is compiling a statement and is preparing for execution. +* **Executing** – the worker is executing a statement after compilation. +* **Stopped** – the worker was stopped (either deliberately or due to an error). +* **Waiting** – the worker was waiting on an object locked by another worker. + +.. _add_worker_to_service_5.4.6: + +Adding A Worker to A Service +^^^^^^^^^^^^^^^^^^^^^ +You can add a worker to a service by clicking the **add** button. + + + +Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. + + +.. _view_worker_query_information_5.4.6: + +Viewing A Worker's Active Query Information +^^^^^^^^^^^^^^^^^^^^^ +You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. + + +Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. + +Viewing A Worker's Host Utilization +^^^^^^^^^^^^^^^^^^^^^ + +While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. + + + +The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. + +Error notifications related to statements are displayed, and you can hover over them for more information about the error. + + +.. _view_worker_execution_plan_5.4.6: + +Viewing a Worker's Execution Plan +^^^^^^^^^^^^^^^^^^^^^ + +Clicking the ellipsis in a service shows the following additional options: + +* **Stop Query** - stops the query. +* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. + +For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. + +.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst + :start-line: 67 + :end-line: 84 + +Managing Worker Status +^^^^^^^^^^^^^^^^^^^^^ + +In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. + + +Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. + + + + +.. |icon-user| image:: /_static/images/studio_icon_user.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-editor| image:: /_static/images/studio_icon_editor.png + :align: middle + +.. |icon-copy| image:: /_static/images/studio_icon_copy.png + :align: middle + +.. |icon-select| image:: /_static/images/studio_icon_select.png + :align: middle + +.. |icon-dots| image:: /_static/images/studio_icon_dots.png + :align: middle + +.. |icon-filter| image:: /_static/images/studio_icon_filter.png + :align: middle + +.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png + :align: middle + +.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png + :align: middle + +.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png + :align: middle + +.. |icon-plus| image:: /_static/images/studio_icon_plus.png + :align: middle + +.. |icon-close| image:: /_static/images/studio_icon_close.png + :align: middle + +.. |icon-left| image:: /_static/images/studio_icon_left.png + :align: middle + +.. |icon-right| image:: /_static/images/studio_icon_right.png + :align: middle + +.. |icon-format-sql| image:: /_static/images/studio_icon_format.png + :align: middle + +.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png + :align: middle + +.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png + :align: middle + +.. |icon-execute| image:: /_static/images/studio_icon_execute.png + :align: middle + +.. |icon-stop| image:: /_static/images/studio_icon_stop.png + :align: middle + +.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png + :align: middle + +.. |icon-expand| image:: /_static/images/studio_icon_expand.png + :align: middle + +.. |icon-scale| image:: /_static/images/studio_icon_scale.png + :align: middle + +.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png + :align: middle + +.. |icon-add| image:: /_static/images/studio_icon_add.png + :align: middle + +.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png + :align: middle + +.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png + :align: middle + +:ref:`Back to Monitoring Workers and Services from the Dashboard` + + + +.. _license_information_5.4.6: + +License Information +---------------------- +The license information section shows the following: + + * The amount of time in days remaining on the license. + * The license storage capacity. + +.. image:: /_static/images/license_storage_capacity.png + + +:ref:`Back to Monitoring Workers and Services from the Dashboard` diff --git a/sqream_studio_5.4.3/viewing_logs.rst b/sqream_studio_5.4.6/viewing_logs.rst similarity index 85% rename from sqream_studio_5.4.3/viewing_logs.rst rename to sqream_studio_5.4.6/viewing_logs.rst index 0a8350a45..e431550ed 100644 --- a/sqream_studio_5.4.3/viewing_logs.rst +++ b/sqream_studio_5.4.6/viewing_logs.rst @@ -1,122 +1,122 @@ -.. _viewing_logs: - -.. _logs_top_5.4.3: - -**************************** -Viewing Logs -**************************** -The **Logs** screen is used for viewing logs and includes the following elements: - -.. list-table:: - :widths: 15 75 - :header-rows: 1 - - * - Element - - Description - * - :ref:`Filter area` - - Lets you filter the data shown in the table. - * - :ref:`Query tab` - - Shows basic query information logs, such as query number and the time the query was run. - * - :ref:`Session tab` - - Shows basic session information logs, such as session ID and user name. - * - :ref:`System tab` - - Shows all system logs. - * - :ref:`Log lines tab` - - Shows the total amount of log lines. - - -.. _filter_5.4.3: - -Filtering Table Data -------------- -From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). - -Other filters require you to select an item from a dropdown menu: - -* INFO -* WARNING -* ERROR -* FATAL -* SYSTEM - -You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. - -.. _queries_5.4.3: - -:ref:`Back to Viewing Logs` - - -Viewing Query Logs ----------- -The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. - -From the Queries area you can see and sort by the following: - -* Query ID -* Start time -* Query -* Compilation duration -* Execution duration -* Total duration -* Details (execution details, error details, successful query details) - -In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. - -:ref:`Back to Viewing Logs` - -.. _sessions_5.4.3: - -Viewing Session Logs ----------- -The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. - -From here you can see and sort by the following: - -* Timestamp -* Connection ID -* Username -* Client IP -* Login (Success or Failed) -* Duration (of session) -* Configuration Changes - -In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. - -:ref:`Back to Viewing Logs` - -.. _system_5.4.3: - -Viewing System Logs ----------- -The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. - -From here you can see and sort by the following: - -* Timestamp -* Log type -* Message - -In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. - -:ref:`Back to Viewing Logs` - -.. _log_lines_5.4.3: - -Viewing All Log Lines ----------- -The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. - -From here you can see and sort by the following: - -* Timestamp -* Message level -* Worker hostname -* Worker port -* Connection ID -* Database name -* User name -* Statement ID - -In the **LOG LINES** table, you can click on any of the items to set them as your filters. - -:ref:`Back to Viewing Logs` \ No newline at end of file +.. _viewing_logs: + +.. _logs_top_5.4.6: + +**************************** +Viewing Logs +**************************** +The **Logs** screen is used for viewing logs and includes the following elements: + +.. list-table:: + :widths: 15 75 + :header-rows: 1 + + * - Element + - Description + * - :ref:`Filter area` + - Lets you filter the data shown in the table. + * - :ref:`Query tab` + - Shows basic query information logs, such as query number and the time the query was run. + * - :ref:`Session tab` + - Shows basic session information logs, such as session ID and user name. + * - :ref:`System tab` + - Shows all system logs. + * - :ref:`Log lines tab` + - Shows the total amount of log lines. + + +.. _filter_5.4.6: + +Filtering Table Data +------------- +From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). + +Other filters require you to select an item from a dropdown menu: + +* INFO +* WARNING +* ERROR +* FATAL +* SYSTEM + +You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. + +.. _queries_5.4.6: + +:ref:`Back to Viewing Logs` + + +Viewing Query Logs +---------- +The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. + +From the Queries area you can see and sort by the following: + +* Query ID +* Start time +* Query +* Compilation duration +* Execution duration +* Total duration +* Details (execution details, error details, successful query details) + +In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. + +:ref:`Back to Viewing Logs` + +.. _sessions_5.4.6: + +Viewing Session Logs +---------- +The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. + +From here you can see and sort by the following: + +* Timestamp +* Connection ID +* Username +* Client IP +* Login (Success or Failed) +* Duration (of session) +* Configuration Changes + +In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. + +:ref:`Back to Viewing Logs` + +.. _system_5.4.6: + +Viewing System Logs +---------- +The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. + +From here you can see and sort by the following: + +* Timestamp +* Log type +* Message + +In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. + +:ref:`Back to Viewing Logs` + +.. _log_lines_5.4.6: + +Viewing All Log Lines +---------- +The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. + +From here you can see and sort by the following: + +* Timestamp +* Message level +* Worker hostname +* Worker port +* Connection ID +* Database name +* User name +* Statement ID + +In the **LOG LINES** table, you can click on any of the items to set them as your filters. + +:ref:`Back to Viewing Logs` \ No newline at end of file From f5d562641a0ef4482e4c9b2baf8d6daf3142bf8c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 15:10:18 +0300 Subject: [PATCH 0197/1892] Updated Studio 5.4.3 to 5.4.6 Changed links to ref syntax. --- .../utility_commands/shutdown_server.rst | 2 -- .../configuring_your_instance_of_sqream.rst | 4 ++- ...ts_and_running_queries_from_the_editor.rst | 33 +++++++------------ ...started.rst => getting_started_sqream.rst} | 8 ++--- sqream_studio_5.4.6/index.rst | 2 +- ...orkers_and_services_from_the_dashboard.rst | 31 ++++++++--------- sqream_studio_5.4.6/viewing_logs.rst | 3 ++ 7 files changed, 36 insertions(+), 47 deletions(-) rename sqream_studio_5.4.6/{getting_started.rst => getting_started_sqream.rst} (86%) diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst index ac0c4dc96..1f607e753 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server.rst @@ -3,8 +3,6 @@ ******************** SHUTDOWN SERVER ******************** -**Comment** - When finished, add command to Utility Commands > shutdown_server. - The **SHUTDOWN_SERVER** guide describes the following: .. contents:: diff --git a/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst index 2b334cbfa..a0def6827 100644 --- a/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst @@ -3,6 +3,8 @@ **************************** Configuring Your Instance of SQream **************************** +**Comment** - *Has this functionality been removed from Studio 5.4.6?* + The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. @@ -20,4 +22,4 @@ Exporting and Importing Configuration Files ------------------------- You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. -For more information about configuring your instance of SQream, see `Configuration Guides `_. \ No newline at end of file +For more information about configuring your instance of SQream, see :ref:`configuration_guides`. \ No newline at end of file diff --git a/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst index 9640665da..8015b7c4a 100644 --- a/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst @@ -14,7 +14,6 @@ The **Editor** is used for the following: The following is a brief description of the Editor panels: - .. list-table:: :widths: 10 34 56 :header-rows: 1 @@ -35,8 +34,6 @@ The following is a brief description of the Editor panels: - :ref:`Results panel` - Shows query results and execution information. - - .. _top_5.4.6: .. _studio_5.4.6_editor_toolbar: @@ -73,22 +70,16 @@ You can access the following from the Toolbar pane: * **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. - -For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. +For more information on stopping active statements, see the :ref:`SHUTDOWN_SERVER` command. :ref:`Back to Executing Statements and Running Queries from the Editor` - .. _studio_5.4.6_editor_db_tree: Performing Statement-Related Operations from the Database Tree ================ From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). - - - - The database object functions are used to perform the following: * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. @@ -179,7 +170,8 @@ The database object functions are used to perform the following: .. |keep-tabs| image:: /_static/images/studio_keep_tabs.png :align: middle - + + :ref:`insert` .. list-table:: :widths: 30 70 @@ -188,23 +180,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT `_ statement for the selected table in the editing area. + - Generates an :ref:`insert` statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE `_ statement for the selected table in the editing area. + - Generates a :ref:`delete` statement for the selected table in the editing area. * - Create Table As statement - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. + - Generates an :ref:`rename_table` statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. + - Generates an :ref:`add_column` statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. + - Generates a :ref:`truncate` statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See :ref:`seeing_system_objects_as_ddl`. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -229,7 +221,7 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices `_. +For more information, see :ref:`sql_best_practices`. Executing Pre-Defined Queries from the System Queries Panel --------------- @@ -274,8 +266,7 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started `_. - +.. tip:: If this is your first time using SQream, see :ref:`getting_started`. .. Keyboard shortcuts .. ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/sqream_studio_5.4.6/getting_started.rst b/sqream_studio_5.4.6/getting_started_sqream.rst similarity index 86% rename from sqream_studio_5.4.6/getting_started.rst rename to sqream_studio_5.4.6/getting_started_sqream.rst index 6b328ae67..10542277e 100644 --- a/sqream_studio_5.4.6/getting_started.rst +++ b/sqream_studio_5.4.6/getting_started_sqream.rst @@ -1,15 +1,13 @@ -.. _getting_started: +.. _getting_started_sqream: **************************** Getting Started with SQream Acceleration Studio 5.4.6 **************************** Setting Up and Starting Studio ---------------- +Studio is included with all dockerized installations of SQream. When starting Studio, it listens on the local machine on port 8080. -:ref:`installing-sqream-db-docker` - - -Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. +For more information, see :ref:`running_sqream_in_a_docker_container`. Logging In to Studio --------------- diff --git a/sqream_studio_5.4.6/index.rst b/sqream_studio_5.4.6/index.rst index 83fd6d224..451a520ad 100644 --- a/sqream_studio_5.4.6/index.rst +++ b/sqream_studio_5.4.6/index.rst @@ -11,7 +11,7 @@ This section describes how to use the SQream Accleration Studio version 5.4.6: :maxdepth: 1 :glob: - getting_started + getting_started_sqream executing_statements_and_running_queries_from_the_editor monitoring_workers_and_services_from_the_dashboard viewing_logs diff --git a/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst index 00ec30eda..51dbb3941 100644 --- a/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst @@ -34,22 +34,17 @@ The following is a brief description of the Dashboard panels: - Monitors system health and shows each Sqreamd worker running in the cluster. * - 3 - :ref:`License information` - - Shows the remaining amount of days left on your license. - + - Shows the remaining amount of days left on your license. .. _data_storage_panel_5.4.6: - - :ref:`Back to Monitoring Workers and Services from the Dashboard` .. _services_panel_5.4.6: Subscribing to Workers from the Services Panel -------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. - - +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined in the :ref:`workload_manager`. The following is a brief description of each pane: @@ -138,20 +133,27 @@ While viewing a worker's query information, clicking the **down arrow** expands The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. -Error notifications related to statements are displayed, and you can hover over them for more information about the error. - +Error notifications related to statements are displayed, and you can hover over them for more information about the error. .. _view_worker_execution_plan_5.4.6: Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^ - +^^^^^^^^^^^^^^^^^^^^^ Clicking the ellipsis in a service shows the following additional options: * **Stop Query** - stops the query. + + :: + * **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. -For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. +For more information on the current query plan, see the following: + +* :ref:`show_node_info` + + :: + +* :ref:`show_server_status` .. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst :start-line: 67 @@ -159,15 +161,10 @@ For more information on the current query plan, see `SHOW_NODE_INFO ` - Shows the total amount of log lines. +.. note:: Because the logs are stored in the **system** database, you cannot search the logs without first creating a **system** database. When you access the **Logs** tab, SQream can automatically create a **system** database for you. .. _filter_5.4.6: @@ -104,6 +105,8 @@ In the Systems table, you can click on the **Timestamp** and **Log type** items Viewing All Log Lines ---------- +**Comment** - *Has this tab been removed from the GUI?* + The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. From here you can see and sort by the following: From 643334085b7468c01b70db4b8ce510805233d338 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 15:33:44 +0300 Subject: [PATCH 0198/1892] Removed Configuration from Studio index --- index.rst | 2 +- sqream_studio_5.4.6/index.rst | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/index.rst b/index.rst index 23e2288c0..efeecb8e2 100644 --- a/index.rst +++ b/index.rst @@ -87,7 +87,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit This version of the documentation is for SQream DB Version 2022.1. -If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . +If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com. .. toctree:: :caption: Contents: diff --git a/sqream_studio_5.4.6/index.rst b/sqream_studio_5.4.6/index.rst index 451a520ad..c4981ce81 100644 --- a/sqream_studio_5.4.6/index.rst +++ b/sqream_studio_5.4.6/index.rst @@ -15,5 +15,4 @@ This section describes how to use the SQream Accleration Studio version 5.4.6: executing_statements_and_running_queries_from_the_editor monitoring_workers_and_services_from_the_dashboard viewing_logs - creating_assigning_and_managing_roles_and_permissions - configuring_your_instance_of_sqream \ No newline at end of file + creating_assigning_and_managing_roles_and_permissions \ No newline at end of file From 4bdc8f6ba36a45b5ffd03ddd6316173c3fc451b7 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 15:34:12 +0300 Subject: [PATCH 0199/1892] Delete configuring_your_instance_of_sqream.rst --- .../configuring_your_instance_of_sqream.rst | 25 ------------------- 1 file changed, 25 deletions(-) delete mode 100644 sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst diff --git a/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst deleted file mode 100644 index a0def6827..000000000 --- a/sqream_studio_5.4.6/configuring_your_instance_of_sqream.rst +++ /dev/null @@ -1,25 +0,0 @@ -.. _configuring_your_instance_of_sqream: - -**************************** -Configuring Your Instance of SQream -**************************** -**Comment** - *Has this functionality been removed from Studio 5.4.6?* - -The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. - -Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. -Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. - -Editing Your Parameters -------------------------------- -When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. - -Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. - -You can hover over the **information** icon located on each parameter to read a short description of its behavior. - -Exporting and Importing Configuration Files -------------------------- -You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. - -For more information about configuring your instance of SQream, see :ref:`configuration_guides`. \ No newline at end of file From b072eabda389e4c26fea3d637195b29266f53092 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 16:34:18 +0300 Subject: [PATCH 0200/1892] Updated --- feature_guides/query_healer.rst | 2 ++ .../utility_commands/shutdown_server.rst | 34 +++++-------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 8f0b56d08..a2874e3bb 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -21,6 +21,8 @@ The following is an example of a log record for a query stuck in the query detec The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. +.. note:: The logs are located in your cluster. + Configuring the Healer ------------------ The following **Administration Worker** flags are required to configure the Query Healer: diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst index 1f607e753..334281929 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server.rst @@ -11,7 +11,7 @@ The **SHUTDOWN_SERVER** guide describes the following: Overview =============== -SQream's current method for stopping the SQream server is running the ``shutdown_server ()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown, giving you more control over the following: +SQream's current method for stopping the SQream server is running the ``shutdown_server()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown, giving you more control over the following: * Preventing new queries from connecting to the server. @@ -29,7 +29,7 @@ Running the ``SHUTDOWN_SERVER`` command does the following: * Prevents new queries from entering the server by doing the following: - * Setting the SQream server to unavailable in the metadata server. **Comment** - *Is "unavailable" the official server setting?* + * Disabling incoming queries. :: @@ -39,9 +39,7 @@ Running the ``SHUTDOWN_SERVER`` command does the following: :: -* Waiting for the statement queue to be cleared - the graceful shutdown waits for queries that have been compiled on the server to be cleared from the statement queue. During this time - start executing on other available servers. - -**Comment** - *The last bullet requires clarification.* +* Waits for any queries that depend on server being shut down to leave the statement queue. Syntax ========== @@ -51,14 +49,12 @@ The following is the syntax for using the ``SHUTDOWN_SERVER`` command: select shutdown_server([is_graceful, [timeout]]); -**Comment** - *Is the below syntax correct?* - +The following is example of the ``SHUTDOWN_SERVER`` command: + .. code-block:: postgres select shutdown_server([true/false, [timeout]]); -**Comment** - *Can you set the timeout as a flag in Studio, or only in the CLI?* - Returns ========== Running the ``shutdown_server`` command returns no output. @@ -78,7 +74,7 @@ The following table shows the ``shutdown_server`` parameters: * - ``is_graceful`` - Determines the method used to shut down the server. - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. - - **Comment** - Is the default ``true`` or ``false``? + - ``false`` * - ``timeout`` - Sets the maximum amount of minutes for the graceful shutdown method to run before the server is shut down using the standard method. - ``30`` @@ -86,10 +82,8 @@ The following table shows the ``shutdown_server`` parameters: .. note:: Setting ``is_graceful`` to ``false`` and defining the ``timeout`` value shuts the server down mid-query after the defined time. -It is possible to pass as the second argument the timeout in minutes after which a forceful shutdown will run, regardless of the progression of the graceful shutdown. - -**Comment** - *How can the above be true given the following, "Note that running forced shutdown with a timeout, i.e. select shutdown_server(false, 30) will return an error message; forced shutdown has no timeout timer"?* - +It is possible to pass as the second argument the timeout in minutes after which a forceful shutdown will run after defining the graceful shutdown value, regardless of the progression of the graceful shutdown. + Note that you set the timeout value using the ``defaultGracefulShutdownTimeoutMinutes`` flag in Studio. For more information, see :ref:`graceful_shutdown`. @@ -98,16 +92,6 @@ For more information, see :ref:`graceful_shutdown`. Like shutdown_server() graceful shutdown will stop any query currently running on the server. -**Comment** - *The above makes it seem like it's a separate command, but that's not the case.* - -Relationship to Healer & Use Case -============================ -**Comment** - *Cannot document this section until I know what the Healer actually does.* - -Currently the Healer will not trigger a graceful shutdown upon detection of a stuck query. It will however log detection of such a query, prompting the user to run a graceful shutdown of the server, possibly saving existing queued queries. - Permissions ============= -Using the ``shutdown_server`` command requires no special permissions. - -**Comment** - *Confirm.* \ No newline at end of file +Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file From e0a7def00cccd2dcaf7d8521a19fa4b0d7bfa685 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 22:21:22 +0300 Subject: [PATCH 0201/1892] Replaced 10.1 with 11.4 where necessary --- feature_guides/query_healer.rst | 2 +- .../installing_sqream_with_kubernetes.rst | 109 ++++++++++-------- .../running_sqream_in_a_docker_container.rst | 25 ++-- 3 files changed, 73 insertions(+), 63 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index a2874e3bb..7068abc2d 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -17,7 +17,7 @@ The following is an example of a log record for a query stuck in the query detec .. code-block:: console - 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours + #SQ#|1659621825880088264|2022-05-19 20:01:25.880|INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours"|#EOM# The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. diff --git a/installation_guides/installing_sqream_with_kubernetes.rst b/installation_guides/installing_sqream_with_kubernetes.rst index 093f21ba3..aa7e22422 100644 --- a/installation_guides/installing_sqream_with_kubernetes.rst +++ b/installation_guides/installing_sqream_with_kubernetes.rst @@ -197,27 +197,32 @@ After completing all of the steps above, you must check the CUDA version. .. code-block:: postgres - $ +-----------------------------------------------------------------------------+ - $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - $ |-------------------------------+----------------------+----------------------+ - $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - $ |===============================+======================+======================| - $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | - $ | 32% 38C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | - $ +-------------------------------+----------------------+----------------------+ - $ - $ +-----------------------------------------------------------------------------+ - $ | Processes: GPU Memory | - $ | GPU PID Type Process name Usage | - $ |=============================================================================| - $ | No running processes found | - $ +-----------------------------------------------------------------------------+ - -In the above output, the CUDA version is **10.1**. - -If the above output is not generated, CUDA has not been installed. To install CUDA, see `Installing the CUDA driver `_. + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + | | | MIG M. | + |===============================+======================+======================| + | 0 NVIDIA A100-PCI... On | 00000000:17:00.0 Off | 0 | + | N/A 34C P0 64W / 300W | 79927MiB / 80994MiB | 0% Default | + | | | Disabled | + +-------------------------------+----------------------+----------------------+ + | 1 NVIDIA A100-PCI... On | 00000000:CA:00.0 Off | 0 | + | N/A 35C P0 60W / 300W | 79927MiB / 80994MiB | 0% Default | + | | | Disabled | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ + +In the above output, the CUDA version is **11.4**. +If the above output is not generated, CUDA has not been installed. To install CUDA, see :ref:`installing-the-cuda-driver`. Go back to :ref:`Setting Up Your Hosts` @@ -795,40 +800,46 @@ Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS .. code-block:: postgres - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi The following is an example of the correct output: .. code-block:: postgres - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi - $ Unable to find image 'nvidia/cuda:10.1-base' locally - $ 10.1-base: Pulling from nvidia/cuda - $ d519e2592276: Pull complete - $ d22d2dfcfa9c: Pull complete - $ b3afe92c540b: Pull complete - $ 13a10df09dc1: Pull complete - $ 4f0bc36a7e1d: Pull complete - $ cd710321007d: Pull complete - $ Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 - $ Status: Downloaded newer image for nvidia/cuda:10.1-base - $ Sun Feb 14 13:27:58 2021 - $ +-----------------------------------------------------------------------------+ - $ | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - $ |-------------------------------+----------------------+----------------------+ - $ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - $ | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - $ |===============================+======================+======================| - $ | 0 GeForce GTX 105... Off | 00000000:01:00.0 Off | N/A | - $ | 32% 37C P0 N/A / 75W | 0MiB / 4039MiB | 0% Default | - $ +-------------------------------+----------------------+----------------------+ - $ - $ +-----------------------------------------------------------------------------+ - $ | Processes: GPU Memory | - $ | GPU PID Type Process name Usage | - $ |=============================================================================| - $ | No running processes found | - $ +-----------------------------------------------------------------------------+ + docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi + Unable to find image 'nvidia/cuda:11.4.3-base-centos7' locally + 11.4.3-base-centos7: Pulling from nvidia/cuda + d519e2592276: Pull complete + d22d2dfcfa9c: Pull complete + b3afe92c540b: Pull complete + 13a10df09dc1: Pull complete + 4f0bc36a7e1d: Pull complete + cd710321007d: Pull complete + Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 + Status: Downloaded newer image for nvidia/cuda:11.4.3-base-centos7 + Sun Feb 14 13:27:58 2021 + +-----------------------------------------------------------------------------+ + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + |-------------------------------+----------------------+----------------------+ + | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | + | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | + | | | MIG M. | + |===============================+======================+======================| + | 0 NVIDIA A100-PCI... On | 00000000:17:00.0 Off | 0 | + | N/A 34C P0 64W / 300W | 79927MiB / 80994MiB | 0% Default | + | | | Disabled | + +-------------------------------+----------------------+----------------------+ + | 1 NVIDIA A100-PCI... On | 00000000:CA:00.0 Off | 0 | + | N/A 35C P0 60W / 300W | 79927MiB / 80994MiB | 0% Default | + | | | Disabled | + +-------------------------------+----------------------+----------------------+ + + +-----------------------------------------------------------------------------+ + | Processes: GPU Memory | + | GPU PID Type Process name Usage | + |=============================================================================| + | No running processes found | + +-----------------------------------------------------------------------------+ For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions `_ diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index e85eac925..dd8d07e50 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -248,7 +248,7 @@ Installing the Nvidia CUDA Driver nvidia-smi Wed Oct 30 14:05:42 2019 +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | @@ -267,7 +267,7 @@ Installing the Nvidia CUDA Driver | No running processes found | +-----------------------------------------------------------------------------+ -#. Verify that the installed CUDA version shown in the output above is ``10.1``. +#. Verify that the installed CUDA version shown in the output above is ``11.4``. :: @@ -276,25 +276,25 @@ Installing the Nvidia CUDA Driver :: - 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). + 1. If CUDA version 11.4 has already been installed, skip to Docktime Runtime (Community Edition). :: - 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. + 2. If CUDA version 11.4 has not been installed yet, continue with Step 7 below. #. Do one of the following: - * Install :ref:`CUDA Driver version 10.1 for x86_64 `. + * Install :ref:`CUDA Driver version 11.4 for x86_64 `. :: * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. -.. _CUDA_10.1_x8664: +.. _CUDA_11.4_x8664: -Installing the CUDA Driver Version 10.1 for x86_64 +Installing the CUDA Driver Version 11.4 for x86_64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the CUDA driver version 10.1 for x86_64:** +**To install the CUDA driver version 11.4 for x86_64:** 1. Make the following target platform selections: @@ -314,7 +314,6 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - 3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: .. code-block:: @@ -353,7 +352,7 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab nvidia-smi Wed Oct 30 14:05:42 2019 +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | @@ -623,7 +622,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System .. code-block:: - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` @@ -675,7 +674,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System .. code-block:: - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1-base nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` @@ -1063,7 +1062,7 @@ The following is an example of the correct output: METADATA_PORT=3105 PICKER_PORT=3108 NUM_OF_GPUS=2 - CUDA_VERSION=10.1 + CUDA_VERSION=11.4 NVIDIA_SMI_PATH=/usr/bin/nvidia-smi DOCKER_PATH=/usr/bin/docker NVIDIA_DRIVER=418 From e42dc04cb2778fb9be4caa4060a3cf4fb492e2d9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 22:30:17 +0300 Subject: [PATCH 0202/1892] Update healer_max_inactivity_hours.rst --- configuration_guides/healer_max_inactivity_hours.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst index d05d46014..56ddb78fc 100644 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ b/configuration_guides/healer_max_inactivity_hours.rst @@ -1,7 +1,7 @@ .. _healer_max_inactivity_hours: ************************* -Query Healer +Configuring the Query Healer ************************* The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. From 888673e4502ed3fccfc117c61d308cbf05f0df0b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 22:49:09 +0300 Subject: [PATCH 0203/1892] Added Graceful Shutdown Flag --- configuration_guides/admin_regular_flags.rst | 3 ++- configuration_guides/graceful_shutdown.rst | 22 ++++++++++++++++++ .../utility_commands/shutdown_server.rst | 12 +++++----- .../getting_started_sqream.rst | 2 -- sqream_studio_5.4.6/viewing_logs.rst | 23 +------------------ 5 files changed, 31 insertions(+), 31 deletions(-) create mode 100644 configuration_guides/graceful_shutdown.rst diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 064fc4b1a..133641765 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -3,7 +3,7 @@ ************************* Regular Administration Flags ************************* -The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: +The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: * `Setting Bin Size `_ * `Setting CUDA Memory `_ @@ -12,6 +12,7 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Reducing CPU Hashtable Sizes `_ * `Setting Chunk Size for Copying from CPU to GPU `_ * `Indicating GPU Synchronicity `_ +* `Setting the Graceful Server Shutdown `_ * `Enabling Modification of R&D Flags `_ * `Checking for Post-Production CUDA Errors `_ * `Enabling Modification of clientLogger_debug File `_ diff --git a/configuration_guides/graceful_shutdown.rst b/configuration_guides/graceful_shutdown.rst new file mode 100644 index 000000000..8b4f4b55c --- /dev/null +++ b/configuration_guides/graceful_shutdown.rst @@ -0,0 +1,22 @@ +.. _graceful_shutdown: + +************************* +Setting the Graceful Server Shutdown +************************* +The ``defaultGracefulShutdownTimeoutMinutes`` flag is used for setting the amount of time to pass before SQream performs a graceful server shutdown. + +The following describes the ``defaultGracefulShutdownTimeoutMinutes`` flag: + +* **Data type** - size_t +* **Default value** - ``5`` +* **Allowed values** - 1-4000000000 + +For more information, see :ref:`shutdown_server`. + +For related flags, see the folowing: + +* :ref:`is_healer_on` + + :: + +* :ref:`healer_max_inactivity_hours` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst index 334281929..b38834d7e 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server.rst @@ -69,16 +69,16 @@ The following table shows the ``shutdown_server`` parameters: * - Parameter - Description - - Example - - Default + - Example + - Default * - ``is_graceful`` - Determines the method used to shut down the server. - - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. - - ``false`` + - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. + - ``false`` * - ``timeout`` - Sets the maximum amount of minutes for the graceful shutdown method to run before the server is shut down using the standard method. - - ``30`` - - Five minutes. + - ``30`` + - Five minutes. .. note:: Setting ``is_graceful`` to ``false`` and defining the ``timeout`` value shuts the server down mid-query after the defined time. diff --git a/sqream_studio_5.4.6/getting_started_sqream.rst b/sqream_studio_5.4.6/getting_started_sqream.rst index 10542277e..ea95f0c41 100644 --- a/sqream_studio_5.4.6/getting_started_sqream.rst +++ b/sqream_studio_5.4.6/getting_started_sqream.rst @@ -45,8 +45,6 @@ From here you can navigate between the main areas of the Studio: - Lets you view usage logs. * - :ref:`Roles` - Lets you create users and manage user permissions. - * - :ref:`Configuration` - - Lets you configure your instance of SQream. By clicking the user icon, you can also use it for logging out and viewing the following: diff --git a/sqream_studio_5.4.6/viewing_logs.rst b/sqream_studio_5.4.6/viewing_logs.rst index 99afde3d2..4b4654c4a 100644 --- a/sqream_studio_5.4.6/viewing_logs.rst +++ b/sqream_studio_5.4.6/viewing_logs.rst @@ -101,25 +101,4 @@ In the Systems table, you can click on the **Timestamp** and **Log type** items :ref:`Back to Viewing Logs` -.. _log_lines_5.4.6: - -Viewing All Log Lines ----------- -**Comment** - *Has this tab been removed from the GUI?* - -The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. - -From here you can see and sort by the following: - -* Timestamp -* Message level -* Worker hostname -* Worker port -* Connection ID -* Database name -* User name -* Statement ID - -In the **LOG LINES** table, you can click on any of the items to set them as your filters. - -:ref:`Back to Viewing Logs` \ No newline at end of file +.. _log_lines_5.4.6: \ No newline at end of file From bb28843d0130eb9553d8142fff5bc95bc182629e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 22:57:05 +0300 Subject: [PATCH 0204/1892] Update shutdown_server.rst --- .../sql/sql_statements/utility_commands/shutdown_server.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst index b38834d7e..7fa1571b5 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server.rst @@ -88,9 +88,7 @@ Note that you set the timeout value using the ``defaultGracefulShutdownTimeoutMi For more information, see :ref:`graceful_shutdown`. -**Comment** - *I have not yet created the ``graceful_shutdown`` configuration flag. I need to know what category it belongs in before doing so.* - -Like shutdown_server() graceful shutdown will stop any query currently running on the server. +As with the ``shutdown_server`` command, the **graceful server shutdown** stops all queries currently running on your server. Permissions ============= From 50944519ccd025eb3662df831fab61e76a24d57c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Thu, 4 Aug 2022 23:04:17 +0300 Subject: [PATCH 0205/1892] Corrected the links --- configuration_guides/admin_regular_flags.rst | 50 +++++++++---------- .../generic_regular_flags.rst | 26 +++++----- configuration_guides/generic_worker_flags.rst | 2 +- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 133641765..902ff224b 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -5,28 +5,28 @@ Regular Administration Flags ************************* The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Bin Size `_ -* `Setting CUDA Memory `_ -* `Limiting Runtime to Utility Functions `_ -* `Enabling High Bin Control Granularity `_ -* `Reducing CPU Hashtable Sizes `_ -* `Setting Chunk Size for Copying from CPU to GPU `_ -* `Indicating GPU Synchronicity `_ -* `Setting the Graceful Server Shutdown `_ -* `Enabling Modification of R&D Flags `_ -* `Checking for Post-Production CUDA Errors `_ -* `Enabling Modification of clientLogger_debug File `_ -* `Activating the NVidia Profiler Markers `_ -* `Appending String at End of Log Lines `_ -* `Monitoring and Printing Pinned Allocation Reports `_ -* `Increasing Chunk Size to Reduce Query Speed `_ -* `Adding Rechunker before Expensing Chunk Producer `_ -* `Setting the Buffer Size `_ -* `Setting Memory Used to Abort Server `_ -* `Splitting Large Reads for Concurrent Execution `_ -* `Setting Worker Amount to Handle Concurrent Reads `_ -* `Setting Implicit Casts in ORC Files `_ -* `Setting Timeout Limit for Locking Objects before Executing Statements `_ -* `Interpreting Decimal Literals as Double Instead of Numeric `_ -* `Interpreting VARCHAR as TEXT `_ -* `VARCHAR Identifiers `_ +* `Setting Bin Size `_ +* `Setting CUDA Memory `_ +* `Limiting Runtime to Utility Functions `_ +* `Enabling High Bin Control Granularity `_ +* `Reducing CPU Hashtable Sizes `_ +* `Setting Chunk Size for Copying from CPU to GPU `_ +* `Indicating GPU Synchronicity `_ +* `Setting the Graceful Server Shutdown `_ +* `Enabling Modification of R&D Flags `_ +* `Checking for Post-Production CUDA Errors `_ +* `Enabling Modification of clientLogger_debug File `_ +* `Activating the NVidia Profiler Markers `_ +* `Appending String at End of Log Lines `_ +* `Monitoring and Printing Pinned Allocation Reports `_ +* `Increasing Chunk Size to Reduce Query Speed `_ +* `Adding Rechunker before Expensing Chunk Producer `_ +* `Setting the Buffer Size `_ +* `Setting Memory Used to Abort Server `_ +* `Splitting Large Reads for Concurrent Execution `_ +* `Setting Worker Amount to Handle Concurrent Reads `_ +* `Setting Implicit Casts in ORC Files `_ +* `Setting Timeout Limit for Locking Objects before Executing Statements `_ +* `Interpreting Decimal Literals as Double Instead of Numeric `_ +* `Interpreting VARCHAR as TEXT `_ +* `VARCHAR Identifiers `_ diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index 83afa9e8f..34ff6850c 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -6,16 +6,16 @@ Regular Generic Flags The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: -* `Flipping Join Order to Force Equijoins `_ -* `Determining Client Level `_ -* `Setting CPU to Compress Defined Columns `_ -* `Setting Query Memory Processing Limit `_ -* `Setting the Spool Memory `_ -* `Setting Cache Partitions `_ -* `Setting Cache Flushing `_ -* `Setting InMemory Spool Memory `_ -* `Setting Disk Spool Memory `_ -* `Setting Spool Saved File Directory Location `_ -* `Setting Data Stored Persistently on Cache `_ -* `Setting Persistent Spool Saved File Directory Location `_ -* `Setting Session Tag Name `_ \ No newline at end of file +* `Flipping Join Order to Force Equijoins `_ +* `Determining Client Level `_ +* `Setting CPU to Compress Defined Columns `_ +* `Setting Query Memory Processing Limit `_ +* `Setting the Spool Memory `_ +* `Setting Cache Partitions `_ +* `Setting Cache Flushing `_ +* `Setting InMemory Spool Memory `_ +* `Setting Disk Spool Memory `_ +* `Setting Spool Saved File Directory Location `_ +* `Setting Data Stored Persistently on Cache `_ +* `Setting Persistent Spool Saved File Directory Location `_ +* `Setting Session Tag Name `_ \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst index 59fb9ac7a..7ae2a0ee7 100644 --- a/configuration_guides/generic_worker_flags.rst +++ b/configuration_guides/generic_worker_flags.rst @@ -5,4 +5,4 @@ Worker Generic Flags ************************* The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: - * `Persisting Your Cache Directory `_ \ No newline at end of file + * `Persisting Your Cache Directory `_ \ No newline at end of file From 98252ade3376b591bf3f37f95a988ab01113134b Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 8 Aug 2022 22:08:30 +0300 Subject: [PATCH 0206/1892] Removed enhancements to Update feature --- .../sql/sql_statements/dml_commands/update.rst | 16 ---------------- releases/2022.1.1.rst | 7 ------- releases/2022.1_index.rst | 3 --- 3 files changed, 26 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 6cc33f516..873cf6290 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -62,8 +62,6 @@ The following table describes the ``UPDATE`` parameters: - Specifies the column containing the data to be updated. * - ``additional_table_name`` - Specifies the column containing the data to be updated. - * - ``FROM`` |icon-new_2022.1.1| - - For making complex joins, specifies additional tables to be used in the WHERE condition. ``FROM`` is similar to the ``FROM`` clause in a ``DELETE`` statement. * - ``condition`` - Specifies the condition for updating the data. @@ -87,20 +85,6 @@ The following is an example of performing a simple update: UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; -Updating Tables that Contain Multi-Table Conditions ------------------ -The following shows an example of updating tables that contain multi-table conditions |icon-new_2022.1.1|: - -.. code-block:: postgres - - UPDATE bands - SET records_sold = records_sold + 1 - WHERE EXISTS ( - SELECT 1 FROM countries - WHERE countries.id=bands.country_id - AND country.name = 'Sweden' - ); - Triggering a Clean-Up ----------------- The following section shows an example of triggering a clean-up: diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 517c11042..1421a82a6 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -14,7 +14,6 @@ Version Content The 2022.1.1 Release Notes describes the following: * Enhanced security features. -* New data manipulation command. * Additional data ingestion format. New Features @@ -25,12 +24,6 @@ The 2022.1.1 Release Notes include the following new features: :local: :depth: 1 -Update Feature -************ -The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. - -For more information, see `UPDATE `_. - Password Security Compliance ************ In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 16a7d80ef..4018bedd1 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -35,9 +35,6 @@ The following enhancements were introduced in :ref:`August 2022 (2022.1.1) <2022 * - **Operational Guides** - :ref:`Password Security Compliance` - Integrated password security compliance measures when logging in to the CLI or Studio. - * - **Reference Guides** - - :ref:`update` - - The DML ``UPDATE`` statement has been enhanced to support running subqueries in the ``WHERE`` condition. July 2022 ================== From 99c9c020bdfb196ddb7fb55adbbd7d081ca6b6d9 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 10:19:09 +0300 Subject: [PATCH 0207/1892] Prepared for 2022.1.1 Release Removed New for 2022.1 icons. Removed zlib compression. Removed compression from 2022.1.1 RN main page. Removed zlib and Update from 2022.1 RN main page. --- data_ingestion/avro.rst | 2 +- feature_guides/compression.rst | 4 ---- feature_guides/data_encryption.rst | 2 +- releases/2022.1.1.rst | 7 ------- releases/2022.1_index.rst | 5 +---- 5 files changed, 3 insertions(+), 17 deletions(-) diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index 753786376..b20e64d49 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -3,7 +3,7 @@ ************************** Inserting Data from Avro ************************** -The **Inserting Data from Avro** page |icon-new_2022.1| describes inserting data from Avro into SQream and includes the following: +The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: .. |icon-new_2022.1| image:: /_static/images/new_2022.1.png :align: middle diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index ce5e922b6..4472c7ded 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -93,10 +93,6 @@ Compression strategies - Integer types - Optimized RLE + Delta type for built-in :ref:`identity columns`. - GPU - * - ``zlib`` |icon-new_dark_gray_2022.1.1.png| - - All types - - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - - CPU .. _specifying_compressions: diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 19aabb8e3..607d6c09a 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -3,7 +3,7 @@ *********************** Data Encryption *********************** -The **Data Encryption** page |icon-new_2022.1| describes the following: +The **Data Encryption** page describes the following: .. |icon-new_2022.1| image:: /_static/images/new_2022.1.png :align: middle diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 1421a82a6..faec3add2 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -14,7 +14,6 @@ Version Content The 2022.1.1 Release Notes describes the following: * Enhanced security features. -* Additional data ingestion format. New Features ---------- @@ -30,12 +29,6 @@ In compliance with GDPR standards, SQream now requires a strong password policy For more information, see :ref:`access_control_password_policy`. -Compression -************ -SQream now supports the **zlib** compression format. - -For more information, see `Compression `_. - Known Issues --------- The following table lists the known issues for Version 2022.1.1: diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 4018bedd1..eeb744d4e 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -29,9 +29,6 @@ The following enhancements were introduced in :ref:`August 2022 (2022.1.1) <2022 * - Topic - Feature - Description - * - **Feature Guides** - - :ref:`compression` - - SQream supports compressing and decompressing data in and from the **ZLIB** format. * - **Operational Guides** - :ref:`Password Security Compliance` - Integrated password security compliance measures when logging in to the CLI or Studio. @@ -54,5 +51,5 @@ The following enhancements were introduced in :ref:`July 2022 (2022.1) <2022.1>` - :ref:`data_encryption` - SQream has integrated data encryption mechanisms in accordance with General Data Protection Regulation (GDPR) standards. * - **Reference Guides** - - `UPDATE `_ + - `UPDATE `_ - The DML ``UPDATE`` statement has been introduced to support modifying the value of certain columns in existing rows. \ No newline at end of file From dfdcdea2f29f7c172ec4088ea2d0c7b57185967e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 11:14:00 +0300 Subject: [PATCH 0208/1892] Released 2022.1.1 --- operational_guides/access_control.rst | 2 +- releases/2022.1_index.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index d5d32394e..9d12ed712 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -8,8 +8,8 @@ Access Control :maxdepth: 1 :titlesonly: + access_control_password_policy access_control_overview access_control_managing_roles access_control_permissions - access_control_password_policy access_control_departmental_example \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index eeb744d4e..284dc299f 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -45,11 +45,11 @@ The following enhancements were introduced in :ref:`July 2022 (2022.1) <2022.1>` - Feature - Description * - **Data Ingestion** - - :ref:`avro` + - `Inserting data from Avro `_ - SQream now supports ingesting data from Avro files. * - **Feature Guides** - - :ref:`data_encryption` + - `Data encryption `_ - SQream has integrated data encryption mechanisms in accordance with General Data Protection Regulation (GDPR) standards. * - **Reference Guides** - - `UPDATE `_ + - `UPDATE `_ - The DML ``UPDATE`` statement has been introduced to support modifying the value of certain columns in existing rows. \ No newline at end of file From e73416b9cd33d38f1bc71cd5eee16fa2a0e99711 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 11:26:04 +0300 Subject: [PATCH 0209/1892] Corrected date in conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 95a622cd6..f8ee2ea90 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '2021.2' +release = '2022.1.1' From c89c5bcf0ae213d56859b763352fec4b33798e68 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 12:00:12 +0300 Subject: [PATCH 0210/1892] 2022.1.1 Removed New for 2022.1.1 icon (it doesn't look good). On main RN page, replaced ref syntax with absolute URL. --- configuration_guides/login_max_retries.rst | 2 +- operational_guides/access_control_password_policy.rst | 2 +- releases/2022.1.1.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst index af236c9c3..6938d990b 100644 --- a/configuration_guides/login_max_retries.rst +++ b/configuration_guides/login_max_retries.rst @@ -8,7 +8,7 @@ Adjusting Permitted Log-in Attempts :align: middle :width: 110 -The ``loginMaxRetries`` flag |icon-new_2022.1.1| sets the permitted log-in attempts. +The ``loginMaxRetries`` flag sets the permitted log-in attempts. The following describes the ``loginMaxRetries`` flag: diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst index fc845ebc4..6f678dc10 100644 --- a/operational_guides/access_control_password_policy.rst +++ b/operational_guides/access_control_password_policy.rst @@ -8,7 +8,7 @@ Password Security Compliance (New!) :align: middle :width: 110 -As part of our compliance with GDPR standards |icon-new_gray_2022.1.1| SQream relies on a strong password policy when accessing the CLI or Studio. +As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio. The following requirements apply when creating a password: diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index faec3add2..c830b15b6 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -27,7 +27,7 @@ Password Security Compliance ************ In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. -For more information, see :ref:`access_control_password_policy`. +For more information, see `Access Control Password Policy `_. Known Issues --------- From 38d2cb5d0ab202a806f544e2cee9fefce2bf0fad Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 16:07:50 +0300 Subject: [PATCH 0211/1892] Returned 2020.3.2 --- releases/2020.3.2.rst | 28 ++++++++++++++++++++++++++++ releases/2020.3_index.rst | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 releases/2020.3.2.rst diff --git a/releases/2020.3.2.rst b/releases/2020.3.2.rst new file mode 100644 index 000000000..c97e2bd47 --- /dev/null +++ b/releases/2020.3.2.rst @@ -0,0 +1,28 @@ +.. _2020.3.2: + +************************** +What's new in 2020.3.2 +************************** + +SQream DB v2020.3.2 contains major performance improvements and some bug fixes. + +Performance Enhancements +========================= +* Metadata on Demand optimization resulting in reduced latency and improved overall performance + + +Known Issues & Limitations +================================ +* Bug with STDDEV_SAMP,STDDEV_POP and STDEV functions +* Window function query returns wrong results +* rank() in window function sometimes returns garbage +* Window function on null value could have bad result +* Window function lead() on varchar can have garbage results +* Performance degradation when using "groupby" or outer_join + +Upgrading to v2020.3.2 +======================== + +Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. + +Contact your account manager to get the latest release of SQream DB. diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst index b13340b52..a662cb48a 100644 --- a/releases/2020.3_index.rst +++ b/releases/2020.3_index.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2020.3 ************************** -The 2020.3 Release Notes describe the following releases: +The 2020.3 release notes describe the following releases: .. contents:: :local: @@ -14,5 +14,6 @@ The 2020.3 Release Notes describe the following releases: :glob: 2020.3.2.1 + 2020.3.2 2020.3.1 2020.3 \ No newline at end of file From a4f8bc94f4e9bd8c56e8cc8e1611c540a6e11a1f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 16:33:12 +0300 Subject: [PATCH 0212/1892] Divided bugs --- releases/2021.2.1.24.rst | 42 ++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 1d5407d89..aa60c701c 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -15,7 +15,7 @@ The 2021.2.1.24 Release Notes includes a query maintenance feature. New Features ---------- -The 2021.2.1.24 Release Notes include the following new features: +The 2021.2.1.24 Release Notes include the following new features: .. contents:: :local: @@ -27,35 +27,49 @@ The new **Query Healer** feature periodically examines the progress of running s For more information, see `Query Healer `_. -Known Issues +Resolved Issues --------- -The following table lists the known issues for Version 2021.2.1.24: +The following table lists the resolved issues for Version 2021.2.1.24: +-------------+------------------------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +=============+====================================================================================================================================+ -| SQ-10071 | An error occurred on existing subqueries with ``TEXT`` and ``VARCHAR`` equality conditions. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ | SQ-10606 | Queries were getting stuck in the queue for a prolonged time. | +-------------+------------------------------------------------------------------------------------------------------------------------------------+ | SQ-10691 | The DB schema identifier was causing an error when running queries from joins suite. | +-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10902 | Inserting a null value into non-null column was causing SQream to crash. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ | SQ-10918 | The Workload Manager was only assigning jobs sequentially, delaying user SQLs assigned to workers running very large jobs. | +-------------+------------------------------------------------------------------------------------------------------------------------------------+ | SQ-10955 | Metadata filters were not being applied when users filtered by nullable dates using ``dateadd`` | +-------------+------------------------------------------------------------------------------------------------------------------------------------+ + +Known Issues +--------- +The following table lists the known issues for Version 2021.2.1.24: + ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+====================================================================================================================================+ +| SQ-10071 | An error occurred on existing subqueries with ``TEXT`` and ``VARCHAR`` equality conditions. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-10902 | Inserting a null value into non-null column was causing SQream to crash. | ++-------------+------------------------------------------------------------------------------------------------------------------------------------+ | SQ-11088 | Specific workers caused low performance during compilation. | +-------------+------------------------------------------------------------------------------------------------------------------------------------+ -Resolved Issues ---------- -The Resolved Issues section is not relevant for Version 2021.2.1.24. +Operations and Configuration Changes +-------- +The following configuration flags were added: -Operational and Configuration Changes -------- -No relevant operational or configuration changes were made. + * :ref:`is_healer_on` + + :: + + * :ref:`healer_max_inactivity_hours` + + :: + + * :ref:`login_max_retries` Naming Changes ------- @@ -74,4 +88,4 @@ The End of Support section is not relevant to Version 2021.2.1.24. :glob: :hidden: - 2021.2.1.24 \ No newline at end of file + 2021.2.1.24 From 2629fc755633effc64451c9729b6ab55a9ebee67 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 18:02:46 +0300 Subject: [PATCH 0213/1892] Reverted to 2022.1 Will restore 2022.1.1 when new release date is decided. --- operational_guides/access_control.rst | 1 - .../access_control_password_policy.rst | 73 -------- releases/2022.1.1.rst | 113 ------------ releases/2022.1_index.rst | 162 +++++++++++++----- 4 files changed, 122 insertions(+), 227 deletions(-) delete mode 100644 operational_guides/access_control_password_policy.rst delete mode 100644 releases/2022.1.1.rst diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index 9d12ed712..88a14d71b 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -8,7 +8,6 @@ Access Control :maxdepth: 1 :titlesonly: - access_control_password_policy access_control_overview access_control_managing_roles access_control_permissions diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst deleted file mode 100644 index 6f678dc10..000000000 --- a/operational_guides/access_control_password_policy.rst +++ /dev/null @@ -1,73 +0,0 @@ -.. _access_control_password_policy: - -************** -Password Security Compliance (New!) -************** - -.. |icon-new_gray_2022.1.1| image:: /_static/images/new_gray_2022.1.1.png - :align: middle - :width: 110 - -As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio. - -The following requirements apply when creating a password: - -* At least eight characters long. - - :: - -* At least one numeric character. - - :: - -* Should not include a username. - - :: - -* Must include at least one special character, such as **?**, **!**, **$**, etc. - - :: - -* Mandatory upper and lowercase letters. - -The following is the syntax for creating a password: - -.. code-block:: console - - CREATE ROLE ; - GRANT LOGIN ; - GRANT PASSWORD <'password'> to ; - -The following is an example of creating a password: - -.. code-block:: console - - CREATE ROLE user_a ; - GRANT LOGIN to user_a ; - GRANT PASSWORD 'BBAu47?fqPL' to user_a ; - -Creating a password that does not comply with the above requirements generates the following error message: - -.. code-block:: console - - The password you attempt to create does not comply with SQream security requirements. Please follow the requirements below: - - * At least 8 characters long. - - * Must include both upper and lower case letters. - - * Must include at least one numeric character. - - * Must not include your username. - - * Must include at least one “special” character (?, !, $, etc.). - -.. note:: When a new user is created in Studio, a message is displayed to help you determine what the constraints are. - -Unsuccessfully attempting to log in three times displays the following message: - -.. code-block:: console - - The user is locked. please contact your system administrator to reset the password and regain access functionality. - -For more information, see :ref:`login_max_retries`. \ No newline at end of file diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst deleted file mode 100644 index c830b15b6..000000000 --- a/releases/2022.1.1.rst +++ /dev/null @@ -1,113 +0,0 @@ -.. _2022.1.1: - -************************** -Release Notes 2022.1.1 -************************** -The 2022.1.1 release notes were released on 7/19/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------- -The 2022.1.1 Release Notes describes the following: - -* Enhanced security features. - -New Features ----------- -The 2022.1.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Password Security Compliance -************ -In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. - -For more information, see `Access Control Password Policy `_. - -Known Issues ---------- -The following table lists the known issues for Version 2022.1.1: - -+-------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+================================================================================================+ -| SQ-6419 | An internal compiler error occurred when casting Numeric literals in an aggregation function. | -+-------------+------------------------------------------------------------------------------------------------+ - -Resolved Issues ---------- -The following table lists the issues that were resolved in Version 2022.1.1: - -+-------------+----------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+========================================================================================+ -| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | -+-------------+----------------------------------------------------------------------------------------+ -| SQ-10892 | An unclear message was displayed when users ran ``UPDATE`` on foreign tables. | -+-------------+----------------------------------------------------------------------------------------+ - -Operations and Configuration Changes --------- -The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. - -For more information, see `Adjusting the Permitted Log-In Attempts `_. - -Naming Changes -------- -No relevant naming changes were made. - -Deprecated Features -------- -No features were deprecated for Version 2022.1.1. - -End of Support -------- -The End of Support section is not relevant to Version 2022.1.1. - -Upgrading to v2022.1.1 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. - -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 284dc299f..3d1517371 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -1,55 +1,137 @@ -.. _2022.1_index: +.. _2022.1: ************************** Release Notes 2022.1 ************************** -The 2022.1 Release Notes describe the following releases: +The 2022.1 release notes were released on 7/19/2022 and describe the following: -.. toctree:: - :maxdepth: 1 - :glob: +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1 Release Notes describes the following: - 2022.1.1 - 2022.1 +* Enhanced security features. +* New data manipulation command. +* Additional data ingestion format. -You can also use the following tables for a summary of the new features in Version 2022.1 according to month: +New Features +---------- +The 2022.1 Release Notes include the following new features: .. contents:: :local: :depth: 1 + +Data Encryption +************ +SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. + +Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. + +For more information, see `Data Encryption `_. + +Update Feature +************ +SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. + +For more information, see `UPDATE `_. + +Avro Ingestion +************ +SQream now supports ingesting data from Avro files. + +For more information, see `Inserting Data from Avro `_. + +Known Issues +--------- +The following table lists the known issues for Version 2022.1: + ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10629 | Inserting data into a table significantly slowed down running queries. | ++-------------+-------------------------------------------------------------------------------------------+ +| SQ-10659 | Using a comment generated a compile error. | ++-------------+-------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1: + ++-------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================+ +| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | ++-------------+-------------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +No relevant operations and configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. -August 2022 -================== -The following enhancements were introduced in :ref:`August 2022 (2022.1.1) <2022.1.1>`: +Deprecated Features +------- +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. -.. list-table:: - :widths: 24 25 60 - :header-rows: 1 +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1. + +Upgrading to v2022.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. - * - Topic - - Feature - - Description - * - **Operational Guides** - - :ref:`Password Security Compliance` - - Integrated password security compliance measures when logging in to the CLI or Studio. - -July 2022 -================== -The following enhancements were introduced in :ref:`July 2022 (2022.1) <2022.1>`: - -.. list-table:: - :widths: 20 20 60 - :header-rows: 1 + SQream runs the Garbage Collector and creates a clean backup tarball package. - * - Topic - - Feature - - Description - * - **Data Ingestion** - - `Inserting data from Avro `_ - - SQream now supports ingesting data from Avro files. - * - **Feature Guides** - - `Data encryption `_ - - SQream has integrated data encryption mechanisms in accordance with General Data Protection Regulation (GDPR) standards. - * - **Reference Guides** - - `UPDATE `_ - - The DML ``UPDATE`` statement has been introduced to support modifying the value of certain columns in existing rows. \ No newline at end of file +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 \ No newline at end of file From b833913c876a86b849819bebe068ea0b4e79a7a4 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Tue, 9 Aug 2022 18:06:04 +0300 Subject: [PATCH 0214/1892] Removed login_max_retries Will restore when new release date is announced. --- configuration_guides/admin_worker_flags.rst | 3 +-- configuration_guides/login_max_retries.rst | 16 ---------------- releases/2021.2.1.24.rst | 4 ---- 3 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 configuration_guides/login_max_retries.rst diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index edbc71465..b41a6a5cd 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -16,5 +16,4 @@ The **Worker Administration Flags** page describes **Worker** modification type * `Setting Port Used for Metadata Server Connection `_ * `Assigning Local Network IP `_ * `Enabling the Query Healer `_ -* `Configuring the Query Healer `_ -* `Adjusting the Permitted Log-In Attempts `_ |icon-new_gray_2022.1.1| \ No newline at end of file +* `Configuring the Query Healer `_ \ No newline at end of file diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst deleted file mode 100644 index 6938d990b..000000000 --- a/configuration_guides/login_max_retries.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _login_max_retries: - -************************* -Adjusting Permitted Log-in Attempts -************************* - -.. |icon-new_2022.1.1| image:: /_static/images/new_2022.1.1.png - :align: middle - :width: 110 - -The ``loginMaxRetries`` flag sets the permitted log-in attempts. - -The following describes the ``loginMaxRetries`` flag: - -* **Data type** - size_t -* **Default value** - ``5`` \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index aa60c701c..a89244934 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -67,10 +67,6 @@ The following configuration flags were added: * :ref:`healer_max_inactivity_hours` - :: - - * :ref:`login_max_retries` - Naming Changes ------- No relevant naming changes were made. From 220d97f436c797b23357d02da477336e0753a83a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Wed, 10 Aug 2022 11:26:32 +0300 Subject: [PATCH 0215/1892] Started creating 2022.1.2 --- conf.py | 2 +- configuration_guides/admin_worker_flags.rst | 13 +- configuration_guides/login_max_retries.rst | 11 ++ operational_guides/access_control.rst | 1 + .../access_control_password_policy.rst | 42 ++++++ releases/2022.1.1.rst | 113 +++++++++++++++ releases/2022.1.2.rst | 129 ++++++++++++++++++ releases/2022.1_index.rst | 129 +----------------- 8 files changed, 309 insertions(+), 131 deletions(-) create mode 100644 configuration_guides/login_max_retries.rst create mode 100644 operational_guides/access_control_password_policy.rst create mode 100644 releases/2022.1.1.rst create mode 100644 releases/2022.1.2.rst diff --git a/conf.py b/conf.py index f8ee2ea90..4151da1c4 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '2022.1.1' +release = '2022.1.2' diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst index b41a6a5cd..130131b57 100644 --- a/configuration_guides/admin_worker_flags.rst +++ b/configuration_guides/admin_worker_flags.rst @@ -11,9 +11,10 @@ Worker Administration Flags The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Total Device Memory Usage in SQream Instance `_ -* `Enabling Manually Setting Reported IP `_ -* `Setting Port Used for Metadata Server Connection `_ -* `Assigning Local Network IP `_ -* `Enabling the Query Healer `_ -* `Configuring the Query Healer `_ \ No newline at end of file +* `Setting Total Device Memory Usage in SQream Instance `_ +* `Enabling Manually Setting Reported IP `_ +* `Setting Port Used for Metadata Server Connection `_ +* `Assigning Local Network IP `_ +* `Enabling the Query Healer `_ +* `Configuring the Query Healer `_ +* `Adjusting Permitted Log-in Attempts `_ \ No newline at end of file diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst new file mode 100644 index 000000000..bf3ae6d40 --- /dev/null +++ b/configuration_guides/login_max_retries.rst @@ -0,0 +1,11 @@ +.. _login_max_retries: + +************************* +Adjusting Permitted Log-in Attempts +************************* +The ``loginMaxRetries`` flag sets the permitted log-in attempts. + +The following describes the ``loginMaxRetries`` flag: + +* **Data type** - size_t +* **Default value** - ``5`` \ No newline at end of file diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index 88a14d71b..8aba611eb 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -8,6 +8,7 @@ Access Control :maxdepth: 1 :titlesonly: + access_control_password_policy access_control_overview access_control_managing_roles access_control_permissions diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst new file mode 100644 index 000000000..10a4f697f --- /dev/null +++ b/operational_guides/access_control_password_policy.rst @@ -0,0 +1,42 @@ +.. _access_control_password_policy: + +************** +Password Policy +************** +As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: + +* At least eight characters long. + + :: + +* Mandatory upper and lowercase letters. + + :: + +* At least one numeric character. + + :: + +* May not include a username. + + :: + +* Must include at least one special character, such as **?**, **!**, **$**, etc. + +You can create a password through the Studio graphic interface or through the CLI, as in the following example command: + +.. code-block:: console + + CREATE ROLE user_a ; + GRANT LOGIN to user_a ; + GRANT PASSWORD 'BBAu47?fqPL' to user_a ; + +Creating a password that does not comply with the above requirements generates an error message with a request to modify it. + +Unsuccessfully attempting to log in three times displays the following message: + +.. code-block:: console + + The user is locked. please contact your system administrator to reset the password and regain access functionality. + +For more information, see :ref:`login_max_retries`. diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst new file mode 100644 index 000000000..faec3add2 --- /dev/null +++ b/releases/2022.1.1.rst @@ -0,0 +1,113 @@ +.. _2022.1.1: + +************************** +Release Notes 2022.1.1 +************************** +The 2022.1.1 release notes were released on 7/19/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.1 Release Notes describes the following: + +* Enhanced security features. + +New Features +---------- +The 2022.1.1 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Password Security Compliance +************ +In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. + +For more information, see :ref:`access_control_password_policy`. + +Known Issues +--------- +The following table lists the known issues for Version 2022.1.1: + ++-------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+================================================================================================+ +| SQ-6419 | An internal compiler error occurred when casting Numeric literals in an aggregation function. | ++-------------+------------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.1: + ++-------------+----------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+========================================================================================+ +| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | ++-------------+----------------------------------------------------------------------------------------+ +| SQ-10892 | An unclear message was displayed when users ran ``UPDATE`` on foreign tables. | ++-------------+----------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. + +For more information, see `Adjusting the Permitted Log-In Attempts `_. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +No features were deprecated for Version 2022.1.1. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1.1. + +Upgrading to v2022.1.1 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst new file mode 100644 index 000000000..d94916d02 --- /dev/null +++ b/releases/2022.1.2.rst @@ -0,0 +1,129 @@ +.. _2022.1.2: + +************************** +Release Notes 2022.1.2 +************************** +The 2022.1.2 release notes were released on x/xx/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.2 Release Notes describes the following: + +* Enhanced security features. + +New Features +---------- +The 2022.1.2 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Feature 1 +************ + + +For more information, see + +Feature 2 +************ + + +For more information, see + +Known Issues +--------- +The following table lists the known issues for Version 2022.1.2: + ++-------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+================================================================================================+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.2: + ++-------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+================================================================================================+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-xxxx | Description | ++-------------+------------------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +The ``xxxx`` configuration flag is required for adjusting the permitted log-in attempts. + +For more information, see + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +No features were deprecated for Version 2022.1.2. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1.2. + +Upgrading to v2022.1.2 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.2 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 3d1517371..5f53bcb38 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -1,137 +1,18 @@ -.. _2022.1: +.. _2022.1_index: ************************** Release Notes 2022.1 ************************** -The 2022.1 release notes were released on 7/19/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------- -The 2022.1 Release Notes describes the following: - -* Enhanced security features. -* New data manipulation command. -* Additional data ingestion format. - -New Features ----------- -The 2022.1 Release Notes include the following new features: +The 2022.1 Release Notes describe the following releases: .. contents:: :local: :depth: 1 - -Data Encryption -************ -SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. - -Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. - -For more information, see `Data Encryption `_. - -Update Feature -************ -SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. - -For more information, see `UPDATE `_. - -Avro Ingestion -************ -SQream now supports ingesting data from Avro files. - -For more information, see `Inserting Data from Avro `_. - -Known Issues ---------- -The following table lists the known issues for Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10629 | Inserting data into a table significantly slowed down running queries. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10659 | Using a comment generated a compile error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Resolved Issues ---------- -The following table lists the issues that were resolved in Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes --------- -No relevant operations and configuration changes were made. - -Naming Changes -------- -No relevant naming changes were made. - -Deprecated Features -------- -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. - -End of Support -------- -The End of Support section is not relevant to Version 2022.1. - -Upgrading to v2022.1 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. - .. toctree:: - :maxdepth: 2 + :maxdepth: 1 :glob: - :hidden: + 2022.1.2 + 2022.1.1 2022.1 \ No newline at end of file From 3b287ce61c88ec64386fcfd3d8a6c17a03fe2e6f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 14 Aug 2022 19:05:17 +0300 Subject: [PATCH 0216/1892] Updated --- feature_guides/query_healer.rst | 26 +++- login_5.3.1.png | Bin 88126 -> 0 bytes .../access_control_password_policy.rst | 40 ++++++- reference/sql/sql_statements/index.rst | 4 +- .../utility_commands/shutdown_server.rst | 95 --------------- .../shutdown_server_command.rst | 113 ++++++++++++++++++ sqream_studio_5.4.6/index.rst | 18 --- .../configuring_your_instance_of_sqream.rst | 23 ++++ ...ing_and_managing_roles_and_permissions.rst | 12 +- ...ts_and_running_queries_from_the_editor.rst | 93 +++++++------- .../getting_started.rst | 14 +-- sqream_studio_5.4.7/index.rst | 19 +++ ...orkers_and_services_from_the_dashboard.rst | 77 ++++++------ .../viewing_logs.rst | 50 +++++--- studio_login_5.3.2.png | Bin 82674 -> 0 bytes 15 files changed, 353 insertions(+), 231 deletions(-) delete mode 100644 login_5.3.1.png delete mode 100644 reference/sql/sql_statements/utility_commands/shutdown_server.rst create mode 100644 reference/sql/sql_statements/utility_commands/shutdown_server_command.rst delete mode 100644 sqream_studio_5.4.6/index.rst create mode 100644 sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst rename {sqream_studio_5.4.6 => sqream_studio_5.4.7}/creating_assigning_and_managing_roles_and_permissions.rst (97%) rename {sqream_studio_5.4.6 => sqream_studio_5.4.7}/executing_statements_and_running_queries_from_the_editor.rst (86%) rename sqream_studio_5.4.6/getting_started_sqream.rst => sqream_studio_5.4.7/getting_started.rst (78%) create mode 100644 sqream_studio_5.4.7/index.rst rename {sqream_studio_5.4.6 => sqream_studio_5.4.7}/monitoring_workers_and_services_from_the_dashboard.rst (84%) rename {sqream_studio_5.4.6 => sqream_studio_5.4.7}/viewing_logs.rst (73%) delete mode 100644 studio_login_5.3.2.png diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 7068abc2d..0180150ea 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -17,11 +17,9 @@ The following is an example of a log record for a query stuck in the query detec .. code-block:: console - #SQ#|1659621825880088264|2022-05-19 20:01:25.880|INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours"|#EOM# + 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours -The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. - -.. note:: The logs are located in your cluster. +The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. Configuring the Healer ------------------ @@ -33,4 +31,22 @@ The following **Administration Worker** flags are required to configure the Quer * :ref:`healer_max_inactivity_hours` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. -The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. \ No newline at end of file +The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. + +Activating a Graceful Shutdown +------------------ +If your log entry says ``Stuck query found``, you must set the **shutdown_server** utility function to ``select shutdown_server(true);``, as in the following example: + +.. code-block:: console + + |INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1. + +Note that the log above identifies the IP (192.168.4.65) and port (5001) referring to the stuck query. + +For more information, see the following: + +* Activating the :ref:`shutdown_server_command` utility function. + + :: + +* Configuring the :ref:`shutdown_server` flag. \ No newline at end of file diff --git a/login_5.3.1.png b/login_5.3.1.png deleted file mode 100644 index 48c725a4c141b6a2bb04718c683646300bda009c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88126 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
2k12sUQOc} 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
25hieY$j%?+_Jc9<6R}d~s2d%gu9h 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 diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst index 10a4f697f..055d674bb 100644 --- a/operational_guides/access_control_password_policy.rst +++ b/operational_guides/access_control_password_policy.rst @@ -3,6 +3,14 @@ ************** Password Policy ************** +The **Password Policy** describes the following: + +.. contents:: + :local: + :depth: 1 + +Password Strength Requirements +============================== As part of our compliance with GDPR standards SQream relies on a strong password policy when accessing the CLI or Studio, with the following requirements: * At least eight characters long. @@ -23,7 +31,7 @@ As part of our compliance with GDPR standards SQream relies on a strong password * Must include at least one special character, such as **?**, **!**, **$**, etc. -You can create a password through the Studio graphic interface or through the CLI, as in the following example command: +You can grant a password through the Studio graphic interface or through the CLI, as in the following example command: .. code-block:: console @@ -31,12 +39,38 @@ You can create a password through the Studio graphic interface or through the CL GRANT LOGIN to user_a ; GRANT PASSWORD 'BBAu47?fqPL' to user_a ; -Creating a password that does not comply with the above requirements generates an error message with a request to modify it. +Granting a password that does not comply with the above requirements generates an error message with a request to modify it; + +.. code-block:: console + + The password you attempted to create does not comply with SQream's security requirements. + + Your password must: + + * Be at least eight characters long. + + * Contain upper and lowercase letters. + * Contain at least one numeric character. + + * Not include a username. + + * Include at least one special character, such as **?**, **!**, **$**, etc. + +Brute Force Prevention +============================== Unsuccessfully attempting to log in three times displays the following message: .. code-block:: console - The user is locked. please contact your system administrator to reset the password and regain access functionality. + The user is locked. Please contact your system administrator to reset the password and regain access functionality. + +You must have superuser permissions to release a locked user to grant a new password: + +.. code-block:: console + + GRANT PASSWORD '' to ; For more information, see :ref:`login_max_retries`. + +.. warning:: Because superusers can also be blocked, **you must have** at least two superusers per cluster. \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 5cac43122..960200937 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -130,8 +130,8 @@ The following table shows the Utility commands: - Returns a list of active sessions across the cluster * - :ref:`SHOW VERSION` - Returns the system version for SQream DB - * - :ref:`SHUTDOWN SERVER` - - Performs a graceful server shutdown + * - :ref:`SHUTDOWN_SERVER` + - Sets your server to finish compiling all active queries before shutting down according to a user-defined time value * - :ref:`STOP STATEMENT` - Stops or aborts an active statement diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server.rst b/reference/sql/sql_statements/utility_commands/shutdown_server.rst deleted file mode 100644 index 7fa1571b5..000000000 --- a/reference/sql/sql_statements/utility_commands/shutdown_server.rst +++ /dev/null @@ -1,95 +0,0 @@ -.. _shutdown_server: - -******************** -SHUTDOWN SERVER -******************** -The **SHUTDOWN_SERVER** guide describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview -=============== -SQream's current method for stopping the SQream server is running the ``shutdown_server()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown, giving you more control over the following: - -* Preventing new queries from connecting to the server. - - :: - -* The amount of time to wait before shutting down the server. - - :: - -* Configurations related to shutting down the server. - -How Does it Work? -======================== -Running the ``SHUTDOWN_SERVER`` command does the following: - -* Prevents new queries from entering the server by doing the following: - - * Disabling incoming queries. - - :: - - * Unsubscribing the server from its service. - -* Preventing new connections from being made to the server - attempting to establish a connection with the server after initiating a graceful shutdown displays the "Server is shutting down, no new connections are possible at the moment" messsge. - - :: - -* Waits for any queries that depend on server being shut down to leave the statement queue. - -Syntax -========== -The following is the syntax for using the ``SHUTDOWN_SERVER`` command: - -.. code-block:: postgres - - select shutdown_server([is_graceful, [timeout]]); - -The following is example of the ``SHUTDOWN_SERVER`` command: - -.. code-block:: postgres - - select shutdown_server([true/false, [timeout]]); - -Returns -========== -Running the ``shutdown_server`` command returns no output. - -Parameters -============ -The following table shows the ``shutdown_server`` parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - - Example - - Default - * - ``is_graceful`` - - Determines the method used to shut down the server. - - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. - - ``false`` - * - ``timeout`` - - Sets the maximum amount of minutes for the graceful shutdown method to run before the server is shut down using the standard method. - - ``30`` - - Five minutes. - -.. note:: Setting ``is_graceful`` to ``false`` and defining the ``timeout`` value shuts the server down mid-query after the defined time. - -It is possible to pass as the second argument the timeout in minutes after which a forceful shutdown will run after defining the graceful shutdown value, regardless of the progression of the graceful shutdown. - -Note that you set the timeout value using the ``defaultGracefulShutdownTimeoutMinutes`` flag in Studio. - -For more information, see :ref:`graceful_shutdown`. - -As with the ``shutdown_server`` command, the **graceful server shutdown** stops all queries currently running on your server. - -Permissions -============= -Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst new file mode 100644 index 000000000..ebc3d9184 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -0,0 +1,113 @@ +.. _shutdown_server_command: + +******************** +SHUTDOWN SERVER +******************** +The **SHUTDOWN_SERVER** guide describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +=============== +SQream's current method for stopping the SQream server is running the ``shutdown_server ()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown by setting it to ``select shutdown_server([is_graceful, [timeout]]);``. This causes the server to wait for any queued statements to complete before shutting down. + +How Does it Work? +======================== +Running the ``SHUTDOWN_SERVER`` command gives you more control over the following: + +* Preventing new queries from connecting to the server by: + + * Setting the server as unavailable in the metadata server. + + :: + + * Unsubscribing the server from its service. + +* Stopping users from making new connections to the server. Attempting to connect to the server after activating a graceful shutdown displays the following message: + + .. code-block:: postgres + + Server is shutting down, no new connections are possible at the moment. + +* The amount of time to wait before shutting down the server. + + :: + +* Configurations related to shutting down the server. + +Syntax +========== +The following is the syntax for using the ``SHUTDOWN_SERVER`` command: + +.. code-block:: postgres + + select shutdown_server([true/false, [timeout]]); + +Returns +========== +Running the ``shutdown_server`` command returns no output. + +Parameters +============ +The following table shows the ``shutdown_server`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Example + - Default + * - ``is_graceful`` + - Determines the method used to shut down the server. + - Selecting ``false`` shuts down the server while queries are running. Selecting ``true`` uses the graceful shutdown method. + - NA + * - ``timeout`` + - Sets the maximum amount of minutes for the graceful shutdown method to run before the server is shut down using the standard method. + - ``([is_graceful, [30]]);`` + - Five minutes + +.. note:: Setting ``is_graceful`` to ``false`` and defining the ``timeout`` value shuts the server down mid-query after the defined time. + +You can define the ``timeout`` argument as the amount minutes after which a forceful shutdown will run, even if a graceful shutdown is in progress. + +Note that activating a forced shutdown with a timeout, such as ``select shutdown_server(false, 30)``, outputs the following error message: + +.. code-block:: postgres + + forced shutdown has no timeout timer + +.. note:: You can set the timeout value using the ``defaultGracefulShutdownTimeoutMinutes`` flag in the Acceleration Studio. + +For more information, see :ref:`shutdown_server`. + +Examples +=================== +This section shows the following examples: + +**Example 1 - Activating a Forceful Shutdown** + +.. code-block:: postgres + + shutdown_server () + +**Example 2 - Activating a Graceful Shutdown** + +.. code-block:: postgres + + shutdown_server (true) + +**Example 3 - Overriding the timeout Default with Another Value** + +.. code-block:: postgres + + shutdown_server (500) + +The ``timeout`` unit is minutes. + +Permissions +============= +Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file diff --git a/sqream_studio_5.4.6/index.rst b/sqream_studio_5.4.6/index.rst deleted file mode 100644 index c4981ce81..000000000 --- a/sqream_studio_5.4.6/index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _sqream_studio_5.4.6: - -********************************** -SQream Acceleration Studio 5.4.6 -********************************** -The SQream Acceleration Studio is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. - -This section describes how to use the SQream Accleration Studio version 5.4.6: - -.. toctree:: - :maxdepth: 1 - :glob: - - getting_started_sqream - executing_statements_and_running_queries_from_the_editor - monitoring_workers_and_services_from_the_dashboard - viewing_logs - creating_assigning_and_managing_roles_and_permissions \ No newline at end of file diff --git a/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst new file mode 100644 index 000000000..3fcac7861 --- /dev/null +++ b/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst @@ -0,0 +1,23 @@ +.. _configuring_your_instance_of_sqream: + +**************************** +Configuring Your Instance of SQreams +**************************** +The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. + +Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. +Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. + +Editing Your Parameters +------------------------------- +When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. + +Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. + +You can hover over the **information** icon located on each parameter to read a short description of its behavior. + +Exporting and Importing Configuration Files +------------------------- +You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. + +For more information about configuring your instance of SQream, see :ref:`Configuration`. \ No newline at end of file diff --git a/sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst similarity index 97% rename from sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst rename to sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst index b87b6f2cf..9f0f7f39a 100644 --- a/sqream_studio_5.4.6/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst @@ -1,6 +1,6 @@ .. _creating_assigning_and_managing_roles_and_permissions: -.. _roles_5.4.6: +.. _roles_5.4.3: **************************** Creating, Assigning, and Managing Roles and Permissions @@ -32,7 +32,7 @@ The **Type** column displays one of the following assigned role types: .. note:: If you disable a password, when you enable it you have to create a new one. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Viewing Information About a Role @@ -49,7 +49,7 @@ Clicking a role in the roles table displays the following information: * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Creating a New Role @@ -73,7 +73,7 @@ From the New Role panel you view directly and indirectly (or inherited) granted When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Editing a Role -------------------- @@ -89,10 +89,10 @@ Once you've created a role, clicking the **Edit Role** button lets you do the fo From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Deleting a Role ----------------- Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file diff --git a/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst similarity index 86% rename from sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst rename to sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst index 8015b7c4a..0a298fdbf 100644 --- a/sqream_studio_5.4.6/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst @@ -1,6 +1,6 @@ .. _executing_statements_and_running_queries_from_the_editor: -.. _editor_top_5.4.6: +.. _editor_top_5.4.3: **************************** Executing Statements and Running Queries from the Editor @@ -14,6 +14,7 @@ The **Editor** is used for the following: The following is a brief description of the Editor panels: + .. list-table:: :widths: 10 34 56 :header-rows: 1 @@ -22,21 +23,23 @@ The following is a brief description of the Editor panels: - Element - Description * - 1 - - :ref:`Toolbar` + - :ref:`Toolbar` - Used to select the active database you want to work on, limit the number of rows, save query, etc. * - 2 - - :ref:`Database Tree and System Queries panel` + - :ref:`Database Tree and System Queries panel` - Shows a hierarchy tree of databases, views, tables, and columns * - 3 - - :ref:`Statement panel` + - :ref:`Statement panel` - Used for writing queries and statements * - 4 - - :ref:`Results panel` + - :ref:`Results panel` - Shows query results and execution information. -.. _top_5.4.6: -.. _studio_5.4.6_editor_toolbar: + +.. _top_5.4.3: + +.. _studio_5.4.3_editor_toolbar: Executing Statements from the Toolbar ================ @@ -70,16 +73,22 @@ You can access the following from the Toolbar pane: * **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. -For more information on stopping active statements, see the :ref:`SHUTDOWN_SERVER` command. -:ref:`Back to Executing Statements and Running Queries from the Editor` +For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. -.. _studio_5.4.6_editor_db_tree: +:ref:`Back to Executing Statements and Running Queries from the Editor` + + +.. _studio_5.4.3_editor_db_tree: Performing Statement-Related Operations from the Database Tree ================ From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). + + + + The database object functions are used to perform the following: * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. @@ -170,8 +179,7 @@ The database object functions are used to perform the following: .. |keep-tabs| image:: /_static/images/studio_keep_tabs.png :align: middle - - :ref:`insert` + .. list-table:: :widths: 30 70 @@ -180,23 +188,23 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an :ref:`insert` statement for the selected table in the editing area. + - Generates an `INSERT `_ statement for the selected table in the editing area. * - Delete statement - - Generates a :ref:`delete` statement for the selected table in the editing area. + - Generates a `DELETE `_ statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. + - Generates a `CREATE TABLE AS `_ statement for the selected table in the editing area. * - Rename statement - - Generates an :ref:`rename_table` statement for renaming the selected table in the editing area. + - Generates an `RENAME TABLE AS `_ statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an :ref:`add_column` statement for adding columns to the selected table in the editing area. + - Generates an `ADD COLUMN `_ statement for adding columns to the selected table in the editing area. * - Truncate table statement - - Generates a :ref:`truncate` statement for the selected table in the editing area. + - Generates a `TRUNCATE_IF_EXISTS `_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See :ref:`seeing_system_objects_as_ddl`. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -221,7 +229,7 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see :ref:`sql_best_practices`. +For more information, see `Optimization and Best Practices `_. Executing Pre-Defined Queries from the System Queries Panel --------------- @@ -235,7 +243,7 @@ The **System Queries** panel lets you execute predefined queries and includes th Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. -.. _studio_5.4.6_editor_statement_area: +.. _studio_5.4.3_editor_statement_area: Writing Statements and Queries from the Statement Panel ============== @@ -266,7 +274,8 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see :ref:`getting_started`. +.. tip:: If this is your first time using SQream, see `Getting Started `_. + .. Keyboard shortcuts .. ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -279,13 +288,13 @@ You can also rename the default tab name by double-clicking it and typing a new .. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab -.. _studio_editor_results_5.4.6: +.. _studio_editor_results_5.4.3: -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` -.. _studio_5.4.6_editor_results: +.. _studio_5.4.3_editor_results: -.. _results_panel_5.4.6: +.. _results_panel_5.4.3: Viewing Statement and Query Results from the Results Panel ============== @@ -301,17 +310,17 @@ The following is a brief description of the Results panel views highlighted in t * - Element - Description - * - :ref:`Results view` + * - :ref:`Results view` - Lets you view search query results. - * - :ref:`Execution Details view` + * - :ref:`Execution Details view` - Lets you analyze your query for troubleshooting and optimization purposes. - * - :ref:`SQL view` + * - :ref:`SQL view` - Lets you see the SQL view. -.. _results_view_5.4.6: +.. _results_view_5.4.3: -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` Searching Query Results in the Results View ---------------- @@ -329,7 +338,7 @@ Saving Results to the Clipboard ^^^^^^^^^^^^ The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. -.. _save_results_to_local_file_5.4.6: +.. _save_results_to_local_file_5.4.3: Saving Results to a Local File ^^^^^^^^^^^^ @@ -337,7 +346,7 @@ The **Save results to local file** functions lets you save your search query res In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. -.. _running_parallel_statements_5.4.6: +.. _running_parallel_statements_5.4.3: Running Parallel Statements ^^^^^^^^^^^^ @@ -355,11 +364,11 @@ The following shows the syntax for running parallel statements: $ $$ -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -.. _execution_details_view_5.4.6: +.. _execution_details_view_5.4.3: -.. _execution_tree_5.4.6: +.. _execution_tree_5.4.3: Execution Details View -------------- @@ -468,16 +477,16 @@ This can be seen in the **timeSum** column as follows: * **Rows highlighted orange** - medium runtime * **Rows highlighted yellow** - shortest runtime -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -.. _sql_view_5.4.6: +.. _sql_view_5.4.3: Viewing Wrapped Strings in the SQL View ------------------ The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. -.. _save_results_to_clipboard_5.4.6: +.. _save_results_to_clipboard_5.4.3: -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` diff --git a/sqream_studio_5.4.6/getting_started_sqream.rst b/sqream_studio_5.4.7/getting_started.rst similarity index 78% rename from sqream_studio_5.4.6/getting_started_sqream.rst rename to sqream_studio_5.4.7/getting_started.rst index ea95f0c41..7f401f5fa 100644 --- a/sqream_studio_5.4.6/getting_started_sqream.rst +++ b/sqream_studio_5.4.7/getting_started.rst @@ -1,13 +1,11 @@ -.. _getting_started_sqream: +.. _getting_started: **************************** -Getting Started with SQream Acceleration Studio 5.4.6 +Getting Started with SQream Acceleration Studio 5.4.3 **************************** Setting Up and Starting Studio ---------------- -Studio is included with all dockerized installations of SQream. When starting Studio, it listens on the local machine on port 8080. - -For more information, see :ref:`running_sqream_in_a_docker_container`. +Studio is included with all `dockerized installations of SQream DB `_. When starting Studio, it listens on the local machine on port 8080. Logging In to Studio --------------- @@ -45,6 +43,8 @@ From here you can navigate between the main areas of the Studio: - Lets you view usage logs. * - :ref:`Roles` - Lets you create users and manage user permissions. + * - :ref:`Configuration` + - Lets you configure your instance of SQream. By clicking the user icon, you can also use it for logging out and viewing the following: @@ -56,6 +56,6 @@ By clicking the user icon, you can also use it for logging out and viewing the f * License storage capacity * Log out -.. _back_to_dashboard_5.4.6: +.. _back_to_dashboard_5.4.3: -.. _studio_dashboard_5.4.6: +.. _studio_dashboard_5.4.3: diff --git a/sqream_studio_5.4.7/index.rst b/sqream_studio_5.4.7/index.rst new file mode 100644 index 000000000..d98df64d5 --- /dev/null +++ b/sqream_studio_5.4.7/index.rst @@ -0,0 +1,19 @@ +.. _sqream_studio_: + +********************************** +SQream Acceleration Studio +********************************** +The SQream Acceleration Studio 5.4.3 is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. + +This section describes how to use the SQream Accleration Studio version 5.4.3: + +.. toctree:: + :maxdepth: 1 + :glob: + + getting_started + monitoring_workers_and_services_from_the_dashboard + executing_statements_and_running_queries_from_the_editor + viewing_logs + creating_assigning_and_managing_roles_and_permissions + configuring_your_instance_of_sqream \ No newline at end of file diff --git a/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst similarity index 84% rename from sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst rename to sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst index 51dbb3941..4283f64a8 100644 --- a/sqream_studio_5.4.6/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst @@ -1,6 +1,6 @@ .. _monitoring_workers_and_services_from_the_dashboard: -.. _back_to_dashboard_5.4.6: +.. _back_to_dashboard_: **************************** Monitoring Workers and Services from the Dashboard @@ -27,24 +27,29 @@ The following is a brief description of the Dashboard panels: - Element - Description * - 1 - - :ref:`Services panel` + - :ref:`Services panel` - Used for viewing and monitoring the defined service queues. * - 2 - - :ref:`Workers panel` + - :ref:`Workers panel` - Monitors system health and shows each Sqreamd worker running in the cluster. * - 3 - - :ref:`License information` - - Shows the remaining amount of days left on your license. + - :ref:`License information` + - Shows the remaining amount of days left on your license. + + +.. _data_storage_panel_: + -.. _data_storage_panel_5.4.6: -:ref:`Back to Monitoring Workers and Services from the Dashboard` +:ref:`Back to Monitoring Workers and Services from the Dashboard` -.. _services_panel_5.4.6: +.. _services_panel_: Subscribing to Workers from the Services Panel -------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined in the :ref:`workload_manager`. +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues `_. + + The following is a brief description of each pane: @@ -73,23 +78,23 @@ You can add a service by clicking **+ Add** and defining the service name. You can manage workers from the **Workers** panel. For more information about managing workers, see the following: -* :ref:`Managing Workers from the Workers Panel` -* `Workers `_ +* :ref:`Managing Workers from the Workers Panel` +* `Workers `_ -:ref:`Back to Monitoring Workers and Services from the Dashboard` +:ref:`Back to Monitoring Workers and Services from the Dashboard` -.. _workers_panel_5.4.6: +.. _workers_panel_: Managing Workers from the Workers Panel ------------ From the **Workers** panel you can do the following: -* :ref:`View workers ` -* :ref:`Add a worker to a service` -* :ref:`View a worker's active query information` -* :ref:`View a worker's execution plan` +* :ref:`View workers ` +* :ref:`Add a worker to a service` +* :ref:`View a worker's active query information` +* :ref:`View a worker's execution plan` -.. _view_workers_5.4.6: +.. _view_workers_: Viewing Workers ^^^^^^^^ @@ -104,7 +109,7 @@ You can hover over segments in the status bar to see the date and time correspon * **Stopped** – the worker was stopped (either deliberately or due to an error). * **Waiting** – the worker was waiting on an object locked by another worker. -.. _add_worker_to_service_5.4.6: +.. _add_worker_to_service_: Adding A Worker to A Service ^^^^^^^^^^^^^^^^^^^^^ @@ -115,14 +120,14 @@ You can add a worker to a service by clicking the **add** button. Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. -.. _view_worker_query_information_5.4.6: +.. _view_worker_query_information_: Viewing A Worker's Active Query Information ^^^^^^^^^^^^^^^^^^^^^ You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. -Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. +Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan ` below. Viewing A Worker's Host Utilization ^^^^^^^^^^^^^^^^^^^^^ @@ -133,27 +138,20 @@ While viewing a worker's query information, clicking the **down arrow** expands The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. -Error notifications related to statements are displayed, and you can hover over them for more information about the error. +Error notifications related to statements are displayed, and you can hover over them for more information about the error. -.. _view_worker_execution_plan_5.4.6: + +.. _view_worker_execution_plan_: Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ + Clicking the ellipsis in a service shows the following additional options: * **Stop Query** - stops the query. - - :: - * **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. -For more information on the current query plan, see the following: - -* :ref:`show_node_info` - - :: - -* :ref:`show_server_status` +For more information on the current query plan, see `SHOW_NODE_INFO `_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS `_. .. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst :start-line: 67 @@ -161,10 +159,15 @@ For more information on the current query plan, see the following: Managing Worker Status ^^^^^^^^^^^^^^^^^^^^^ + In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. + Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. + + + .. |icon-user| image:: /_static/images/studio_icon_user.png :align: middle @@ -243,11 +246,11 @@ Starting or restarting workers terminates all queries related to that worker. Wh .. |keep-tabs| image:: /_static/images/studio_keep_tabs.png :align: middle -:ref:`Back to Monitoring Workers and Services from the Dashboard` +:ref:`Back to Monitoring Workers and Services from the Dashboard` -.. _license_information_5.4.6: +.. _license_information_: License Information ---------------------- @@ -259,4 +262,4 @@ The license information section shows the following: .. image:: /_static/images/license_storage_capacity.png -:ref:`Back to Monitoring Workers and Services from the Dashboard` +:ref:`Back to Monitoring Workers and Services from the Dashboard` diff --git a/sqream_studio_5.4.6/viewing_logs.rst b/sqream_studio_5.4.7/viewing_logs.rst similarity index 73% rename from sqream_studio_5.4.6/viewing_logs.rst rename to sqream_studio_5.4.7/viewing_logs.rst index 4b4654c4a..7f98bea5e 100644 --- a/sqream_studio_5.4.6/viewing_logs.rst +++ b/sqream_studio_5.4.7/viewing_logs.rst @@ -1,6 +1,6 @@ .. _viewing_logs: -.. _logs_top_5.4.6: +.. _logs_top_5.4.3: **************************** Viewing Logs @@ -13,20 +13,19 @@ The **Logs** screen is used for viewing logs and includes the following elements * - Element - Description - * - :ref:`Filter area` + * - :ref:`Filter area` - Lets you filter the data shown in the table. - * - :ref:`Query tab` + * - :ref:`Query tab` - Shows basic query information logs, such as query number and the time the query was run. - * - :ref:`Session tab` + * - :ref:`Session tab` - Shows basic session information logs, such as session ID and user name. - * - :ref:`System tab` + * - :ref:`System tab` - Shows all system logs. - * - :ref:`Log lines tab` + * - :ref:`Log lines tab` - Shows the total amount of log lines. -.. note:: Because the logs are stored in the **system** database, you cannot search the logs without first creating a **system** database. When you access the **Logs** tab, SQream can automatically create a **system** database for you. -.. _filter_5.4.6: +.. _filter_5.4.3: Filtering Table Data ------------- @@ -42,9 +41,9 @@ Other filters require you to select an item from a dropdown menu: You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. -.. _queries_5.4.6: +.. _queries_5.4.3: -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` Viewing Query Logs @@ -63,9 +62,9 @@ From the Queries area you can see and sort by the following: In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _sessions_5.4.6: +.. _sessions_5.4.3: Viewing Session Logs ---------- @@ -83,9 +82,9 @@ From here you can see and sort by the following: In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _system_5.4.6: +.. _system_5.4.3: Viewing System Logs ---------- @@ -99,6 +98,25 @@ From here you can see and sort by the following: In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _log_lines_5.4.6: \ No newline at end of file +.. _log_lines_5.4.3: + +Viewing All Log Lines +---------- +The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. + +From here you can see and sort by the following: + +* Timestamp +* Message level +* Worker hostname +* Worker port +* Connection ID +* Database name +* User name +* Statement ID + +In the **LOG LINES** table, you can click on any of the items to set them as your filters. + +:ref:`Back to Viewing Logs` \ No newline at end of file diff --git a/studio_login_5.3.2.png b/studio_login_5.3.2.png deleted file mode 100644 index e888aca13a8081b0ef7c196c969d1e4235845bd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 82674 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 z z#^BZp(NVV0FXLdEWXLqB#rBVC$V+2ddQW)^bWrnd9BYJ@i9GtWVL5cOm94S79@@r{ zdFdMPB-4A1I7XW51V(1IQ;xt7owIH47#~Q1BvkTdfYtR0JpZ;K=b!jbrKJ^VMKuna?Iz%Os!*SKn* zB>H<+-Asb7=Me0xdHEWoe1Bhdb&xYDJFNv{!XMW^Eh7+MUsT@dOE(CBy5=+_L0B2hYm)x-$Kvw$CxcJeLPMC zCXNbf0522oV3HfoS!X6@rCp+06hW;3=*(jc0JGHVT67*jc>w%S2P9X54l0}04NDs{ zi^LR{r-8XNrk_3LJ-vy$OBQ&@SQ6FPSAjcn>ifP1ZI@7+RlqtcM+FL&!FHhvGp;3V z71$VYZxG$^MG$_QqYeFKz@z&LL8-wz@VW*XkWdkrA^o&q_2`9DA2qca`;F~Y;$n)q z&KL%G)EU1+a+w&Df!bFKEH9_XO?h;9P>I0B2QHc{PP?TWo_0n;)xt!vmm|#lSKb7H z%p?XG{SScK-~vlbcCQ$)o5TS6tl=VXcVfN{9)Vn!0e{w!`ev=2%hC6q9;ycnc0Vey zu&;^&C&CZMCPRTx80@^`q675{(vQK6N2_^yplBxr#INK(2JrHK{+FZ@g%x8B9d?OK$iQK~4#N+@iy&s4@2i%~J}m9#k1pMKG*N6yW8F{j)?q~^vhMqm7{HAUWq_rTSzUGtAzupKKrccvcr!qVc%Kn zvRjUbd%vNPXOh1ouMJ;p)zh*5ak($Ce8?GbdM3sw0aBu{FIKm40omAL%9TK#$_l%q zecah_(1Uy_;l7Rq`4Z)nIc2j{nKMF$;M}O0EcW0_;l%8f6p3qR(7We}^%Jh&v!~qb zrJsLKSI0#e83<~j7fcD$oUpRRvxKIeaHi*}B}md)51DrrBmp9;Acy z0(S*lZ!%9?Q^08vA^GVuSW={NUY>*&19)?sNIc z?@L&E-tu3-@|?sN`@>2=qT?g^&Fe8dgWw{U2OD%_12}^@!~}VKbMV^E%F+zC1ujsBm?%7?y#e(z|XyN<=+4g!f9k&KZsdVSg}MmkkkBifNA4Y+8U zJms_JPsr~REP8Y@@||P#P^5WA)_Su&%=LPJn}1zOp(y4R=Jc6Tw(mh4NRegGk3l)$7ROVak>}4)pGxpxue)IdmS{vE5HDK`IooQ7g8hf{>qapj$!pG z_FSiKa~p((6#?*Q&m*V+_<{kFOb0ph;H?mEh?j+Y6<_3NmS~eGjHx}^oyCCEngQ$) zlRCIa6kig(Oc^!#6z~Bv+*01x#IQR6^TpTY533J2PejU~!7@5s{dPbu<|!vVi5|-% zk{GBgcJ}A&d#>1M5SDb@KQiBmB!sn0hcLz>d__a{Fz=C_Gs90M!~p1rXOby9E+q@x z5rsywcCM3-8{|S2XYFM977v@}LlX&kGukn8ckY8Je+dHGnnJoW2ZPrnN=txAg?3tM*m`l0WEsZdlPE#vq>cjWD7ZGBvS ze(Gb!rXw-S1$j>eqV;pzo33lY4XC!rd`)}|1hkamIy+U+zP|KxSRIUf)HXwg`X@|b zzOV^c9s^0Em0Dn5XEz55l(`#X4yRAnBP1*)u2I+~AonGRr2+;tAe<$7Cim z>q*e0FnA_Dq0PFqXttO!K+N(a{eTI{;{+m^->L-yT@16BU0ym8``qC4YnqesVG>>I}rrRP*OLB z_=*ekwsrNQSxrILd-h!nI5LN6M<&>c-d!0Od=npc=kym&lUG$2x_gL!6FmEm<%ybm z-g-8EzIbs`Z#}_2=0Q;;WZt71d=8Gf@m)Okv`7MF;v+v|@-$pyd@D+e^;wDfX_Zr$ zN}sB4NSU%Jxddk<>yaub7_ImlBdXu+z%tPHC=JBZL9)qXu6}jtzz>&L>V8@+10wc0 z7NlO^1T^{2*=BVQkdN2Mm*gsLsY7yA<5oq;vY$x;u{FHb$$-$cC_(}=teHjdkIOGi zH&;RkN_cF8m|`sEm6@&L)W%Q!(?U^|&7Kte+XEz-lT94dYb^jPg}=9tPQ z{=_{m0w_XWUK}_rS1B*$UifIpGMtyp$TM~$x$2Vvr9KV36I(`daL}tY>0u7m_b(3d zr96d(bF2<+%=;&--j-oFbFgR8IG7Z}bEFN@aiO(yT+VJ0&8{qAtl#WBz~bJf6=@X- zZp5fa;I(u#!l}Tq1M0-K(Haum|_I-4{3FMwGws^cl#1T zZ(lUILyZ!4F>Da`7~!CVMj{Z6N9U;WD9=SgnRKaSM% zU>wO?`=tiVq|g6!y;=+=A+puUY);4~IUPyHhpsX9pZ(s0(E@1K++zg&;D>GyZB5gA z-yBpdK_IXQgcACZ(iU2&p)Ao44l-?d3t0xYuXN()bjKR+dT_25FMvg_T3#5Z7C-`@ z5x7b}8!t|KhH@bYT&7$!x?k=rHd@9=@fWz~T4kKdjr|UQ60RJYdIoy+JK0fu;-1-? zdXg)7Bl=idCNL-OFwb;1zTX@6*7Xa=A=oXWW>xnbvH%Wl`)(R2$n5ZE-X*vPSkO3f zuJ)fLaLI>FT**$<+y!~yz=4Stg)FZa$D*6+qf#m0|Ner7sXXj*8OYrD3H`01J@LWs z6y8q(Bw)MJ>^udMXu%oJ`6hB7ODjgr^+<4 zB1Eggf3HC=hDbiSv#>F%SQ$TU*5D(PrO;fnzesqKW7D{@Mu;7Mw7>4vyfIJR>o%e8 z(~a*ZQkQe~B5~AU>W3wi%;a}EfF!VI^dPFvt)_>L2m_UkzuL8BkZ7H?{M29`??9M( z%)P;Z?z`~}!m((0HaiRl+ugb7XD38wu=iVjw6gQhrL9|$+bhvrDiP(bF1n$#beq%Z z>Q)NRAYm!z?z5njQa^M&f)DV-iF~4{V};=g*Uo^$MKn$b&|mK*d6-X#OZ9Ml%2)p; z_^kZ-$*=G;HW3hYz?cVvAZ2#LcjZ@j_mb5?W`o8er32k(mavUhP<*yLp-=L(I3WXk zJEQ&6Zr$w{j4sD|Uok>~LVd&@`AMGyXfz4P%Uc2OmitB|pFnob1G2=)K*U*weDD^d6OK}(KW-p6hA9-!d6i3fd4`@6VJHa_@HBuaAY z`eYe8B=F-o5bhJO71}phT!&j6P8m}?P&(7%D*pScw`^y79Zp@RstTfHk4GFdxBmhD N=x7;gma5x^{U4w+h_wI! From 0cef12c3b0f362021ba13c4602df8517cd31959a Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 13:33:25 +0300 Subject: [PATCH 0217/1892] Updated with Dor. --- feature_guides/query_healer.rst | 42 +++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 0180150ea..f8bb7f694 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -11,42 +11,48 @@ The **Query Healer** page describes the following: Overview ---------- -The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. The following is an example of a log record for a query stuck in the query detection phase for more than five hours: .. code-block:: console - 2022/05/19::20:01:25|ERROR|Healer|(0x7f07147fc700)|Stuck query found. Statement ID: 72, Last chunk producer updated: 1 WriteTable, Started on: Thu May 19 14:01:25 2022, Last updated: Thu May 19 15:01:25 2022, Stuck time: 5 hours, Max allowed stuck query time: 5 hours + |INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1. -The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. +Once you identify the stuck worker, you can execute the ``shutdown_server`` utility function from this specific worker, as described in the next section. -Configuring the Healer +Activating a Graceful Shutdown ------------------ -The following **Administration Worker** flags are required to configure the Query Healer: - - * :ref:`is_healer_on` - Enables the Query Healer. +You can activate a graceful shutdown if your log entry says ``Stuck query found``, as shown in the example above. You can do this by setting the **shutdown_server** utility function to ``select shutdown_server();``. - :: +**To activte a graceful shutdown:** - * :ref:`healer_max_inactivity_hours` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. +1. Locate the IP and the Port of the stuck worker from the logs. -The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. For example, setting ``healerMaxInactivityHours`` to five hours (the default setting) triggers an examination every 15 minutes. + .. note:: The log in the previous section identifies the IP **(192.168.4.65)** and port **(5001)** referring to the stuck query. -Activating a Graceful Shutdown ------------------- -If your log entry says ``Stuck query found``, you must set the **shutdown_server** utility function to ``select shutdown_server(true);``, as in the following example: +2. From the machine of the stuck query (IP: **192.168.4.65**, port: **5001**), connect to SQream SQL client: -.. code-block:: console + .. code-block:: console - |INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1. + ./sqream sql --port=$STUCK_WORKER_IP --username=$SQREAM_USER --password=$SQREAM_PASSWORD databasename=$SQREAM_DATABASE -Note that the log above identifies the IP (192.168.4.65) and port (5001) referring to the stuck query. +3. Execute ``shutdown_server``. For more information, see the following: -* Activating the :ref:`shutdown_server_command` utility function. +* Activating the :ref:`shutdown_server_command` utility function. This page describes all of ``shutdown_server`` options. :: -* Configuring the :ref:`shutdown_server` flag. \ No newline at end of file +* Configuring the :ref:`shutdown_server` flag. + +Configuring the Healer +------------------ +The following **Administration Worker** flags are required to configure the Query Healer: + + * :ref:`is_healer_on` - Enables the Query Healer. + + :: + + * :ref:`healer_max_inactivity_hours` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. \ No newline at end of file From 5bdfefd47bfd95612a17b90079eb729a8a6756f3 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 14:03:40 +0300 Subject: [PATCH 0218/1892] Enhanced Automatic Adaptive Compression --- releases/2022.1.2.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index d94916d02..389925e9d 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -23,15 +23,11 @@ The 2022.1.2 Release Notes include the following new features: :local: :depth: 1 -Feature 1 +Enhanced Automatic Adaptive Compression ************ - +SQream's automatic adaptive compression has been enhanced with new compression methods. This mechanism automatically uses the best compression method for each scenario, improving the compression ratio by approximately twice of that in Version 2022.1 -For more information, see - -Feature 2 -************ - +.. note:: The compression ratio is highly dependent on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. For more information, see From a14f6692dcedd72e7fc1e1a02590914cdd00450e Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 14:38:55 +0300 Subject: [PATCH 0219/1892] Updated - not done --- feature_guides/compression.rst | 39 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 4472c7ded..d39cf2df4 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -3,43 +3,37 @@ *********************** Compression *********************** +The **Compression** page describes the following: + +.. contents:: + :local: + :depth: 1 .. |icon-new_dark_gray_2022.1.1.png| image:: /_static/images/new_dark_gray_2022.1.1.png :align: middle :width: 110 -SQream DB uses compression and encoding techniques to optimize query performance and save on disk space. +SQream uses a variety of compression and encoding methods to optimize query performance and to save disk space. Encoding ============= +**Encoding** is an automatic operation used to convert data into common formats. For example, certain formats are often used for data stored in columnar format, in contrast with data stored in a CSV file, which stores all data in text format. -Encoding converts data into a common format. - -When data is stored in a columnar format, it is often in a common format. This is in contrast with data stored in CSVs for example, where everything is stored in a text format. - -Because encoding uses specific data formats and encodings, it increases performance and reduces data size. +Encoding enhances performance and reduces data size by using specific data formats and encoding methods. SQream encodes data in a number of ways in accordance with the data type. For example, a **date** is stored as an **integer**, starting with **March 1st 1CE**, which is significantly more efficient than encoding the date as a string. In addition, it offers a wider range than storing it relative to the Unix Epoch. -SQream DB encodes data in several ways depending on the data type. For example, a date is stored as an integer, with March 1st 1CE as the start. This is a lot more efficient than encoding the date as a string, and offers a wider range than storing it relative to the Unix Epoch. - -Compression +Lossless Compression ============== +**Compression** transforms data into a smaller format without sacrificing accuracy, known as **lossless compression**. -Compression transforms data into a smaller format without losing accuracy (lossless). - -After encoding a set of column values, SQream DB packs the data and compresses it. +After encoding a set of column values, SQream packs the data and compresses it and decompresses it to make it accessible to users. Depending on the compression scheme used, these operations can be performed on the CPU or the GPU. Some users find that GPU compressions provide better performance. -Before data can be accessed, SQream DB needs to decompress it. - -Depending on the compression scheme, the operations can be performed on the CPU or the GPU. Some users find that GPU compressions perform better for their data. - -Automatic compression +Automatic Compression ------------------------ - -By default, SQream DB automatically compresses every column (see :ref:`Specifying compressions` below for overriding default compressions). This feature is called **automatic adaptive compression** strategy. +By default, SQream automatically compresses every column (see :ref:`Specifying compressions` below for overriding default compressions). This feature is called **automatic adaptive compression** strategy. When loading data, SQream DB automatically decides on the compression schemes for specific chunks of data by trying several compression schemes and selecting the one that performs best. SQream DB tries to balance more agressive compressions with the time and CPU/GPU time required to compress and decompress the data. -Compression strategies +Compression Methods ------------------------ .. list-table:: @@ -93,6 +87,11 @@ Compression strategies - Integer types - Optimized RLE + Delta type for built-in :ref:`identity columns`. - GPU + * - ``zlib`` + - All types + - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. + + .. note:: Automatic compression does not select the **zlib** compression method. .. _specifying_compressions: From 7211281d357cec3d1fcac84a10a2ab54fdd394e8 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 20:32:06 +0300 Subject: [PATCH 0220/1892] Restored additional Update functionality I removed this all per Ben Esh's request before publishing 2022.1.1, with the intent to restore it in the next release. as was done here. --- .../sql_statements/dml_commands/update.rst | 119 +++++++++++++++--- 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 873cf6290..9f1d321b9 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -5,7 +5,7 @@ UPDATE ********************** The **UPDATE** statement page describes the following: -.. |icon-new_2022.1.1| image:: /_static/images/new_2022.1.1.png +.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png :align: middle :width: 110 @@ -15,7 +15,7 @@ The **UPDATE** statement page describes the following: Overview ========== -The ``UPDATE`` command is used to modify the value of certain columns in existing rows without creating a table. +The ``UPDATE`` statement is used to modify the value of certain columns in existing rows without creating a table. It can be used to do the following: @@ -27,6 +27,8 @@ It can be used to do the following: .. warning:: Using the ``UPDATE`` command on column clustered using a cluster key can undo your clustering. +The ``UPDATE`` statement cannot be used to reference other tables in the ``WHERE`` or ``SET`` clauses. + Syntax ========== The following is the correct syntax for the ``UPDATE`` command: @@ -35,8 +37,8 @@ The following is the correct syntax for the ``UPDATE`` command: UPDATE target_table_name [[AS] alias1] SET column_name = expression [,...] - [FROM additional_table_name [[AS] alias2][,...]] - [WHERE condition] + [FROM additional_table_name [[AS] alias2][,...]] + [WHERE condition] The following is the correct syntax for triggering a clean-up: @@ -44,7 +46,6 @@ The following is the correct syntax for triggering a clean-up: SELECT cleanup_chunks('schema_name','table_name'); SELECT cleanup_extents('schema_name','table_name'); - SELECT cleanup_discarded_chunks(‘public’,’t’); Parameters ============ @@ -61,13 +62,11 @@ The following table describes the ``UPDATE`` parameters: * - ``column_name`` - Specifies the column containing the data to be updated. * - ``additional_table_name`` - - Specifies the column containing the data to be updated. + - Additional tables used in the WHERE condition for performing complex joins. * - ``condition`` - Specifies the condition for updating the data. -.. note:: A single table can appear **both** as a ``DELETE`` target *and* as a ``FROM`` table. This can be useful for deleting data based on self-join conditions. A ``SET`` clause can contain columns from tables specified in a ``FROM`` clause. For example, using the join ``WHERE`` condition updates rows in the target tables with the values of one of the matching rows. - -.. note:: Similar to a ``DELETE`` statement, an ``UPDATE`` statement may leave some uncleaned data behind, which requires a clean-up operation. +.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. Examples =========== @@ -76,7 +75,31 @@ The **Examples** section includes the following examples: .. contents:: :local: :depth: 1 - + +Updating an Entire Table +----------------- +The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: + +.. image:: /_static/images/delete_optimization.png + +The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 WHERE true; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries; + +.. code-block:: postgres + + UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; + Performing Simple Updates ----------------- The following is an example of performing a simple update: @@ -84,15 +107,73 @@ The following is an example of performing a simple update: .. code-block:: postgres UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; + +Updating Tables that Contain Multi-Table Conditions +----------------- +The following shows an example of updating tables that contain multi-table conditions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + 1 + WHERE EXISTS ( + SELECT 1 FROM countries + WHERE countries.id=bands.country_id + AND country.name = 'Sweden' + ); + +You can also write the statement above using the FROM clause: + +.. code-block:: psql + + UPDATE bands + SET records_sold = records_sold + 1 + FROM countries + WHERE countries.id=bands.country_id AND country.name = 'Sweden'; + +Updating Tables that Contain Multi-Table Expressions +----------------- +The following shows an example of updating tables that contain multi-table expressions: + +.. code-block:: postgres + + UPDATE bands + SET records_sold = records_sold + + CASE + WHEN c.name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c -Triggering a Clean-Up +Configuring Update Behavior ----------------- -The following section shows an example of triggering a clean-up: +The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. + +For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. + +When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). + +You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. + +Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: + +.. code-block:: postgres + + UPDATE bands + SET record_count = record_count + 1 + FROM countries c + WHERE c.name = 'Israel' + +However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. + +Triggering a Clean-Up +--------------------------------------- +The following shows an example of triggering a clean-up: .. code-block:: psql SELECT * FROM sqream_catalog.discarded_chunks; - SELECT cleanup_discarded_chunks('public','t'); + SELECT cleanup_discarded_chunks('public','t'); The following is an example of the output generated from the above: @@ -100,14 +181,14 @@ The following is an example of the output generated from the above: * **table_id** - 24 * **column_id** - 1 * **extent_ID** - 0 - -Locking and Concurrency -============= -Executing the ``UPDATE`` statement obtains an exclusive ``UPDATE`` lock on the target table. - + Permissions ============= Executing an ``UPDATE`` statement requires the following permissions: * Both ``UPDATE`` and ``SELECT`` permissions on the target table. -* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). \ No newline at end of file +* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). + +Locking and Concurrency +============= +Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file From f1086363b279effae9cad39a60944b291d6e5e1c Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 21:10:39 +0300 Subject: [PATCH 0221/1892] 2022.1.2 - Updated Compression Page Compression: added zlib method 2022.1.2 RN page: added link to Compression page --- feature_guides/compression.rst | 113 +++++++++++++++++---------------- releases/2022.1.2.rst | 9 ++- 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index d39cf2df4..b44d78cf8 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -29,29 +29,30 @@ After encoding a set of column values, SQream packs the data and compresses it a Automatic Compression ------------------------ -By default, SQream automatically compresses every column (see :ref:`Specifying compressions` below for overriding default compressions). This feature is called **automatic adaptive compression** strategy. +By default, SQream automatically compresses every column (see :ref:`Specifying Compression Strategies` below for overriding default compressions). This feature is called **automatic adaptive compression** strategy. When loading data, SQream DB automatically decides on the compression schemes for specific chunks of data by trying several compression schemes and selecting the one that performs best. SQream DB tries to balance more agressive compressions with the time and CPU/GPU time required to compress and decompress the data. Compression Methods ------------------------ +The following table shows the available compression methods: .. list-table:: :widths: auto :header-rows: 1 - * - Compression name - - Supported data types + * - Compression Method + - Supported Data Types - Description - Location * - ``FLAT`` - All types - No compression (forced) - - - + - NA * - ``DEFAULT`` - All types - Automatic scheme selection - - - + - NA * - ``DICT`` - Integer types, dates and timestamps, short texts - @@ -89,23 +90,26 @@ Compression Methods - GPU * - ``zlib`` - All types - - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - - .. note:: Automatic compression does not select the **zlib** compression method. + - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. + - **Comment - GPU, CPU?** + +.. note:: Automatic compression does not select the **zlib** compression method. .. _specifying_compressions: -Specifying compression strategies +Specifying Compression Strategies ---------------------------------- +When you create a table without defining any compression specifications, SQream defaults to automatic adaptive compression (``"default"``). However, you can prevent this by specifying a compression strategy when creating a table. -When creating a table without any compression specifications, SQream DB defaults to automatic adaptive compression (``"default"``). +This section describes the following compression strategies: -However, this can be overriden by specifying a compression strategy when creating a table. +.. contents:: + :local: + :depth: 1 -Explicitly specifying automatic compression +Explicitly Specifying Automatic Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The following two are equivalent: +When you explicitly specify automatic compression, the following two are equivalent: .. code-block:: postgres @@ -123,11 +127,11 @@ In this version, the default compression is specified explicitly: y TEXT(50) CHECK('CS "default"') ); -Forcing no compression (flat) +Forcing No Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +**Forcing no compression** is also known as "flat", and can be used in the event that you want to remove compression entirely on some columns. This may be useful for reducing CPU or GPU resource utilization at the expense of increased I/O. -In some cases, you may wish to remove compression entirely on some columns, -in order to reduce CPU or GPU resource utilization at the expense of increased I/O. +The following is an example of removing compression: .. code-block:: postgres @@ -136,14 +140,9 @@ in order to reduce CPU or GPU resource utilization at the expense of increased I y TEXT(50) -- This column will still be compressed automatically ); - -Forcing compressions +Forcing Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In some cases, you may wish to force SQream DB to use a specific compression scheme based -on your knowledge of the data. - -For example: +In other cases, you may want to force SQream to use a specific compression scheme based on your knowledge of the data, as shown in the following example: .. code-block:: postgres @@ -154,13 +153,19 @@ For example: ); - -Examining compression effectiveness +Examining Compression Effectiveness -------------------------------------- +Queries made on the internal metadata catalog can expose how effective the compression is, as well as what compression schemes were selected. -Queries to the internal metadata catalog can expose how effective the compression is, as well as what compression schemes were selected. +This section describes the following: -Here is a sample query we can use to query the catalog: +.. contents:: + :local: + :depth: 1 + +Querying the Catalog +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following is a sample query that can be used to query the catalog: .. code-block:: postgres @@ -181,7 +186,9 @@ Here is a sample query we can use to query the catalog: GROUP BY 1, 2; -Example (subset) from the ``ontime`` table: +Example Subset from "Ontime" Table +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following is an example (subset) from the ``ontime`` table: .. code-block:: psql @@ -271,43 +278,43 @@ Example (subset) from the ``ontime`` table: uniquecarrier | dict | 578221 | 7230705 | 11.96 | default year | rle | 6 | 2065915 | 317216.08 | default - -Notes on reading this table: +Notes on Reading the "Ontime" Table ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following are some useful notes on reading the "Ontime" table shown above: -#. Higher numbers in the *effectiveness* column represent better compressions. 0 represents a column that wasn't compressed at all. +#. Higher numbers in the **Compression effectiveness** column represent better compressions. **0** represents a column that has **not been compressed**. -#. Column names are the internal representation. Names with ``@null`` and ``@val`` suffixes represent a nullable column's null (boolean) and values respectively, but are treated as one logical column. + :: +#. Column names are an internal representation. Names with ``@null`` and ``@val`` suffixes represent a nullable column's null (boolean) and values respectively, but are treated as one logical column. + + :: + #. The query lists all actual compressions for a column, so it may appear several times if the compression has changed mid-way through the loading (as with the ``carrierdelay`` column). -#. When ``default`` is the compression strategy, the system automatically selects the best compression. This can also mean no compression at all (``flat``). + :: + +#. When your compression strategy is ``default``, the system automatically selects the best compression, including no compression at all (``flat``). -Compression best practices +Best Practices ============================== +This section describes the best compression practices: -Let SQream DB decide on the compression strategy +.. contents:: + :local: + :depth: 1 + +Letting SQream Determine the Best Compression Strategy ---------------------------------------------------- +In general, SQream determines the best compression strategy for most cases. If you decide to override SQream's selected compression strategies, we recommend benchmarking your query and load performance **in addition to** your storage size. -In general, SQream DB will decide on the best compression strategy in most cases. - -When overriding compression strategies, we recommend benchmarking not just storage size but also query and load performance. - - -Maximize the advantage of each compression schemes +Maximizing the Advantage of Each Compression Scheme ------------------------------------------------------- - -Some compression schemes perform better when data is organized in a specific way. - -For example, to take advantage of RLE, sorting a column may result in better performance and reduced disk-space and I/O usage. +Some compression schemes perform better when data is organized in a specific way. For example, to take advantage of RLE, sorting a column may result in better performance and reduced disk-space and I/O usage. Sorting a column partially may also be beneficial. As a rule of thumb, aim for run-lengths of more than 10 consecutive values. -Choose data types that fit the data +Choosing Data Types that Fit Your Data --------------------------------------- +Adapting to the narrowest data type improves query performance while reducing disk space usage. However, smaller data types may compress better than larger types. -Adapting to the narrowest data type will improve query performance and also reduce disk space usage. -However, smaller data types may compress better than larger types. - -For example, use the smallest numeric data type that will accommodate your data. Using ``BIGINT`` for data that fits in ``INT`` or ``SMALLINT`` can use more disk space and memory for query execution. - -Using ``FLOAT`` to store integers will reduce compression's effectiveness significantly. \ No newline at end of file +For example, SQream recommends using the smallest numeric data type that will accommodate your data. Using ``BIGINT`` for data that fits in ``INT`` or ``SMALLINT`` can use more disk space and memory for query execution. Using ``FLOAT`` to store integers will reduce compression's effectiveness significantly. \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 389925e9d..c16b551a7 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -13,7 +13,7 @@ Version Content ---------- The 2022.1.2 Release Notes describes the following: -* Enhanced security features. +* Enhanced compression features. New Features ---------- @@ -27,9 +27,12 @@ Enhanced Automatic Adaptive Compression ************ SQream's automatic adaptive compression has been enhanced with new compression methods. This mechanism automatically uses the best compression method for each scenario, improving the compression ratio by approximately twice of that in Version 2022.1 -.. note:: The compression ratio is highly dependent on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. +.. note:: The compression ratio depends on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. -For more information, see +For more information, see :ref:`compression`. + +Parquet Read Optimization +************ Known Issues --------- From df0612b0bbcc2bfe8b6fd51e34ff0b4ac181efaa Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 21:21:10 +0300 Subject: [PATCH 0222/1892] 2022.1.2 - Provided Parquet Read Optimization PRD Link --- releases/2022.1.2.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index c16b551a7..7338c410f 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -29,10 +29,12 @@ SQream's automatic adaptive compression has been enhanced with new compression m .. note:: The compression ratio depends on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. -For more information, see :ref:`compression`. +For more information, navigate to the **Compression Methods** table on the :ref:`compression` page. Parquet Read Optimization -************ +************ + +https://sqream.atlassian.net/wiki/spaces/PRODUCT/pages/2277998593/Parquet+read+optimization Known Issues --------- From c19e76e3b47d6efb3b507b1cacf60375836f0ddf Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 15 Aug 2022 23:50:36 +0300 Subject: [PATCH 0223/1892] 2022.1.2 - Update in progress --- ...automatic_foreign_table_ddl_resolution.rst | 46 +++++++++++++++++++ feature_guides/index.rst | 1 + releases/2022.1.2.rst | 6 +++ 3 files changed, 53 insertions(+) create mode 100644 feature_guides/automatic_foreign_table_ddl_resolution.rst diff --git a/feature_guides/automatic_foreign_table_ddl_resolution.rst b/feature_guides/automatic_foreign_table_ddl_resolution.rst new file mode 100644 index 000000000..3ce1cc49f --- /dev/null +++ b/feature_guides/automatic_foreign_table_ddl_resolution.rst @@ -0,0 +1,46 @@ +.. _automatic_foreign_table_ddl_resolution: + +*********************** +Automatic Foreign Table DDL Resolution +*********************** +The **Automatic Foreign Table DDL Resolution** page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +---------- +SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. + +Usage Notes +---------- +The automatic foreign table DDL resolution feature supports Parquet, ORC, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. + +Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. + +.. note:: When using this feature, SQream assumes that all files in the path use the same schema. + +Syntax +---------- +The following is the syntax for using the automatic foreign table DDL resolution feature: + +.. code-block:: console + + CREATE FOREIGN TABLE table_name + [FOREIGN DATA] WRAPPER fdw_name + [OPTIONS (...)]; + +Example +---------- +The following is an example of using the automatic foreign table DDL resolution feature: + +.. code-block:: console + + create foreign table parquet_table + wrapper parquet_fdw + options (location = '/tmp/file.parquet'); + +Permissions +---------- +The automatic foreign table DDL resolution feature requires **Read** permissions. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index d70ceb705..abb975c5d 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -11,6 +11,7 @@ This section describes the following features: :maxdepth: 1 :titlesonly: + automatic_foreign_table_ddl_resolution query_healer data_encryption compression diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 7338c410f..b5bbb34f0 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -23,6 +23,12 @@ The 2022.1.2 Release Notes include the following new features: :local: :depth: 1 +Automatic Foreign Table DDL Resolution +************ +When mapping external files to foreign tables, SQream now automatically identifies the required schema. This is especially useful for Parquet files, which include built-in schema declarations. + +For more information, see :ref:`automatic_foreign_table_ddl_resolution`. + Enhanced Automatic Adaptive Compression ************ SQream's automatic adaptive compression has been enhanced with new compression methods. This mechanism automatically uses the best compression method for each scenario, improving the compression ratio by approximately twice of that in Version 2022.1 From a6c452e77bdab2449177def5b1306f646d43e005 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 11:31:23 +0300 Subject: [PATCH 0224/1892] Documented Parquet Optimization --- data_ingestion/avro.rst | 2 +- data_ingestion/parquet.rst | 153 +++++++++--------- external_storage_platforms/index.rst | 2 + .../storing_data_on_parquet.rst | 8 + feature_guides/compression.rst | 3 +- releases/2022.1.2.rst | 3 +- 6 files changed, 89 insertions(+), 82 deletions(-) create mode 100644 external_storage_platforms/storing_data_on_parquet.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index b20e64d49..7679df816 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -352,7 +352,7 @@ The following is an example of loading a table from a directory of Avro files on CREATE TABLE users AS SELECT * FROM ext_users; -For more configuration option examples, see the `CREATE FOREIGN TABLE parameters `_. +For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. Loading a Table from a Directory of Avro Files on S3 -------------- diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index c5971e064..36ad8c613 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -3,16 +3,19 @@ ********************** Inserting Data from a Parquet File ********************** +This guide covers inserting data from Parquet files into SQream using :ref:`FOREIGN TABLE`, and describes the following; -This guide covers inserting data from Parquet files into SQream DB using :ref:`FOREIGN TABLE`. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 -1. Prepare the files -===================== +Overview +=================== +As described in **Inserting Data from a Parquet File** section, you can insert data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of inserting it into SQream. SQream supports executing queries on external Parquet files. -Prepare the source Parquet files, with the following requirements: +Preparing Your Parquet Files +===================== +Prepare your source Parquet files according to the requirements described in the following table: .. list-table:: :widths: 40 5 20 20 20 20 5 5 5 5 10 @@ -120,7 +123,7 @@ Prepare the source Parquet files, with the following requirements: - - Supported [#f4]_ -* If a Parquet file has an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not Supported, but the column may be ommited. This can be worked around. See more information in the examples. +* Your statements will succeed even if your Parquet file contains an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query). If the column containing the unsupported type is referenced, an error message is displayed explaining that the type is not supported and that the column may be ommitted. For solutions to this error message, see more information in **Managing Unsupported Column Types** example in the **Example** section. .. rubric:: Footnotes @@ -132,35 +135,28 @@ Prepare the source Parquet files, with the following requirements: .. [#f4] Any microseconds will be rounded down to milliseconds. -2. Place Parquet files where SQream DB workers can access them +Making Parquet Files Accessible to Workers ================================================================ - -Any worker may try to access files (unless explicitly speficied with the :ref:`workload_manager`). -It is important that every node has the same view of the storage being used - meaning, every SQream DB worker should have access to the files. +To give workers access to files every node must have the same view of the storage being used. * For files hosted on NFS, ensure that the mount is accessible from all servers. -* For HDFS, ensure that SQream DB servers can access the HDFS name node with the correct user-id. See our :ref:`hdfs` guide for more information. +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct user-id. For more information, see :ref:`hdfs` guide for more information. -* For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3` guide for more information. - -3. Figure out the table structure +Creating a Table =============================================== +Before loading data, you must build the CREATE TABLE to correspond with the file structure of the inserted table. -Prior to loading data, you will need to write out the table structure, so that it matches the file structure. - -For example, to import the data from ``nba.parquet``, we will first look at the source table: +The example in this section is based on the source nba.parquet table shown below: .. csv-table:: nba.parquet :file: nba-t10.csv :widths: auto :header-rows: 1 -* The file is stored on S3, at ``s3://sqream-demo-data/nba.parquet``. - - -We will make note of the file structure to create a matching ``CREATE EXTERNAL TABLE`` statement. +The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the nba.parquet table: .. code-block:: postgres @@ -182,71 +178,53 @@ We will make note of the file structure to create a matching ``CREATE EXTERNAL T LOCATION = 's3://sqream-demo-data/nba.parquet' ); -.. tip:: - - Types in SQream DB must match Parquet types exactly. - - If the column type isn't Supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. - - -4. Verify table contents -==================================== - -External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. - -.. code-block:: psql - - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 +.. tip:: An exact match must exist between the SQream and Parquet types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. -If any errors show up at this stage, verify the structure of the Parquet files and match them to the external table structure you created. +.. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. -5. Copying data into SQream DB +Ingesting Data into SQream =================================== +This section describes the following: -To load the data into SQream DB, use the :ref:`create_table_as` statement: +.. contents:: + :local: + :depth: 1 + +Syntax +----------- +You can use the :ref:`create_table_as` statement to load the data into SQream, as shown below: .. code-block:: postgres CREATE TABLE nba AS SELECT * FROM ext_nba; -Working around unSupported column types ---------------------------------------------- +Examples +---------------- +This section describes the following examples: -Suppose you only want to load some of the columns - for example, if one of the columns isn't Supported. +.. contents:: + :local: + :depth: 1 -By ommitting unSupported columns from queries that access the ``EXTERNAL TABLE``, they will never be called, and will not cause a "type mismatch" error. +Omitting Unsupported Column Types +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +When loading data, you can omit columns using the NULL as argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a “type mismatch” error. -For this example, assume that the ``Position`` column isn't Supported because of its type. +In the example below, the ``Position column`` is not supported due its type. .. code-block:: postgres CREATE TABLE nba AS SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; - - -- We ommitted the unSupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. - -Modifying data during the copy process ------------------------------------------- +Modifying Data Before Loading +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. -One of the main reasons for staging data with ``EXTERNAL TABLE`` is to examine the contents and modify them before loading them. +For example, we can replace **pounds** with **kilograms** using the ``CREATE TABLE AS`` statement. -Assume we are unhappy with weight being in pounds, because we want to use kilograms instead. We can apply the transformation as part of the :ref:`create_table_as` statement. - -Similar to the previous example, we will also set the ``Position`` column as a default ``NULL``. +In the example below, the ``Position column`` is set to the default ``NULL``. .. code-block:: postgres @@ -255,15 +233,9 @@ Similar to the previous example, we will also set the ``Position`` column as a d FROM ext_nba ORDER BY weight; - -Further Parquet loading examples -======================================= - -:ref:`create_foreign_table` contains several configuration options. See more in :ref:`the CREATE FOREIGN TABLE parameters section`. - - -Loading a table from a directory of Parquet files on HDFS ------------------------------------------------------------- +Loading a Table from a Directory of Parquet Files on HDFS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following is an example of loading a table from a directory of Parquet files on HDFS: .. code-block:: postgres @@ -277,8 +249,9 @@ Loading a table from a directory of Parquet files on HDFS CREATE TABLE users AS SELECT * FROM ext_users; -Loading a table from a bucket of files on S3 ------------------------------------------------ +Loading a Table from a Directory of Parquet Files on S3 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The following is an example of loading a table from a directory of Parquet files on S3: .. code-block:: postgres @@ -292,3 +265,29 @@ Loading a table from a bucket of files on S3 ); CREATE TABLE users AS SELECT * FROM ext_users; + +For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. + +Best Practices +============ +Because external tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Parquet files into SQream. This lets you determine if your table output is identical to your originally inserted table. + +The following is an example of the output based on the **nba.parquet** table: + +.. code-block:: psql + + t=> SELECT * FROM ext_nba LIMIT 10; + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +.. note:: If your table output has errors, verify that the structure of the Parquet files correctly corresponds to the external table structure that you created. \ No newline at end of file diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index 92c35ee63..b7a591d65 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -23,3 +23,5 @@ For more information, see the following: :: * :ref:`copy_to` + +.. note:: While you can ingest data into SQream from Parquet files, you can also store and run queries on data located on external Parquet files. For more information, see :ref:`parquet`. \ No newline at end of file diff --git a/external_storage_platforms/storing_data_on_parquet.rst b/external_storage_platforms/storing_data_on_parquet.rst new file mode 100644 index 000000000..0aa54dbc4 --- /dev/null +++ b/external_storage_platforms/storing_data_on_parquet.rst @@ -0,0 +1,8 @@ +.. _storing_data_on_parquet: + +*********************** +Storing Data on Parquet +*********************** +As described in the **Data Ingestion Sources** section, users can insert data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, users may want to retain their data there instead of inserting it into SQream. This requires SQream users to be able to execute queries on external Parquet files. + + diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index b44d78cf8..ee36f27f9 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -90,8 +90,7 @@ The following table shows the available compression methods: - GPU * - ``zlib`` - All types - - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - - **Comment - GPU, CPU?** + - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. .. note:: Automatic compression does not select the **zlib** compression method. diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index b5bbb34f0..bd8be6a61 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -39,8 +39,7 @@ For more information, navigate to the **Compression Methods** table on the :ref: Parquet Read Optimization ************ - -https://sqream.atlassian.net/wiki/spaces/PRODUCT/pages/2277998593/Parquet+read+optimization +SQream now supports storing and running queries on data located on external Parquet files. For more information, see :ref:`parquet`. Known Issues --------- From bc994e8ac3c5c7633678358b103b566423a52107 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 12:09:51 +0300 Subject: [PATCH 0225/1892] Prepared for release - See comment about SQ-11291 --- data_ingestion/parquet.rst | 36 ++++++++++++++++++++++-- feature_guides/compression.rst | 3 +- releases/2022.1.2.rst | 50 +++++++++++++--------------------- 3 files changed, 55 insertions(+), 34 deletions(-) diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 36ad8c613..df09891d3 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -21,19 +21,51 @@ Prepare your source Parquet files according to the requirements described in the :widths: 40 5 20 20 20 20 5 5 5 5 10 :header-rows: 1 - * - SQream DB type → + * - SQream Type → - Parquet source + :: + + Parquet Source ↓ - ``BOOL`` + + :: + - ``TINYINT`` + + :: + - ``SMALLINT`` + + :: + - ``INT`` + + :: + - ``BIGINT`` + + :: + - ``REAL`` + + :: + - ``DOUBLE`` + + :: + - ``TEXT`` [#f0]_ + + :: + - ``DATE`` + + :: + - ``DATETIME`` + + :: + * - ``BOOLEAN`` - Supported - diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index ee36f27f9..ab26e9986 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -91,8 +91,9 @@ The following table shows the available compression methods: * - ``zlib`` - All types - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. + - CPU -.. note:: Automatic compression does not select the **zlib** compression method. +.. note:: Automatic compression does **not** select the ``zlib`` compression method. .. _specifying_compressions: diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index bd8be6a61..b3ff083e9 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.2 ************************** -The 2022.1.2 release notes were released on x/xx/2022 and describe the following: +The 2022.1.2 release notes were released on 8/24/2022 and describe the following: .. contents:: :local: @@ -13,8 +13,16 @@ Version Content ---------- The 2022.1.2 Release Notes describes the following: +* Automatic schema identification. + + :: + * Enhanced compression features. + :: + +* Support for external Parquet files. + New Features ---------- The 2022.1.2 Release Notes include the following new features: @@ -41,43 +49,23 @@ Parquet Read Optimization ************ SQream now supports storing and running queries on data located on external Parquet files. For more information, see :ref:`parquet`. -Known Issues ---------- -The following table lists the known issues for Version 2022.1.2: - -+-------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+================================================================================================+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ - Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1.2: -+-------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+================================================================================================+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-xxxx | Description | -+-------------+------------------------------------------------------------------------------------------------+ ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================================================================+ +| SQ-11273 | Clustering ``partial-partial`` optimization only occurs when copying data from CSV files. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11291 | Metadata filters were not applied when using the ``LIKE`` function, causing certain queries to run on full tables instead of sorted data. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + +**Comment** - *Was SQ-11291 just removed?* Operations and Configuration Changes -------- -The ``xxxx`` configuration flag is required for adjusting the permitted log-in attempts. - -For more information, see +No configuration changes were made. Naming Changes ------- From 30f70a8ad7394346535a1f6a54152dd426bcd96f Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 12:19:33 +0300 Subject: [PATCH 0226/1892] Updated Configuration Section --- configuration_guides/configuring_sqream.rst | 22 + .../current_configuration_method.rst | 729 ------------------ .../current_method_all_configurations.rst | 431 +++++++++++ .../current_method_command_examples.rst | 36 + .../current_method_configuration_levels.rst | 33 + .../current_method_configuration_roles.rst | 17 + ...thod_configuring_your_parameter_values.rst | 40 + .../current_method_flag_types.rst | 20 + .../current_method_modification_methods.rst | 50 ++ ...showing_all_flags_in_the_catalog_table.rst | 21 + configuration_guides/index.rst | 6 +- releases/2022.1.2.rst | 2 + 12 files changed, 674 insertions(+), 733 deletions(-) create mode 100644 configuration_guides/configuring_sqream.rst delete mode 100644 configuration_guides/current_configuration_method.rst create mode 100644 configuration_guides/current_method_all_configurations.rst create mode 100644 configuration_guides/current_method_command_examples.rst create mode 100644 configuration_guides/current_method_configuration_levels.rst create mode 100644 configuration_guides/current_method_configuration_roles.rst create mode 100644 configuration_guides/current_method_configuring_your_parameter_values.rst create mode 100644 configuration_guides/current_method_flag_types.rst create mode 100644 configuration_guides/current_method_modification_methods.rst create mode 100644 configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst diff --git a/configuration_guides/configuring_sqream.rst b/configuration_guides/configuring_sqream.rst new file mode 100644 index 000000000..901af9e3d --- /dev/null +++ b/configuration_guides/configuring_sqream.rst @@ -0,0 +1,22 @@ +.. _configuring_sqream: + +************************* +Configuring SQream +************************* +The **Configuring SQream** page describes the following configuration topics: + +.. toctree:: + :maxdepth: 1 + :glob: + :titlesonly: + + current_method_configuration_levels + current_method_flag_types + current_method_configuration_roles + current_method_modification_methods + current_method_configuring_your_parameter_values + current_method_command_examples + current_method_showing_all_flags_in_the_catalog_table + current_method_all_configurations + + diff --git a/configuration_guides/current_configuration_method.rst b/configuration_guides/current_configuration_method.rst deleted file mode 100644 index 078e2dac2..000000000 --- a/configuration_guides/current_configuration_method.rst +++ /dev/null @@ -1,729 +0,0 @@ -.. _current_configuration_method: - -************************** -Configuring SQream -************************** -The **Configuring SQream** page describes SQream’s method for configuring your instance of SQream and includes the following topics: - -.. contents:: - :local: - :depth: 1 - -Overview ------ -Modifications that you make to your configurations are persistent based on whether they are made at the session or cluster level. Persistent configurations are modifications made to attributes that are retained after shutting down your system. - -Modifying Your Configuration ----- -The **Modifying Your Configuration** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Modifying Your Configuration Using the Worker Configuration File -~~~~~~~~~~~ -You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. - -The following is an example of a worker configuration file: - -.. code-block:: postgres - - { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” - } - -You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. - -Modifying Your Configuration Using a Legacy Configuration File -~~~~~~~~~~~ -You can modify your configuration using a legacy configuration file. - -The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. - -The following is an example of the legacy configuration file: - -.. code-block:: postgres - - { - “developerMode”: true, - “reextentUse”: false, - “useClientLog”: true, - “useMetadataServer”” false - } - -Session vs Cluster Based Configuration -============================== -.. contents:: - :local: - :depth: 1 - -Cluster-Based Configuration --------------- -SQream uses cluster-based configuration, enabling you to centralize configurations for all workers on the cluster. Only flags set to the regular or cluster flag type have access to cluster-based configuration. Configurations made on the cluster level are persistent and stored at the metadata level. The parameter settings in this file are applied globally to all workers connected to it. - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -For more information on flag-based access to cluster-based configuration, see **Configuration Flag Types** below. - -Session-Based Configuration ----------------- -Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. - -The **SET flag_name** command is used to modify flag attributes. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends - -For example, when the query below has completed executing, the values configured will be restored to its previous setting: - -.. code-block:: console - - set spoolMemoryGB=700; - select * from table a where date='2021-11-11' - -For more information, see the following: - -* `Using SQream SQL `_ - modifying flag attributes from the CLI. -* `SQream Acceleration Studio `_ - modifying flag attributes from Studio. - -Configuration Flag Types -========== -The flag type attribute can be set for each flag and determines its write access as follows: - -* **Administration:** session-based read/write flags that can be stored in the metadata file. -* **Cluster:** global cluster-based read/write flags that can be stored in the metadata file. -* **Worker:** single worker-based read-only flags that can be stored in the worker configuration file. - -The flag type determines which files can be accessed and which commands or commands sets users can run. - -The following table describes the file or command modification rights for each flag type: - -.. list-table:: - :widths: 20 20 20 20 - :header-rows: 1 - - * - **Flag Type** - - **Legacy Configuration File** - - **ALTER SYSTEM SET** - - **Worker Configuration File** - * - :ref:`Regular` - - Can modify - - Can modify - - Cannot modify - * - :ref:`Cluster` - - Cannot modify - - Can modify - - Cannot modify - * - :ref:`Worker` - - Cannot modify - - Cannot modify - - Can modify - -.. _regular_flag_types: - -Regular Flag Types ---------------------- -The following is an example of the correct syntax for running a **Regular** flag type command: - -.. code-block:: console - - SET spoolMemoryGB= 11; - executed - -The following table describes the Regular flag types: - -.. list-table:: - :widths: 2 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - ``SHOW / ALL`` - - Used to preset either a specific flag value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _cluster_flag_types: - -Cluster Flag Types ---------------------- -The following is an example of the correct syntax for running a **Cluster** flag type command: - -.. code-block:: console - - ALTER SYSTEM RESET useMetadataServer; - executed - -The following table describes the Cluster flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _worker_flag_types: - -Worker Flag Types ---------------------- -The following is an example of the correct syntax for running a **Worker** flag type command: - -.. code-block:: console - - SHOW spoolMemoryGB; - -The following table describes the Worker flag types: - -.. list-table:: - :widths: 1 5 10 - :header-rows: 1 - - * - **Command** - - **Description** - - **Example** - * - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - ``rechunkThreshold,90,true,RND,regular`` - * - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - - ``compilerGetsOnlyUFs,false,generic,regular,Makes runtime pass to compiler only`` - ``utility functions names,boolean,true,false`` - * - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -All Configurations ---------------------- -The following table describes the **Generic** and **Administration** configuration flags: - -.. list-table:: - :header-rows: 1 - :widths: 1 2 1 15 1 20 - :class: my-class - :name: my-name - - * - Flag Name - - Access Control - - Modification Type - - Description - - Data Type - - Default Value - - * - ``binSizes`` - - Administration - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - string - - - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` - ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` - ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` - ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` - ``2684354560,2952790016,3221225472`` - - * - ``checkCudaMemory`` - - Administration - - Regular - - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - - boolean - - ``FALSE`` - - * - ``compilerGetsOnlyUFs`` - - Administration - - Regular - - Sets the runtime to pass only utility functions names to the compiler. - - boolean - - ``FALSE`` - - * - ``copyToRestrictUtf8`` - - Administration - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - boolean - - ``FALSE`` - - * - ``cpuReduceHashtableSize`` - - Administration - - Regular - - Sets the hash table size of the CpuReduce. - - uint - - ``10000`` - - * - ``csvLimitRowLength`` - - Administration - - Cluster - - Sets the maximum supported CSV row length. - - uint - - ``100000`` - - * - ``cudaMemcpyMaxSizeBytes`` - - Administration - - Regular - - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - - uint - - ``0`` - - * - ``CudaMemcpySynchronous`` - - Administration - - Regular - - Indicates if copying from/to GPU is synchronous. - - boolean - - ``FALSE`` - - * - ``cudaMemQuota`` - - Administration - - Worker - - Sets the percentage of total device memory to be used by the instance. - - uint - - ``90`` - - * - ``developerMode`` - - Administration - - Regular - - Enables modifying R&D flags. - - boolean - - ``FALSE`` - - * - ``enableDeviceDebugMessages`` - - Administration - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``enableLogDebug`` - - Administration - - Regular - - Enables creating and logging in the clientLogger_debug file. - - boolean - - ``TRUE`` - - * - ``enableNvprofMarkers`` - - Administration - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``endLogMessage`` - - Administration - - Regular - - Appends a string at the end of every log line. - - string - - ``EOM`` - - - - * - ``varcharIdentifiers`` - - Administration - - Regular - - Activates using varchar as an identifier. - - boolean - - ``true`` - - - - * - ``extentStorageFileSizeMB`` - - Administration - - Cluster - - Sets the minimum size in mebibytes of extents for table bulk data. - - uint - - ``20`` - - * - ``gatherMemStat`` - - Administration - - Regular - - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. - - boolean - - ``FALSE`` - - * - ``increaseChunkSizeBeforeReduce`` - - Administration - - Regular - - Increases the chunk size to reduce query speed. - - boolean - - ``FALSE`` - - * - ``increaseMemFactors`` - - Administration - - Regular - - Adds rechunker before expensive chunk producer. - - boolean - - ``TRUE`` - - * - ``leveldbWriteBufferSize`` - - Administration - - Regular - - Sets the buffer size. - - uint - - ``524288`` - - * - ``machineIP`` - - Administration - - Worker - - Manual setting of reported IP. - - string - - ``127.0.0.1`` - - - - - * - ``memoryResetTriggerMB`` - - Administration - - Regular - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` - - * - ``metadataServerPort`` - - Administration - - Worker - - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. - - uint - - ``3105`` - - * - ``mtRead`` - - Administration - - Regular - - Splits large reads to multiple smaller ones and executes them concurrently. - - boolean - - ``FALSE`` - - * - ``mtReadWorkers`` - - Administration - - Regular - - Sets the number of workers to handle smaller concurrent reads. - - uint - - ``30`` - - * - ``orcImplicitCasts`` - - Administration - - Regular - - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - - boolean - - ``TRUE`` - - * - ``statementLockTimeout`` - - Administration - - Regular - - Sets the timeout (seconds) for acquiring object locks before executing statements. - - uint - - ``3`` - - * - ``useConfigIP`` - - Administration - - Worker - - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - - boolean - - ``FALSE`` - - * - ``useLegacyDecimalLiterals`` - - Administration - - Regular - - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``useLegacyStringLiterals`` - - Administration - - Regular - - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``flipJoinOrder`` - - Generic - - Regular - - Reorders join to force equijoins and/or equijoins sorted by table size. - - boolean - - ``FALSE`` - - * - ``limitQueryMemoryGB`` - - Generic - - Worker - - Prevents a query from processing more memory than the flag’s value. - - uint - - ``100000`` - - * - ``cacheEvictionMilliseconds`` - - Generic - - Regular - - Sets how long the cache stores contents before being flushed. - - size_t - - ``2000`` - - - * - ``cacheDiskDir`` - - Generic - - Regular - - Sets the ondisk directory location for the spool to save files on. - - size_t - - Any legal string - - - * - ``cacheDiskGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool on the disk. - - size_t - - ``128`` - - * - ``cachePartitions`` - - Generic - - Regular - - Sets the number of partitions that the cache is split into. - - size_t - - ``4`` - - - * - ``cachePersistentDir`` - - Generic - - Regular - - Sets the persistent directory location for the spool to save files on. - - string - - Any legal string - - - * - ``cachePersistentGB`` - - Generic - - Regular - - Sets the amount of data (GB) for the cache to store persistently. - - size_t - - ``128`` - - - * - ``cacheRamGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool InMemory. - - size_t - - ``16`` - - - - - - - - * - ``logSysLevel`` - - Generic - - Regular - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` - - * - ``maxAvgBlobSizeToCompressOnGpu`` - - Generic - - Regular - - Sets the CPU to compress columns with size above (flag’s value) * (row count). - - uint - - ``120`` - - - * - ``sessionTag`` - - Generic - - Regular - - Sets the name of the session tag. - - string - - Any legal string - - - - * - ``spoolMemoryGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by the server for spooling. - - uint - - ``8`` - -Configuration Commands -========== -The configuration commands are associated with particular flag types based on permissions. - -The following table describes the commands or command sets that can be run based on their flag type. Note that the flag names described in the following table are described in the :ref:`Configuration Roles` section below. - -.. list-table:: - :header-rows: 1 - :widths: 1 2 10 17 - :class: my-class - :name: my-name - - * - Flag Type - - Command - - Description - - Example - * - Regular - - ``SET `` - - Used for modifying flag attributes. - - ``SET developerMode=true`` - * - Cluster - - ``ALTER SYSTEM SET `` - - Used to storing or modifying flag attributes in the metadata file. - - ``ALTER SYSTEM SET `` - * - Cluster - - ``ALTER SYSTEM RESET `` - - Used to remove a flag or all flag attributes from the metadata file. - - ``ALTER SYSTEM RESET `` - * - Regular, Cluster, Worker - - ``SHOW / ALL`` - - Used to print the value of a specified value or all flag values. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``SHOW ALL LIKE`` - - Used as a wildcard character for flag names. - - ``SHOW `` - * - Regular, Cluster, Worker - - ``show_conf_UF`` - - Used to print all flags with the following attributes: - - * Flag name - * Default value - * Is developer mode (Boolean) - * Flag category - * Flag type - - - - - ``rechunkThreshold,90,true,RND,regular`` - * - Regular, Cluster, Worker - - ``show_conf_extended UF`` - - Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. - - ``spoolMemoryGB,15,false,generic,regular,Amount of memory (GB)`` - ``the server can use for spooling,”Statement that perform “”group by””,`` - ``“”order by”” or “”join”” operation(s) on large set of data will run`` - ``much faster if given enough spool memory, otherwise disk spooling will`` - ``be used resulting in performance hit.”,uint,,0-5000`` - * - Regular, Cluster, Worker - - ``show_md_flag UF`` - - Used to show a specific flag/all flags stored in the metadata file. - - - * Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` - * Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` - * Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` - -.. _configuration_roles: - -Configuration Roles -=========== -SQream divides flags into the following roles, each with their own set of permissions: - -* `Administration flags `_: can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command. -* `Generic flags `_: can be modified by standard users on a session basis. - -Showing All Flags in the Catalog Table -======= -SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. - -The following is the correct syntax for a catalog table query: - -.. code-block:: console - - SELECT * FROM sqream_catalog.settings - -The following is an example of a catalog table query: - -.. code-block:: console - - externalTableBlobEstimate, 100, 100, default, - varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns - useCrcForTextJoinKeys, true, true, default, - hiveStyleImplicitStringCasts, false, false, default, - -This guide covers the configuration files and the ``SET`` statement. \ No newline at end of file diff --git a/configuration_guides/current_method_all_configurations.rst b/configuration_guides/current_method_all_configurations.rst new file mode 100644 index 000000000..7385066af --- /dev/null +++ b/configuration_guides/current_method_all_configurations.rst @@ -0,0 +1,431 @@ +.. _current_method_all_configurations: + +************************** +All Configurations +************************** +The following table describes all **Generic** and **Administration** configuration flags: + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Access Control + - Modification Type + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``cacheEvictionMilliseconds`` + - Generic + - Regular + - Sets how long the cache stores contents before being flushed. + - size_t + - ``2000`` + + + * - ``cacheDiskDir`` + - Generic + - Regular + - Sets the ondisk directory location for the spool to save files on. + - size_t + - Any legal string + + + * - ``cacheDiskGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool on the disk. + - size_t + - ``128`` + + * - ``cachePartitions`` + - Generic + - Regular + - Sets the number of partitions that the cache is split into. + - size_t + - ``4`` + + + * - ``cachePersistentDir`` + - Generic + - Regular + - Sets the persistent directory location for the spool to save files on. + - string + - Any legal string + + + * - ``cachePersistentGB`` + - Generic + - Regular + - Sets the amount of data (GB) for the cache to store persistently. + - size_t + - ``128`` + + + * - ``cacheRamGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by Spool InMemory. + - size_t + - ``16`` + + + + * - ``checkCudaMemory`` + - Admin + - Regular + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - Admin + - Regular + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - Admin + - Regular + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - Admin + - Regular + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - Admin + - Cluster + - Sets the maximum supported CSV row length. + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - Admin + - Regular + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - Admin + - Regular + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + * - ``cudaMemQuota`` + - Admin + - Worker + - Sets the percentage of total device memory to be used by the instance. + - uint + - ``90`` + + * - ``developerMode`` + - Admin + - Regular + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - Admin + - Regular + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - Admin + - Regular + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - Admin + - Regular + - Appends a string at the end of every log line. + - string + - ``EOM`` + + + + + + + + * - ``extentStorageFileSizeMB`` + - Admin + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + + * - ``externalTableBlobEstimate`` + - ? + - Regular + - ? + - ? + - ? + + + + + + * - ``flipJoinOrder`` + - Generic + - Regular + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + + + * - ``gatherMemStat`` + - Admin + - Regular + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. + - boolean + - ``FALSE`` + + + * - ``healerMaxInactivityHours`` + - Admin + - Worker + - Defines the threshold for creating a log recording a slow statement. + - size_t + - ``5`` + + + + + * - ``increaseChunkSizeBeforeReduce`` + - Admin + - Regular + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - Admin + - Regular + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + + * - ``isHealerOn`` + - Admin + - Worker + - Periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. + - boolean + - ``TRUE`` + + + + + + * - ``leveldbWriteBufferSize`` + - Admin + - Regular + - Sets the buffer size. + - uint + - ``524288`` + + * - ``limitQueryMemoryGB`` + - Generic + - Worker + - Prevents a query from processing more memory than the flag’s value. + - uint + - ``100000`` + + + + + * - ``loginMaxRetries`` + - Admin + - Worker + - Sets the permitted log-in attempts. + - size_t + - ``5`` + + + + * - ``logSysLevel`` + - Generic + - Regular + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + + + + + * - ``machineIP`` + - Admin + - Worker + - Manual setting of reported IP. + - string + - ``127.0.0.1`` + + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Generic + - Regular + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + + * - ``maxPinnedPercentageOfTotalRAM`` + - Admin + - Regular + - Sets the maximum percentage CPU RAM that pinned memory can use. + - uint + - ``70`` + + + + * - ``memMergeBlobOffsetsCount`` + - Admin + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + + + * - ``memoryResetTriggerMB`` + - Admin + - Regular + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + * - ``metadataServerPort`` + - Admin + - Worker + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. + - uint + - ``3105`` + + * - ``mtRead`` + - Admin + - Regular + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - Admin + - Regular + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - Admin + - Regular + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + + * - ``sessionTag`` + - Generic + - Regular + - Sets the name of the session tag. + - string + - Any legal string + + + + * - ``spoolMemoryGB`` + - Generic + - Regular + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + + + * - ``statementLockTimeout`` + - Admin + - Regular + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + * - ``useConfigIP`` + - Admin + - Worker + - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + * - ``useLegacyDecimalLiterals`` + - Admin + - Regular + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - Admin + - Regular + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + + + + + + + + + * - ``varcharIdentifiers`` + - Admin + - Regular + - Activates using varchar as an identifier. + - boolean + - ``true`` \ No newline at end of file diff --git a/configuration_guides/current_method_command_examples.rst b/configuration_guides/current_method_command_examples.rst new file mode 100644 index 000000000..2f75a4711 --- /dev/null +++ b/configuration_guides/current_method_command_examples.rst @@ -0,0 +1,36 @@ +.. _current_method_command_examples: + +************************** +Command Examples +************************** +This section includes the following command examples: + +.. contents:: + :local: + :depth: 1 + +Running a Regular Flag Type Command +--------------------- +The following is an example of running a **Regular** flag type command: + +.. code-block:: console + + SET spoolMemoryGB= 11; + executed + +Running a Worker Flag Type Command +--------------------- +The following is an example of running a **Worker** flag type command: + +.. code-block:: console + + SHOW spoolMemoryGB; + +Running a Cluster Flag Type Command +--------------------- +The following is an example of running a **Cluster** flag type command: + +.. code-block:: console + + ALTER SYSTEM RESET useMetadataServer; + executed \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst new file mode 100644 index 000000000..47ccf32b3 --- /dev/null +++ b/configuration_guides/current_method_configuration_levels.rst @@ -0,0 +1,33 @@ +.. _current_method_configuration_levels: + +************************** +Configuration Levels +************************** +SQream's configuration parameters are based on the following hierarchy: + +.. contents:: + :local: + :depth: 1 + +Cluster-Based Configuration +-------------- +Cluster-based configuration lets you centralize configurations for all workers on the cluster. Only Regular and Cluster flag types can be modified on the cluster level. These modifications are persistent and stored at the metadata level, which are applied globally to all workers in the cluster. + +.. note:: While cluster-based configuration was designed for configuring Workers, you can only configure Worker values set to the Regular or Cluster type. + +Worker-Based Configuration +-------------- +Worker-based configuration lets you modify the configuration belong to individual workers from the worker configuration file. + +For more information on making configurations from the worker configuration file, see `Modifying Your Configuration Using a Legacy Configuration File `_. + +Session-Based Configuration +-------------- +Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. The **SET flag_name** command is used to modify flag values on the session level. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends. + +For example, when the query below has completed executing, the values configured will be restored to its previous setting: + +.. code-block:: console + + set spoolMemoryGB=700; + select * from table a where date='2021-11-11' \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_roles.rst b/configuration_guides/current_method_configuration_roles.rst new file mode 100644 index 000000000..11b7e4bfb --- /dev/null +++ b/configuration_guides/current_method_configuration_roles.rst @@ -0,0 +1,17 @@ +.. _current_method_configuration_roles: + +************************** +Configuration Roles +************************** +SQream divides flags into the following roles, each with their own set of permissions: + +* :ref:`admin_flags` - can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: **Comment** - *I don't think we need to mention the command here, as it's described below, and also not mentioned for Generic Flags.* + + * Regular + * Worker + * Cluster + +* :ref:`generic_flags` - can be modified by standard users on a session basis: + + * Regular + * Worker \ No newline at end of file diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst new file mode 100644 index 000000000..d082db693 --- /dev/null +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -0,0 +1,40 @@ +.. _current_method_configuring_your_parameter_values: + +************************** +Configuring Your Parameter Values +************************** +The method you must use to configure your parameter values depends on the configuration level. Each configuration level has its own command or set of commands used to configure values, as shown below: + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Configuration Level** | ++=================================================================================================================================================================================================================================================================================================================+ +| **Regular, Worker, and Cluster** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| **Command** | **Description** | **Example** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SET `` | Used for modifying flag attributes. | ``SET developerMode=true`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SHOW / ALL`` | Used to preset either a specific flag value or all flag values. | ``SHOW `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``SHOW ALL LIKE`` | Used as a wildcard character for flag names. | ``SHOW `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_conf_UF`` | Used to print all flags with the following attributes: | ``rechunkThreshold,90,true,RND,regular`` | +| | | | +| | * Flag name | | +| | * Default value | | +| | * Is Developer Mode (Boolean) | | +| | * Flag category | | +| | * Flag type | | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_conf_extended UF`` | Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. | ``rechunkThreshold,90,true,RND,regular`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``show_md_flag UF`` | Used to show a specific flag/all flags stored in the metadata file. |* Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` | +| | |* Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` | +| | |* Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| **Worker and Cluster** | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``ALTER SYSTEM SET `` | Used for storing or modifying flag attributes in the metadata file. | ``ALTER SYSTEM SET `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ +| ``ALTER SYSTEM RESET `` | Used to remove a flag or all flag attributes from the metadata file. | ``ALTER SYSTEM RESET `` | ++-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ \ No newline at end of file diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst new file mode 100644 index 000000000..b1bedecba --- /dev/null +++ b/configuration_guides/current_method_flag_types.rst @@ -0,0 +1,20 @@ +.. _current_method_flag_types: + +************************** +Flag Types +************************** +SQream uses three flag types, **Cluster**, **Worker**, and **Regular**. Each of these flag types is associated with one of three hierarchical configuration levels described earlier, making it easier to configure your system. + +The highest level in the hierarchy is Cluster, which lets you set configurations across all workers in a given cluster. Modifying cluster values is **persistent**, meaning that any configurations you set are retained after shutting down your system. Configurations set at the Cluster level take the highest priority and override settings made on the Regular and Worker level **Comment** - *Confirm*. This is known as **cluster-based configuration**. Note that Cluster-based configuration lets you modify Cluster *and* Regular flag types. An example of a Cluster flag is **persisting your cache directory.** + +The second level is Worker, which lets you configure individual workers. Modifying Worker values are also **persistent**. This is known as **worker-based configuration**. Some examples of Worker flags includes **setting total device memory usage** and **setting metadata server connection port**. + +The lowest level is Regular, which means that modifying values of Regular flags affects only your current session and are not persistent. This means that they are automatically restored to their default value when the session ends. This is known as **session-based configuration**. Some examples of Regular flags includes **setting your bin size** and **setting CUDA memory**. + +To see each flag's default value, see one of the following: + +* The **Default Value** column in the :ref:`All Configurations` section. + + :: + +* The flag's individual description page, such as :ref:`Setting CUDA Memory`. \ No newline at end of file diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst new file mode 100644 index 000000000..05825b07a --- /dev/null +++ b/configuration_guides/current_method_modification_methods.rst @@ -0,0 +1,50 @@ +.. _current_method_modification_methods: + +************************** +Modification Methods +************************** +SQream provides two different ways to modify your configurations. The current method is based on hierarchical configuration as described above. This method is based on making modifications on the **worker configuration file**, while you can still make modifications using the previous method using the **legacy configuration file**, both described below: + +.. contents:: + :local: + :depth: 1 + +Modifying Your Configuration Using the Worker Configuration File +------------------- +You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. + +The following is an example of a worker configuration file: + +.. code-block:: postgres + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. + +Modifying Your Configuration Using a Legacy Configuration File +--------------------- +You can modify your configuration using a legacy configuration file. + +The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. + +The following is an example of the legacy configuration file: + +.. code-block:: postgres + + { + “developerMode”: true, + “reextentUse”: false, + “useClientLog”: true, + “useMetadataServer”” false + } +For more information on using the previous configuration method, see :ref:`previous_configuration_method`. \ No newline at end of file diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst new file mode 100644 index 000000000..647a401b6 --- /dev/null +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -0,0 +1,21 @@ +.. _current_method_showing_all_flags_in_the_catalog_table: + +************************** +Showing All Flags in the Catalog Table +************************** +SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. + +The following is the correct syntax for a catalog table query: + +.. code-block:: console + + SELECT * FROM sqream_catalog.settings + +The following is an example of a catalog table query: + +.. code-block:: console + + externalTableBlobEstimate, 100, 100, default, + varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + useCrcForTextJoinKeys, true, true, default, + hiveStyleImplicitStringCasts, false, false, default, \ No newline at end of file diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 6a65853f0..6805bc188 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -11,8 +11,6 @@ The **Configuration Guides** page describes the following configuration informat :glob: spooling - configuration_methods + configuring_sqream configuration_flags - - - + previous_configuration_method \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index b3ff083e9..385216c21 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -56,6 +56,8 @@ The following table lists the issues that were resolved in Version 2022.1.2: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +=============+===========================================================================================================================================+ +| SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | SQ-11273 | Clustering ``partial-partial`` optimization only occurs when copying data from CSV files. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | SQ-11291 | Metadata filters were not applied when using the ``LIKE`` function, causing certain queries to run on full tables instead of sorted data. | From bf59f8c7aff5844f4092acbb7be64db20047dbbb Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 12:24:14 +0300 Subject: [PATCH 0227/1892] Studio 5.4.7 --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index efeecb8e2..d6a37d4f7 100644 --- a/index.rst +++ b/index.rst @@ -104,7 +104,7 @@ If you're looking for an older version of the documentation, versions 1.10 throu loading_and_unloading_data/index feature_guides/index operational_guides/index - sqream_studio_5.4.6/index + sqream_studio_5.4.7/index architecture/index configuration_guides/index reference/index From 4fbc81d46972ec6a81c966d69b5aed353174c2df Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 12:26:01 +0300 Subject: [PATCH 0228/1892] Studio 5.4.7 --- ...ing_and_managing_roles_and_permissions.rst | 12 ++-- ...ts_and_running_queries_from_the_editor.rst | 60 +++++++++---------- sqream_studio_5.4.7/getting_started.rst | 6 +- sqream_studio_5.4.7/index.rst | 4 +- sqream_studio_5.4.7/viewing_logs.rst | 32 +++++----- 5 files changed, 57 insertions(+), 57 deletions(-) diff --git a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst index 9f0f7f39a..31ff716cb 100644 --- a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst @@ -1,6 +1,6 @@ .. _creating_assigning_and_managing_roles_and_permissions: -.. _roles_5.4.3: +.. _roles_5.4.7: **************************** Creating, Assigning, and Managing Roles and Permissions @@ -32,7 +32,7 @@ The **Type** column displays one of the following assigned role types: .. note:: If you disable a password, when you enable it you have to create a new one. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Viewing Information About a Role @@ -49,7 +49,7 @@ Clicking a role in the roles table displays the following information: * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Creating a New Role @@ -73,7 +73,7 @@ From the New Role panel you view directly and indirectly (or inherited) granted When adding a new role, you must select the **Enable login for this role** and **Has password** check boxes. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Editing a Role -------------------- @@ -89,10 +89,10 @@ Once you've created a role, clicking the **Edit Role** button lets you do the fo From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` Deleting a Role ----------------- Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. -:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file +:ref:`Back to Creating, Assigning, and Managing Roles and Permissions` \ No newline at end of file diff --git a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst index 0a298fdbf..882b226e0 100644 --- a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst @@ -1,6 +1,6 @@ .. _executing_statements_and_running_queries_from_the_editor: -.. _editor_top_5.4.3: +.. _editor_top_5.4.7: **************************** Executing Statements and Running Queries from the Editor @@ -23,23 +23,23 @@ The following is a brief description of the Editor panels: - Element - Description * - 1 - - :ref:`Toolbar` + - :ref:`Toolbar` - Used to select the active database you want to work on, limit the number of rows, save query, etc. * - 2 - - :ref:`Database Tree and System Queries panel` + - :ref:`Database Tree and System Queries panel` - Shows a hierarchy tree of databases, views, tables, and columns * - 3 - - :ref:`Statement panel` + - :ref:`Statement panel` - Used for writing queries and statements * - 4 - - :ref:`Results panel` + - :ref:`Results panel` - Shows query results and execution information. -.. _top_5.4.3: +.. _top_5.4.7: -.. _studio_5.4.3_editor_toolbar: +.. _studio_5.4.7_editor_toolbar: Executing Statements from the Toolbar ================ @@ -76,10 +76,10 @@ You can access the following from the Toolbar pane: For more information on stopping active statements, see the :ref:`STOP_STATEMENT` command. -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` -.. _studio_5.4.3_editor_db_tree: +.. _studio_5.4.7_editor_db_tree: Performing Statement-Related Operations from the Database Tree ================ @@ -204,7 +204,7 @@ The database object functions are used to perform the following: * - Table DDL - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL `_. * - DDL Optimizer - - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. + - The `DDL Optimizer `_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ----------------------- @@ -243,7 +243,7 @@ The **System Queries** panel lets you execute predefined queries and includes th Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. -.. _studio_5.4.3_editor_statement_area: +.. _studio_5.4.7_editor_statement_area: Writing Statements and Queries from the Statement Panel ============== @@ -288,13 +288,13 @@ You can also rename the default tab name by double-clicking it and typing a new .. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab -.. _studio_editor_results_5.4.3: +.. _studio_editor_results_5.4.7: -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` -.. _studio_5.4.3_editor_results: +.. _studio_5.4.7_editor_results: -.. _results_panel_5.4.3: +.. _results_panel_5.4.7: Viewing Statement and Query Results from the Results Panel ============== @@ -310,17 +310,17 @@ The following is a brief description of the Results panel views highlighted in t * - Element - Description - * - :ref:`Results view` + * - :ref:`Results view` - Lets you view search query results. - * - :ref:`Execution Details view` + * - :ref:`Execution Details view` - Lets you analyze your query for troubleshooting and optimization purposes. - * - :ref:`SQL view` + * - :ref:`SQL view` - Lets you see the SQL view. -.. _results_view_5.4.3: +.. _results_view_5.4.7: -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` Searching Query Results in the Results View ---------------- @@ -338,7 +338,7 @@ Saving Results to the Clipboard ^^^^^^^^^^^^ The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. -.. _save_results_to_local_file_5.4.3: +.. _save_results_to_local_file_5.4.7: Saving Results to a Local File ^^^^^^^^^^^^ @@ -346,7 +346,7 @@ The **Save results to local file** functions lets you save your search query res In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. -.. _running_parallel_statements_5.4.3: +.. _running_parallel_statements_5.4.7: Running Parallel Statements ^^^^^^^^^^^^ @@ -364,11 +364,11 @@ The following shows the syntax for running parallel statements: $ $$ -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -.. _execution_details_view_5.4.3: +.. _execution_details_view_5.4.7: -.. _execution_tree_5.4.3: +.. _execution_tree_5.4.7: Execution Details View -------------- @@ -477,16 +477,16 @@ This can be seen in the **timeSum** column as follows: * **Rows highlighted orange** - medium runtime * **Rows highlighted yellow** - shortest runtime -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -.. _sql_view_5.4.3: +.. _sql_view_5.4.7: Viewing Wrapped Strings in the SQL View ------------------ The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. -.. _save_results_to_clipboard_5.4.3: +.. _save_results_to_clipboard_5.4.7: -:ref:`Back to Viewing Statement and Query Results from the Results Panel` +:ref:`Back to Viewing Statement and Query Results from the Results Panel` -:ref:`Back to Executing Statements and Running Queries from the Editor` +:ref:`Back to Executing Statements and Running Queries from the Editor` diff --git a/sqream_studio_5.4.7/getting_started.rst b/sqream_studio_5.4.7/getting_started.rst index 7f401f5fa..21d9348c0 100644 --- a/sqream_studio_5.4.7/getting_started.rst +++ b/sqream_studio_5.4.7/getting_started.rst @@ -1,7 +1,7 @@ .. _getting_started: **************************** -Getting Started with SQream Acceleration Studio 5.4.3 +Getting Started with SQream Acceleration Studio 5.4.7 **************************** Setting Up and Starting Studio ---------------- @@ -56,6 +56,6 @@ By clicking the user icon, you can also use it for logging out and viewing the f * License storage capacity * Log out -.. _back_to_dashboard_5.4.3: +.. _back_to_dashboard_5.4.7: -.. _studio_dashboard_5.4.3: +.. _studio_dashboard_5.4.7: diff --git a/sqream_studio_5.4.7/index.rst b/sqream_studio_5.4.7/index.rst index d98df64d5..d57789b49 100644 --- a/sqream_studio_5.4.7/index.rst +++ b/sqream_studio_5.4.7/index.rst @@ -3,9 +3,9 @@ ********************************** SQream Acceleration Studio ********************************** -The SQream Acceleration Studio 5.4.3 is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. +The SQream Acceleration Studio 5.4.7 is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. -This section describes how to use the SQream Accleration Studio version 5.4.3: +This section describes how to use the SQream Accleration Studio version 5.4.7: .. toctree:: :maxdepth: 1 diff --git a/sqream_studio_5.4.7/viewing_logs.rst b/sqream_studio_5.4.7/viewing_logs.rst index 7f98bea5e..c4e4b73a3 100644 --- a/sqream_studio_5.4.7/viewing_logs.rst +++ b/sqream_studio_5.4.7/viewing_logs.rst @@ -1,6 +1,6 @@ .. _viewing_logs: -.. _logs_top_5.4.3: +.. _logs_top_5.4.7: **************************** Viewing Logs @@ -13,19 +13,19 @@ The **Logs** screen is used for viewing logs and includes the following elements * - Element - Description - * - :ref:`Filter area` + * - :ref:`Filter area` - Lets you filter the data shown in the table. - * - :ref:`Query tab` + * - :ref:`Query tab` - Shows basic query information logs, such as query number and the time the query was run. - * - :ref:`Session tab` + * - :ref:`Session tab` - Shows basic session information logs, such as session ID and user name. - * - :ref:`System tab` + * - :ref:`System tab` - Shows all system logs. - * - :ref:`Log lines tab` + * - :ref:`Log lines tab` - Shows the total amount of log lines. -.. _filter_5.4.3: +.. _filter_5.4.7: Filtering Table Data ------------- @@ -41,9 +41,9 @@ Other filters require you to select an item from a dropdown menu: You can also export a record of all of your currently filtered logs in Excel format by clicking **Download** located above the Filter area. -.. _queries_5.4.3: +.. _queries_5.4.7: -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` Viewing Query Logs @@ -62,9 +62,9 @@ From the Queries area you can see and sort by the following: In the Queries table, you can click on the **Statement ID** and **Query** items to set them as your filters. In the **Details** column you can also access additional details by clicking one of the **Details** options for a more detailed explanation of the query. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _sessions_5.4.3: +.. _sessions_5.4.7: Viewing Session Logs ---------- @@ -82,9 +82,9 @@ From here you can see and sort by the following: In the Sessions table, you can click on the **Timestamp**, **Connection ID**, and **Username** items to set them as your filters. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _system_5.4.3: +.. _system_5.4.7: Viewing System Logs ---------- @@ -98,9 +98,9 @@ From here you can see and sort by the following: In the Systems table, you can click on the **Timestamp** and **Log type** items to set them as your filters. In the **Message** column, you can also click on an item to show more information about the message. -:ref:`Back to Viewing Logs` +:ref:`Back to Viewing Logs` -.. _log_lines_5.4.3: +.. _log_lines_5.4.7: Viewing All Log Lines ---------- @@ -119,4 +119,4 @@ From here you can see and sort by the following: In the **LOG LINES** table, you can click on any of the items to set them as your filters. -:ref:`Back to Viewing Logs` \ No newline at end of file +:ref:`Back to Viewing Logs` \ No newline at end of file From 13261d752364c298c848b73f9f2397f4164ad217 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Sun, 21 Aug 2022 17:04:11 +0300 Subject: [PATCH 0229/1892] Changed title to 5.4.7 --- sqream_studio_5.4.7/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqream_studio_5.4.7/index.rst b/sqream_studio_5.4.7/index.rst index d57789b49..17c7ae05c 100644 --- a/sqream_studio_5.4.7/index.rst +++ b/sqream_studio_5.4.7/index.rst @@ -1,7 +1,7 @@ .. _sqream_studio_: ********************************** -SQream Acceleration Studio +SQream Acceleration Studio 5.4.7 ********************************** The SQream Acceleration Studio 5.4.7 is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. From 5bb47aaef6c231fbcacb9572eb1d65014e6123ae Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 22 Aug 2022 17:43:10 +0300 Subject: [PATCH 0230/1892] Absolute links --- releases/2022.1.2.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 385216c21..8f7fcc8f6 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -35,7 +35,7 @@ Automatic Foreign Table DDL Resolution ************ When mapping external files to foreign tables, SQream now automatically identifies the required schema. This is especially useful for Parquet files, which include built-in schema declarations. -For more information, see :ref:`automatic_foreign_table_ddl_resolution`. +For more information, see `Automatic Foreign Table DDL Resolution `_. Enhanced Automatic Adaptive Compression ************ @@ -43,11 +43,11 @@ SQream's automatic adaptive compression has been enhanced with new compression m .. note:: The compression ratio depends on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. -For more information, navigate to the **Compression Methods** table on the :ref:`compression` page. +For more information, navigate to the **Compression Methods** table on the `Compression `_ page. Parquet Read Optimization ************ -SQream now supports storing and running queries on data located on external Parquet files. For more information, see :ref:`parquet`. +SQream now supports storing and running queries on data located on external Parquet files. For more information, see `Inserting Data from a Parquet File `_. Resolved Issues --------- @@ -60,10 +60,6 @@ The following table lists the issues that were resolved in Version 2022.1.2: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | SQ-11273 | Clustering ``partial-partial`` optimization only occurs when copying data from CSV files. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11291 | Metadata filters were not applied when using the ``LIKE`` function, causing certain queries to run on full tables instead of sorted data. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - -**Comment** - *Was SQ-11291 just removed?* Operations and Configuration Changes -------- From db8995e55df536c9c1fdeb62e0a4774d7bffa687 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Mon, 22 Aug 2022 17:59:29 +0300 Subject: [PATCH 0231/1892] Update parquet.rst --- data_ingestion/parquet.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index df09891d3..9a8e4c24b 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -11,7 +11,7 @@ This guide covers inserting data from Parquet files into SQream using :ref:`FORE Overview =================== -As described in **Inserting Data from a Parquet File** section, you can insert data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of inserting it into SQream. SQream supports executing queries on external Parquet files. +SQream supports inserting data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of inserting it into SQream. SQream supports executing queries on external Parquet files. Preparing Your Parquet Files ===================== From 242709e9e707ed47e80ce15a2fcf0bfa7d9cfd48 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 23 Aug 2022 17:49:23 +0300 Subject: [PATCH 0232/1892] Corrected the 2022.1.2 release notes --- releases/2022.1.2.rst | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 8f7fcc8f6..076da49d9 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -17,11 +17,11 @@ The 2022.1.2 Release Notes describes the following: :: -* Enhanced compression features. +* Added `zlib` compression. :: -* Support for external Parquet files. +* Optimized queries on external Parquet tables. New Features ---------- @@ -37,17 +37,13 @@ When mapping external files to foreign tables, SQream now automatically identifi For more information, see `Automatic Foreign Table DDL Resolution `_. -Enhanced Automatic Adaptive Compression +Added `zlib` compression ************ -SQream's automatic adaptive compression has been enhanced with new compression methods. This mechanism automatically uses the best compression method for each scenario, improving the compression ratio by approximately twice of that in Version 2022.1 - -.. note:: The compression ratio depends on the nature of the compressed data and on other variables, such as ordering, cardinality and data types. - -For more information, navigate to the **Compression Methods** table on the `Compression `_ page. +Added support for the `zlib` compression algorithm. For more information, navigate to the **Compression Methods** table on the `Compression `_ page. Parquet Read Optimization ************ -SQream now supports storing and running queries on data located on external Parquet files. For more information, see `Inserting Data from a Parquet File `_. +Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. Resolved Issues --------- @@ -58,7 +54,7 @@ The following table lists the issues that were resolved in Version 2022.1.2: +=============+===========================================================================================================================================+ | SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11273 | Clustering ``partial-partial`` optimization only occurs when copying data from CSV files. | +| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes @@ -118,4 +114,4 @@ Upgrading to v2022.1.2 :glob: :hidden: - 2022.1.2 \ No newline at end of file + 2022.1.2 From 775cd692cd19fb5d1910250420b3646aec679c5c Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 23 Aug 2022 18:08:59 +0300 Subject: [PATCH 0233/1892] Removed mentions of zlib in 2022.1.2 Since it was already released in 2022.1.1 --- releases/2022.1.2.rst | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 076da49d9..3a01464f0 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -17,10 +17,6 @@ The 2022.1.2 Release Notes describes the following: :: -* Added `zlib` compression. - - :: - * Optimized queries on external Parquet tables. New Features @@ -36,10 +32,6 @@ Automatic Foreign Table DDL Resolution When mapping external files to foreign tables, SQream now automatically identifies the required schema. This is especially useful for Parquet files, which include built-in schema declarations. For more information, see `Automatic Foreign Table DDL Resolution `_. - -Added `zlib` compression -************ -Added support for the `zlib` compression algorithm. For more information, navigate to the **Compression Methods** table on the `Compression `_ page. Parquet Read Optimization ************ @@ -54,7 +46,9 @@ The following table lists the issues that were resolved in Version 2022.1.2: +=============+===========================================================================================================================================+ | SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | +| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes From 788b6edfe601c0e4147c890fe1e1ad97375e49b1 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 23 Aug 2022 18:10:50 +0300 Subject: [PATCH 0234/1892] Fixed resolved issues table --- releases/2022.1.2.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 3a01464f0..aad45464c 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -48,8 +48,6 @@ The following table lists the issues that were resolved in Version 2022.1.2: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes -------- From 476eb971fa6fcf9134632f42fb77852db88849c6 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 24 Aug 2022 16:36:27 +0300 Subject: [PATCH 0235/1892] Update JDBC version --- connecting_to_sqream/client_drivers/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index b230faaef..fb772853c 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -17,7 +17,7 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC .jar file `_ - sqream-jdbc-4.5.4 (.jar) * `JDBC driver `_ .. _tableau_connector: @@ -81,4 +81,4 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older drivers? -If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. \ No newline at end of file +If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. From 0f01559929702ff0c6bbfd2b69ecc4fbbc1f0da3 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 24 Aug 2022 16:38:59 +0300 Subject: [PATCH 0236/1892] Removed explicit mention of the auto schema feature --- releases/2022.1.2.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index aad45464c..a44d83d83 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -27,12 +27,6 @@ The 2022.1.2 Release Notes include the following new features: :local: :depth: 1 -Automatic Foreign Table DDL Resolution -************ -When mapping external files to foreign tables, SQream now automatically identifies the required schema. This is especially useful for Parquet files, which include built-in schema declarations. - -For more information, see `Automatic Foreign Table DDL Resolution `_. - Parquet Read Optimization ************ Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. From 1165daf511033824c002c27750392bcb1b446709 Mon Sep 17 00:00:00 2001 From: Yaniv Gerowitz Date: Fri, 26 Aug 2022 13:27:54 -0700 Subject: [PATCH 0237/1892] Update 2022.1.2.rst --- releases/2022.1.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index a44d83d83..769bf60bc 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -100,4 +100,4 @@ Upgrading to v2022.1.2 :glob: :hidden: - 2022.1.2 + 2022.1.2 \ No newline at end of file From 0fc7ddda88024a4b91c6b7387b483c501e4aee4d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 08:24:11 +0300 Subject: [PATCH 0238/1892] Add 2022.1.3 RN page --- releases/2022.1.3.rst | 103 ++++++++++++++++++++++++++++++++++++++ releases/2022.1_index.rst | 1 + 2 files changed, 104 insertions(+) create mode 100644 releases/2022.1.3.rst diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst new file mode 100644 index 000000000..769bf60bc --- /dev/null +++ b/releases/2022.1.3.rst @@ -0,0 +1,103 @@ +.. _2022.1.2: + +************************** +Release Notes 2022.1.2 +************************** +The 2022.1.2 release notes were released on 8/24/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.2 Release Notes describes the following: + +* Automatic schema identification. + + :: + +* Optimized queries on external Parquet tables. + +New Features +---------- +The 2022.1.2 Release Notes include the following new features: + +.. contents:: + :local: + :depth: 1 + +Parquet Read Optimization +************ +Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.2: + ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+===========================================================================================================================================+ +| SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ + +Operations and Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +No features were deprecated for Version 2022.1.2. + +End of Support +------- +The End of Support section is not relevant to Version 2022.1.2. + +Upgrading to v2022.1.2 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.2 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 5f53bcb38..beceab0b6 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.3 2022.1.2 2022.1.1 2022.1 \ No newline at end of file From cc7ff075f5b7c66cc672e704dfce80e669c5a040 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 08:37:32 +0300 Subject: [PATCH 0239/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 769bf60bc..beeb68679 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -1,9 +1,9 @@ -.. _2022.1.2: +.. _2022.1.3: ************************** -Release Notes 2022.1.2 +Release Notes 2022.1.3 ************************** -The 2022.1.2 release notes were released on 8/24/2022 and describe the following: +The 2022.1.3 release notes were released on 9/8/2022 and describe the following: .. contents:: :local: @@ -11,7 +11,7 @@ The 2022.1.2 release notes were released on 8/24/2022 and describe the following Version Content ---------- -The 2022.1.2 Release Notes describes the following: +The 2022.1.3 Release Notes describes the following: * Automatic schema identification. @@ -21,7 +21,7 @@ The 2022.1.2 Release Notes describes the following: New Features ---------- -The 2022.1.2 Release Notes include the following new features: +The 2022.1.3 Release Notes include the following new features: .. contents:: :local: @@ -33,7 +33,7 @@ Querying Parquet foreign tables has been optimized and is now up to 20x faster t Resolved Issues --------- -The following table lists the issues that were resolved in Version 2022.1.2: +The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -53,13 +53,13 @@ No relevant naming changes were made. Deprecated Features ------- -No features were deprecated for Version 2022.1.2. +No features were deprecated for Version 2022.1.3. End of Support ------- -The End of Support section is not relevant to Version 2022.1.2. +The End of Support section is not relevant to Version 2022.1.3. -Upgrading to v2022.1.2 +Upgrading to v2022.1.3 ------- 1. Generate a back-up of the metadata by running the following command: @@ -93,11 +93,11 @@ Upgrading to v2022.1.2 $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. .. toctree:: :maxdepth: 2 :glob: :hidden: - 2022.1.2 \ No newline at end of file + 2022.1.3 \ No newline at end of file From 3297854d25a65da7150bbbbb43d6aa60667cba75 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 09:31:40 +0300 Subject: [PATCH 0240/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index beeb68679..37b9e90c6 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -13,11 +13,20 @@ Version Content ---------- The 2022.1.3 Release Notes describes the following: -* Automatic schema identification. +* Optimize the delete operation by removing redundant calls. :: -* Optimized queries on external Parquet tables. +* Support LIKE condition for filtering metadata. + + :: + +* Migration tool for converting VARCHAR columns into TEXT columns. + + :: + +* Support sub-queries in the UPDATE condition. + New Features ---------- @@ -27,9 +36,9 @@ The 2022.1.3 Release Notes include the following new features: :local: :depth: 1 -Parquet Read Optimization +Support sub-queries in the UPDATE condition ************ -Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. +Update functionality has been enhanced to support sub-queries allowing to update table and / or columns based on other table and / or columns. Resolved Issues --------- @@ -38,9 +47,19 @@ The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +=============+===========================================================================================================================================+ -| SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | +| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11378 | Python connector fails to run multi threaded per one connection. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11320 | Locked users are not being released on system reset. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | ++-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ +| SQ-11287 | SQL User Defined Function declaration fails when UDF contains parenthesis. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | +| SQ-10892 | Update || enhanced error message when trying to run update on foreign table. | +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes @@ -57,7 +76,10 @@ No features were deprecated for Version 2022.1.3. End of Support ------- -The End of Support section is not relevant to Version 2022.1.3. +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. +VARCHAR is no longer supported for new customers - effective immanently. +TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. +As part of this release 2022.1.3, SQream provides an automated and secured migration tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information. Upgrading to v2022.1.3 ------- From dbfeb529b16b61c4f0cf925126990ba228e2ee8e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 09:51:52 +0300 Subject: [PATCH 0241/1892] Update VARCHAR deprecation msg --- releases/2022.1.1.rst | 4 +++- releases/2022.1.2.rst | 4 +++- releases/2022.1.3.rst | 3 --- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index faec3add2..d5c76b361 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -63,7 +63,9 @@ No relevant naming changes were made. Deprecated Features ------- -No features were deprecated for Version 2022.1.1. +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. + +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. End of Support ------- diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 769bf60bc..0c9a4f3b3 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -53,7 +53,9 @@ No relevant naming changes were made. Deprecated Features ------- -No features were deprecated for Version 2022.1.2. +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. + +If you are using an earlier version of SQream, see the `Using Legacy String Literals `_ configuration flag. End of Support ------- diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 37b9e90c6..46199e037 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -32,9 +32,6 @@ New Features ---------- The 2022.1.3 Release Notes include the following new features: -.. contents:: - :local: - :depth: 1 Support sub-queries in the UPDATE condition ************ From aae33c7a9553fabd6cffe577e046353993c21fb0 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 10:06:35 +0300 Subject: [PATCH 0242/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 47 ++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 46199e037..fea508cb6 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -41,23 +41,25 @@ Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1.3: -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================================================================+ -| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11378 | Python connector fails to run multi threaded per one connection. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11320 | Locked users are not being released on system reset. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11287 | SQL User Defined Function declaration fails when UDF contains parenthesis. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10892 | Update || enhanced error message when trying to run update on foreign table. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------+-------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+=================================================================================================+ +| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11378 | Python connector fails to run multi threaded per one connection. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11320 | Locked users are not being released on system reset. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11287 | SQL User Defined Function declaration fails when UDF contains parenthesis. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | ++-------------+-------------------------------------------------------------------------------------------------+ + + Operations and Configuration Changes -------- @@ -69,15 +71,18 @@ No relevant naming changes were made. Deprecated Features ------- -No features were deprecated for Version 2022.1.3. - -End of Support -------- SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + VARCHAR is no longer supported for new customers - effective immanently. + TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + As part of this release 2022.1.3, SQream provides an automated and secured migration tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information. +End of Support +------- +No End of Support changes were made. + Upgrading to v2022.1.3 ------- 1. Generate a back-up of the metadata by running the following command: From 2d678574f10a5bf4fc8e94cf10c4dff95ed77936 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Sep 2022 14:45:45 +0300 Subject: [PATCH 0243/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index fea508cb6..37b731a0a 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -46,8 +46,6 @@ The following table lists the issues that were resolved in Version 2022.1.3: +=============+=================================================================================================+ | SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | +-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11378 | Python connector fails to run multi threaded per one connection. | -+-------------+-------------------------------------------------------------------------------------------------+ | SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | +-------------+-------------------------------------------------------------------------------------------------+ | SQ-11320 | Locked users are not being released on system reset. | From e973e38343a45febcb324b4644f4f89742c7c6eb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Sep 2022 08:35:25 +0300 Subject: [PATCH 0244/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 37b731a0a..486ed2244 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -27,15 +27,16 @@ The 2022.1.3 Release Notes describes the following: * Support sub-queries in the UPDATE condition. +Known Issues +--------- +The following table lists the issues that are known limitations in Version 2022.1.3: -New Features ----------- -The 2022.1.3 Release Notes include the following new features: ++-------------+--------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+============================================================================================+ +| SQ-11677 | UPADTE or DELETE using a sub-query that includes '%' (modulo) is crashing SQreamDB worker | ++-------------+--------------------------------------------------------------------------------------------+ - -Support sub-queries in the UPDATE condition -************ -Update functionality has been enhanced to support sub-queries allowing to update table and / or columns based on other table and / or columns. Resolved Issues --------- From 8bbf57ec1862f4373b40309fe92e134100c99b5a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Sep 2022 14:28:02 +0300 Subject: [PATCH 0245/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 486ed2244..7d49b64c3 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -53,8 +53,6 @@ The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------+ | SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | +-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11287 | SQL User Defined Function declaration fails when UDF contains parenthesis. | -+-------------+-------------------------------------------------------------------------------------------------+ | SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | +-------------+-------------------------------------------------------------------------------------------------+ From e357e7ab04b4a72e98ca2bd56b1dc08eb8bcf7b3 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 14 Sep 2022 10:50:44 +0300 Subject: [PATCH 0246/1892] GETDATE is not supported as a default value --- reference/sql/sql_statements/ddl_commands/create_table.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index eb25baa8a..9fd4bacf5 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may either be a literal, **GETDATE()**, or Null, which is evaluated at the time the row is created. +The value may either be NULL or a literal. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. @@ -293,4 +293,4 @@ The following table describes the properties that must be copied from the target Permissions ============= -The role must have the ``CREATE`` permission at the schema level. \ No newline at end of file +The role must have the ``CREATE`` permission at the schema level. From cf5277a47ef364040426cd4532110c5123c7ea05 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 18 Sep 2022 10:48:21 +0300 Subject: [PATCH 0247/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 7d49b64c3..b1412f577 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -55,7 +55,8 @@ The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------+ | SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | +-------------+-------------------------------------------------------------------------------------------------+ - +https://sqream.atlassian.net/browse/SQ-11287 +https://sqream.atlassian.net/browse/SQ-11187 Operations and Configuration Changes From f4ea9959802cc0ec6fef957c31953496a1b549b8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 20 Sep 2022 11:25:00 +0300 Subject: [PATCH 0248/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index b1412f577..a237f1ee6 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -53,10 +53,13 @@ The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------+ | SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | +-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11287 | SQL User Defined Function fails when function definition contain parenthesis | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11187 | FLAT compression is wrongly chosen when dealing with data sets starting with all-nulls | ++-------------+-------------------------------------------------------------------------------------------------+ | SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | +-------------+-------------------------------------------------------------------------------------------------+ -https://sqream.atlassian.net/browse/SQ-11287 -https://sqream.atlassian.net/browse/SQ-11187 + Operations and Configuration Changes @@ -115,7 +118,7 @@ Upgrading to v2022.1.3 $ ./upgrade_storage - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. .. toctree:: :maxdepth: 2 From 74b740074bcf3f9b9ffe5cf0407832430400f826 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 20 Sep 2022 11:33:07 +0300 Subject: [PATCH 0249/1892] Update 2022.1.3.rst --- releases/2022.1.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index a237f1ee6..548c8673c 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.3 ************************** -The 2022.1.3 release notes were released on 9/8/2022 and describe the following: +The 2022.1.3 release notes were released on 9/20/2022 and describe the following: .. contents:: :local: From e43dbdb42b90cc51237e27a91cbac6b3c4cfa25a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 20 Sep 2022 16:34:29 +0300 Subject: [PATCH 0250/1892] Update index.rst Fix misspells --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index fb772853c..5365380b9 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -40,7 +40,7 @@ Windows -------------- The following are applicable to Windows: -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `SSream represenative `_ for this installer. +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customization. Please contact your `SQream representative `_ for this installer. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. From 6c7cf5116b0297a92853fa8337b24c21a707450e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 21 Sep 2022 10:03:23 +0300 Subject: [PATCH 0251/1892] Add non production HW specs and fix some broken links --- getting_started/hardware_guide.rst | 4 +- .../non_production_hardware_guide.rst | 49 +++++++++++++++++++ index.rst | 6 +-- 3 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 getting_started/non_production_hardware_guide.rst diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 5337db9cd..c502f60bf 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -225,4 +225,6 @@ For clustered scale-out installations, SQream relies on NAS/SAN storage. For sta SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream Reference Architecture `_ document. \ No newline at end of file +Download the full `SQream Reference Architecture `_ document. + +.. note:: Non production HW requirements may be found at `Non Production HW Requirements `_ \ No newline at end of file diff --git a/getting_started/non_production_hardware_guide.rst b/getting_started/non_production_hardware_guide.rst new file mode 100644 index 000000000..03c738887 --- /dev/null +++ b/getting_started/non_production_hardware_guide.rst @@ -0,0 +1,49 @@ +.. non_production_hardware_guide: + +*************************************** +Staging and Development Hardware Guide +*************************************** +The **Staging and Development Hardware Guide** describes the SQream recommended HW for development, staging and or QA desktop and servers. + +.. warning:: The HW specification in this page are not intended for production use! + +Development Desktop +----------------------------------- + ++------------------+-----------------------------------------------+ +| **Component** | **Type** | ++==================+===============================================+ +| Server | PC | ++------------------+-----------------------------------------------+ +| Processor | Intel i7 | ++------------------+-----------------------------------------------+ +| RAM | 64GB RAM | ++------------------+-----------------------------------------------+ +| Onboard storage | 2TB SSD | ++------------------+-----------------------------------------------+ +| GPU | 1x NVIDIA RTX A4000 16GB | ++------------------+-----------------------------------------------+ +| Operating System | Red Hat Enterprise Linux v7.9 or CentOS v7.9 | ++------------------+-----------------------------------------------+ + + +Lab Server +----------------------------------- + ++------------------+------------------------------------------------------------+ +| **Component** | **Type** | ++==================+============================================================+ +| Server | Dell R640 or similar | ++------------------+------------------------------------------------------------+ +| Processor | x2 Intel(R) Xeon(R) Silver 4112 CPU @ 2.60GHz | ++------------------+------------------------------------------------------------+ +| RAM | 128 or 256 GB | ++------------------+------------------------------------------------------------+ +| Onboard storage | "2x 960GB SSD 2.5in hot plug for OS, RAID1 | ++------------------+------------------------------------------------------------+ +| | 1(or more)x 3.84TB SSD 2.5in Hot plug for storage, RAID5" | ++------------------+------------------------------------------------------------+ +| GPU | 1xNVIDIA T4 or A40 or A10 | ++------------------+------------------------------------------------------------+ +| Operating System | Red Hat Enterprise Linux v7.9 or CentOS v7.9 | ++------------------+------------------------------------------------------------+ diff --git a/index.rst b/index.rst index d6a37d4f7..c4bee46da 100644 --- a/index.rst +++ b/index.rst @@ -8,7 +8,7 @@ SQream DB Documentation .. tip:: Want to read this offline? - `Download the documentation as a single PDF `_ . + `Download the documentation as a single PDF `_ . .. only:: pdf or latex @@ -33,7 +33,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + `Getting Started `_ :ref:`sql_feature_support` @@ -45,7 +45,7 @@ SQream DB easily plugs in to third-party tools like :ref:`Tableau`_ + `Setting up SQream `_ :ref:`Best practices` From 072320e0bb312af20cf3bcaa8e632f6efd7d55bc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 21 Sep 2022 10:27:33 +0300 Subject: [PATCH 0252/1892] Update conf.py Update latest version to 2022.1.3 --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 4151da1c4..305be5597 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '2022.1.2' +release = '2022.1.3' From 853c8a1440defc7be09afbadb38f0c3f520a930c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 29 Sep 2022 15:25:52 +0300 Subject: [PATCH 0253/1892] Update query_healer.rst --- feature_guides/query_healer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index f8bb7f694..305875447 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -11,7 +11,7 @@ The **Query Healer** page describes the following: Overview ---------- -The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. The following is an example of a log record for a query stuck in the query detection phase for more than five hours: From 06bc8165ae5e323c631b9c8d0bb1e491149f400d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Oct 2022 12:28:41 +0300 Subject: [PATCH 0254/1892] Create 2022.1.4.rst --- releases/2022.1.4.rst | 127 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 releases/2022.1.4.rst diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst new file mode 100644 index 000000000..43b1b1330 --- /dev/null +++ b/releases/2022.1.4.rst @@ -0,0 +1,127 @@ +.. _2022.1.4: + +************************** +Release Notes 2022.1.4 +************************** +The 2022.1.4 release notes were released on 10/XX/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.4 Release Notes describes the following: + +* Optimize the delete operation by removing redundant calls. + + :: + +* Support LIKE condition for filtering metadata. + + :: + +* Migration tool for converting VARCHAR columns into TEXT columns. + + :: + +* Support sub-queries in the UPDATE condition. + +Known Issues +--------- +The following table lists the issues that are known limitations in Version 2022.1.4: + ++-------------+--------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+============================================================================================+ +| SQ-11677 | UPADTE or DELETE using a sub-query that includes '%' (modulo) is crashing SQreamDB worker | ++-------------+--------------------------------------------------------------------------------------------+ + + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.4: + ++-------------+-------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=============+=================================================================================================+ +| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11320 | Locked users are not being released on system reset. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11287 | SQL User Defined Function fails when function definition contain parenthesis | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-11187 | FLAT compression is wrongly chosen when dealing with data sets starting with all-nulls | ++-------------+-------------------------------------------------------------------------------------------------+ +| SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | ++-------------+-------------------------------------------------------------------------------------------------+ + + + +Operations and Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v2022.1.4 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.4 \ No newline at end of file From 4175f1d2ec633a215e6a520085eab544a7e6bde1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Oct 2022 12:32:12 +0300 Subject: [PATCH 0255/1892] Update 2022.1.3.rst fix misspell --- releases/2022.1.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 548c8673c..9887f7a04 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -74,7 +74,7 @@ Deprecated Features ------- SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. -VARCHAR is no longer supported for new customers - effective immanently. +VARCHAR is no longer supported for new customers - effective immediately. TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. From 620a3167cb811b95ea88105f88806cbafa91ee6f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 11 Oct 2022 15:33:07 +0300 Subject: [PATCH 0256/1892] Remove irrelevant toctree --- releases/2022.1.1.rst | 6 ---- releases/2022.1.2.rst | 6 ---- releases/2022.1.4.rst | 59 ++++++++++++--------------------------- releases/2022.1_index.rst | 1 + 4 files changed, 19 insertions(+), 53 deletions(-) diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index d5c76b361..436287c6c 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -107,9 +107,3 @@ Upgrading to v2022.1.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 0c9a4f3b3..5c007f0ec 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -97,9 +97,3 @@ Upgrading to v2022.1.2 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.2 \ No newline at end of file diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 43b1b1330..6b9cbb5a0 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.4 ************************** -The 2022.1.4 release notes were released on 10/XX/2022 and describe the following: +The 2022.1.4 release notes were released on 10/11/2022 and describe the following: .. contents:: :local: @@ -13,52 +13,35 @@ Version Content ---------- The 2022.1.4 Release Notes describes the following: -* Optimize the delete operation by removing redundant calls. +* Security enhancement - Disable Python UDFs by default. :: -* Support LIKE condition for filtering metadata. - - :: - -* Migration tool for converting VARCHAR columns into TEXT columns. - - :: - -* Support sub-queries in the UPDATE condition. Known Issues --------- -The following table lists the issues that are known limitations in Version 2022.1.4: - -+-------------+--------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+============================================================================================+ -| SQ-11677 | UPADTE or DELETE using a sub-query that includes '%' (modulo) is crashing SQreamDB worker | -+-------------+--------------------------------------------------------------------------------------------+ +No relevant Known Issues. Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1.4: -+-------------+-------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+=================================================================================================+ -| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11320 | Locked users are not being released on system reset. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11287 | SQL User Defined Function fails when function definition contain parenthesis | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11187 | FLAT compression is wrongly chosen when dealing with data sets starting with all-nulls | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | -+-------------+-------------------------------------------------------------------------------------------------+ ++--------------+------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+==================================================================================================================+ +| SQ-11487 | Alter default permissions to grant update results in error | ++--------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11771 | Wrong results returned when execute select subquery | ++--------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11740 | A correlated subquery is blocked when having 'not exist' where clause in update query | ++--------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11584 | CUDA malloc error | ++--------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-10602 | Group by clause error | ++--------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-9813 | When executing copy from a parquet file that contain date values earlier than 1970, values are changed to 1970. | ++--------------+------------------------------------------------------------------------------------------------------------------+ @@ -119,9 +102,3 @@ Upgrading to v2022.1.4 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.4 \ No newline at end of file diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index beceab0b6..e5c24021d 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.4 2022.1.3 2022.1.2 2022.1.1 From c022974310478f16887810e2984fe81067acce08 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 11 Oct 2022 16:06:25 +0300 Subject: [PATCH 0257/1892] Update python_functions.rst --- feature_guides/python_functions.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 3717cdcd8..7aaea5051 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -6,6 +6,8 @@ Python UDF (User-Defined Functions) User-defined functions (UDFs) are a feature that extends SQream DB's built in SQL functionality. SQream DB's Python UDFs allow developers to create new functionality in SQL by writing the lower-level language implementation in Python. +.. note:: Starting v2022.1.4, Python UDF are disabled by default in order to enhance product security. Use the ``enablePythonUdfs`` configuration flag in order to enable Python UDF. + .. contents:: In this topic: :local: From 5fe9d223e9bb82f8470390bb94107b7e2fdebe67 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 12 Oct 2022 14:13:44 +0300 Subject: [PATCH 0258/1892] Update 2022.1.4.rst --- releases/2022.1.4.rst | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 6b9cbb5a0..0f3a6add0 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -27,21 +27,22 @@ Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1.4: -+--------------+------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+==============+==================================================================================================================+ -| SQ-11487 | Alter default permissions to grant update results in error | -+--------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11771 | Wrong results returned when execute select subquery | -+--------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11740 | A correlated subquery is blocked when having 'not exist' where clause in update query | -+--------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11584 | CUDA malloc error | -+--------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-10602 | Group by clause error | -+--------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-9813 | When executing copy from a parquet file that contain date values earlier than 1970, values are changed to 1970. | -+--------------+------------------------------------------------------------------------------------------------------------------+ ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=====================+==================================================================================================================+ +| SQ-11782 | Alter default permissions to grant update results in error | ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11771 | Wrong results returned when execute select subquery | ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11740 | A correlated subquery is blocked when having 'not exist' where clause in update query | ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-11686, SQ-11584 | CUDA malloc error | ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-10602 | Group by clause error | ++---------------------+------------------------------------------------------------------------------------------------------------------+ +| SQ-9813 | When executing copy from a parquet file that contain date values earlier than 1970, values are changed to 1970. | ++---------------------+------------------------------------------------------------------------------------------------------------------+ + From 7aafdb3e9871e088e43cfbd53ae911441c4d16c9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:44:32 +0300 Subject: [PATCH 0259/1892] New file for 2022.1.5 release New file for 2022.1.5 release --- releases/2022.1.5.rst | 91 +++++++++++++++++++++++++++++++++++++++ releases/2022.1_index.rst | 1 + 2 files changed, 92 insertions(+) create mode 100644 releases/2022.1.5.rst diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst new file mode 100644 index 000000000..828ac3d5f --- /dev/null +++ b/releases/2022.1.5.rst @@ -0,0 +1,91 @@ +.. _2022.1.5: + +************************** +Release Notes 2022.1.5 +************************** +The 2022.1.5 release notes were released on 10/XX/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +Version Content +---------- +The 2022.1.5 Release Notes describes the following: + +XXXXXX TBD XXXXXXXXXXXXXXXXXXXX + + :: + + +Known Issues +--------- +No relevant Known Issues. + + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.5: + +XXXXXX TBD XXXXXXXXXXXXXXXXXXXX + + + + +Operations and Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v2022.1.5 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index e5c24021d..d6522a59b 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.5 2022.1.4 2022.1.3 2022.1.2 From 84d8101cf9443126a3f9831911cbd77b166e7de8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:49:15 +0300 Subject: [PATCH 0260/1892] Remove redundent toc tree that causes error --- releases/2022.1.3.rst | 6 ------ releases/2022.1.rst | 6 ------ 2 files changed, 12 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index 9887f7a04..b88eb78d9 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -120,9 +120,3 @@ Upgrading to v2022.1.3 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.3 \ No newline at end of file diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 3d1517371..6614d6458 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -129,9 +129,3 @@ Upgrading to v2022.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version `_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1 \ No newline at end of file From 90f0d9772ef43bdb62e8a196503c17071da57b08 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 19 Oct 2022 11:54:44 +0300 Subject: [PATCH 0261/1892] Remove redundent toc tree that causes error --- releases/2019.2.1.rst | 94 ---------------------------------------- releases/2020.1.rst | 6 --- releases/2020.2.rst | 6 --- releases/2020.3.1.rst | 6 --- releases/2020.3.2.1.rst | 6 --- releases/2021.1.2.rst | 6 --- releases/2021.1.rst | 6 --- releases/2021.2.1.24.rst | 6 --- releases/2021.2.1.rst | 6 --- releases/2021.2.rst | 6 --- 10 files changed, 148 deletions(-) delete mode 100644 releases/2019.2.1.rst diff --git a/releases/2019.2.1.rst b/releases/2019.2.1.rst deleted file mode 100644 index c9c96b59b..000000000 --- a/releases/2019.2.1.rst +++ /dev/null @@ -1,94 +0,0 @@ -.. _2019.2.1: - -****************************** -Release Notes 2019.2.1 -****************************** - -* 250 bugs fixed. Thanks to all of our customers and an unprecedented number of deployments for helping us find and fix these! -* Improved Unicode text handling on the GPU -* Improved logging and monitoring of statements -* Alibaba DataX connector - - -Improvements -===================== - -* We’ve updated the ``show_server_status()`` function to more accurately reflect the status of statements across the cluster: - - * Preparing – Initial validation - * In queue – Waiting for execution - * Initializing – Pre-execution processing - * Executing – statement is running - -* We’ve improved our log files and have unified them into a single file per worker, per date. Each message type has a unique code which can help identify potential issues. See the documentation for full details on the changes to the log structures. - -* ``WITH ADMIN OPTION`` added in ``GRANT``/``REVOKE`` operations, allowing roles to grant their own permissions to others. - -* HA cluster fully supports qualified hostnames, and no longer requires explicit IP addresses. - -* SQream DB CLI’s history can be disabled, by passing ``./ClientCmd --no-history`` - - -Behaviour Changes -===================== - -* SQream DB no longer applies an implicit cast from a long text column to a shorter text column (``VARCHAR``/``TEXT``). This means some ``INSERT``/``COPY`` operations will now error instead of truncating the text. This is intended to prevent accidental truncation of text columns. If you want the old truncation behaviour, you can use the ``SUBSTRING`` function to truncate the text. - - -Operations -===================== - -* The client-server protocol has been updated to support a wider range of encodings. End users are required to use only the latest ClientCmd, JDBC, and ODBC drivers delivered with this version. - -* Clients such as SecureCRT and other shells must have locale set as ``cp874`` or equivalent - -* When upgrading from SQream DB v3.2 or lower, the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` - - -Known Issues and Limitations -=================================== - -* TEXT columns cannot be used as a ``GROUP BY`` key when there are multiple ``COUNT (DISTINCT …)`` operations in a query - -* TEXT columns cannot be used in a statement containing window functions - -* TEXT is not supported as a join key - -* The following functions are not supported on ``TEXT`` column types: ``chr``, ``min``, ``max``, ``patindex``, ``to_binary``, ``to_hex``, ``rlike``, ``regexp_count``, ``regexp_instr``, ``regexp_substr`` - -* SQream Dashboard: Only works with a HA clustered installation - -* SQream Editor: External tables and UDFs don’t appear in the DB Tree but do appear in the relevant sqream_catalog entries. - - -Fixes -===================== - -250 bugs and issues fixed, including: - -* Variety of performance improvements: - -* Improved performance of ``TEXT`` by up to 315% for a variety of scenarios, including ``COPY FROM``, ``INNER JOIN``, ``LEFT JOIN``. - -* Improved load performance from previous versions - -* Faster compilation times for very complex queries - -* DWLM: - - * Fixed situation where queries were not distributed correctly among all available workers - * Fixed ``cannot execute - reconnectDb error`` error - * Fixed occasional hanging statement - * Fixed occasional ``Connection refused`` - -* Window functions: - - * Fixed window function edge-case ``error WindowA with no functions`` - * Fixed situations where the SUM window function is applied on a column, partitioned by a second, and sorted by a third would return wrong results when scanning very large datasets - -* Other bugs: - - * Fixed situation where many concurrent statements running would result in ``map::at`` appearing - * Fixed situation where SQream DB would restart when force-stopping an ``INSERT`` over the network - * Fixed situation where RAM wasn’t released immediately after statement has been executed - * Fixed Type doesn’t have a fixed size error that appeared when using an external table joined with a standard SQream DB table diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 86b619d54..769fa0ebb 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -187,9 +187,3 @@ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and othe Contact your account manager to get the latest release of SQream. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2020.1 \ No newline at end of file diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 917d80800..5a66e99bd 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -114,9 +114,3 @@ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and othe Contact your account manager to get the latest release of SQream. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2020.2 \ No newline at end of file diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst index b66454c75..9fa40cbb0 100644 --- a/releases/2020.3.1.rst +++ b/releases/2020.3.1.rst @@ -71,9 +71,3 @@ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and othe Contact your account manager to get the latest release of SQream. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2020.3.1 \ No newline at end of file diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst index 8fef047f6..29f3b3e88 100644 --- a/releases/2020.3.2.1.rst +++ b/releases/2020.3.2.1.rst @@ -30,9 +30,3 @@ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and othe Contact your account manager to get the latest release of SQream. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2020.3.2.1 \ No newline at end of file diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index 750420260..ee33cfbd8 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -60,9 +60,3 @@ The following list describes the resolved issues: * The ``REPLACE`` function only supported constant values as arguments. This was fixed. * The ``LIKE`` function did not check for incorrect patterns or handle escape characters. This was fixed. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.1.2 \ No newline at end of file diff --git a/releases/2021.1.rst b/releases/2021.1.rst index 389655262..02d5377d5 100644 --- a/releases/2021.1.rst +++ b/releases/2021.1.rst @@ -212,9 +212,3 @@ Upgrading to v2021.1 ------- Due to the known issue of a limitation on the amount of access requests that can be simultaneously sent to AWS, deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.1 \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index a89244934..d277ea51a 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -79,9 +79,3 @@ End of Support ------- The End of Support section is not relevant to Version 2021.2.1.24. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2.1.24 diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index e1a01a147..d50f1084e 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -78,9 +78,3 @@ Deprecated Features ------ The **Deprecated Components** section is not relevant to Version 2021.2.1. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2.1 \ No newline at end of file diff --git a/releases/2021.2.rst b/releases/2021.2.rst index 2140dc6be..f95de16a5 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -168,9 +168,3 @@ A new configuration method is used starting with Version 2021.2. For more information about configuring your instance of SQream, see `Client Drivers for 2021.2 `_. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2021.2 \ No newline at end of file From ff8d1d8d4f56daf27e803d8b6e3618dfc250164a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 19 Oct 2022 14:18:13 +0300 Subject: [PATCH 0262/1892] Update remedying_slow_queries.rst Fix broken links --- troubleshooting/remedying_slow_queries.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/troubleshooting/remedying_slow_queries.rst b/troubleshooting/remedying_slow_queries.rst index 8a109f0c0..9bd05b324 100644 --- a/troubleshooting/remedying_slow_queries.rst +++ b/troubleshooting/remedying_slow_queries.rst @@ -33,7 +33,7 @@ The following table is a checklist you can use to identify the cause of your slo - Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. - If the worker list is incomplete, follow the :ref:`cluster troubleshooting` section below. + If the worker list is incomplete, locate and start the missing worker(s). If all workers are up, continue to step 4. * - 4 @@ -73,7 +73,7 @@ The following table is a checklist you can use to identify the cause of your slo - Check free memory across hosts - #. Check free memory across the hosts by running ``$ free -th`` from the terminal. - #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`configuration` guide. + #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`spooling` guide. #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. If performance does not improve, contact SQream support for more help. \ No newline at end of file From 2596e3da9e04a54d10d183141590f84ce8e08e0b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Oct 2022 10:38:15 +0300 Subject: [PATCH 0263/1892] Update 2022.1.4.rst Remove customer sensitive bug --- releases/2022.1.4.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 0f3a6add0..338fdf164 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -32,8 +32,6 @@ The following table lists the issues that were resolved in Version 2022.1.4: +=====================+==================================================================================================================+ | SQ-11782 | Alter default permissions to grant update results in error | +---------------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11771 | Wrong results returned when execute select subquery | -+---------------------+------------------------------------------------------------------------------------------------------------------+ | SQ-11740 | A correlated subquery is blocked when having 'not exist' where clause in update query | +---------------------+------------------------------------------------------------------------------------------------------------------+ | SQ-11686, SQ-11584 | CUDA malloc error | From 89b87fcd68993fb8084b6bd66ba561932f1ae59e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 30 Oct 2022 13:40:30 +0200 Subject: [PATCH 0264/1892] Cuda 11.4 rollback Rollback Cude descriptions from 11.4 to 10.1 as 11.4 is yet to be released --- .../installing_sqream_with_kubernetes.rst | 16 ++++++------- .../running_sqream_in_a_docker_container.rst | 24 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/installation_guides/installing_sqream_with_kubernetes.rst b/installation_guides/installing_sqream_with_kubernetes.rst index aa7e22422..fbf2566ed 100644 --- a/installation_guides/installing_sqream_with_kubernetes.rst +++ b/installation_guides/installing_sqream_with_kubernetes.rst @@ -198,7 +198,7 @@ After completing all of the steps above, you must check the CUDA version. .. code-block:: postgres +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | @@ -220,7 +220,7 @@ After completing all of the steps above, you must check the CUDA version. | No running processes found | +-----------------------------------------------------------------------------+ -In the above output, the CUDA version is **11.4**. +In the above output, the CUDA version is **10.1**. If the above output is not generated, CUDA has not been installed. To install CUDA, see :ref:`installing-the-cuda-driver`. @@ -800,15 +800,15 @@ Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS .. code-block:: postgres - $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi The following is an example of the correct output: .. code-block:: postgres - docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi - Unable to find image 'nvidia/cuda:11.4.3-base-centos7' locally - 11.4.3-base-centos7: Pulling from nvidia/cuda + docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi + Unable to find image 'nvidia/cuda:10.1.3-base-centos7' locally + 10.1.3-base-centos7: Pulling from nvidia/cuda d519e2592276: Pull complete d22d2dfcfa9c: Pull complete b3afe92c540b: Pull complete @@ -816,10 +816,10 @@ Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS 4f0bc36a7e1d: Pull complete cd710321007d: Pull complete Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 - Status: Downloaded newer image for nvidia/cuda:11.4.3-base-centos7 + Status: Downloaded newer image for nvidia/cuda:10.1.3-base-centos7 Sun Feb 14 13:27:58 2021 +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index dd8d07e50..2a2454164 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -248,7 +248,7 @@ Installing the Nvidia CUDA Driver nvidia-smi Wed Oct 30 14:05:42 2019 +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | @@ -267,7 +267,7 @@ Installing the Nvidia CUDA Driver | No running processes found | +-----------------------------------------------------------------------------+ -#. Verify that the installed CUDA version shown in the output above is ``11.4``. +#. Verify that the installed CUDA version shown in the output above is ``10.1``. :: @@ -276,25 +276,25 @@ Installing the Nvidia CUDA Driver :: - 1. If CUDA version 11.4 has already been installed, skip to Docktime Runtime (Community Edition). + 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). :: - 2. If CUDA version 11.4 has not been installed yet, continue with Step 7 below. + 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. #. Do one of the following: - * Install :ref:`CUDA Driver version 11.4 for x86_64 `. + * Install :ref:`CUDA Driver version 10.1 for x86_64 `. :: * Install :ref:`CUDA driver version 10.1 for IBM Power9 `. -.. _CUDA_11.4_x8664: +.. _CUDA_10.1_x8664: -Installing the CUDA Driver Version 11.4 for x86_64 +Installing the CUDA Driver Version 10.1 for x86_64 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the CUDA driver version 11.4 for x86_64:** +**To install the CUDA driver version 10.1 for x86_64:** 1. Make the following target platform selections: @@ -352,7 +352,7 @@ For installer type, SQream recommends selecting **runfile (local)**. The availab nvidia-smi Wed Oct 30 14:05:42 2019 +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 11.4 | + | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | |-------------------------------+----------------------+----------------------+ | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | @@ -622,7 +622,7 @@ Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System .. code-block:: - $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system ` @@ -674,7 +674,7 @@ Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System .. code-block:: - $ docker run --runtime=nvidia --rm nvidia/cuda:11.4.3-base-centos7 nvidia-smi + $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system ` @@ -1062,7 +1062,7 @@ The following is an example of the correct output: METADATA_PORT=3105 PICKER_PORT=3108 NUM_OF_GPUS=2 - CUDA_VERSION=11.4 + CUDA_VERSION=10.1 NVIDIA_SMI_PATH=/usr/bin/nvidia-smi DOCKER_PATH=/usr/bin/docker NVIDIA_DRIVER=418 From 7d2e27c0d70e16f5709c0b3f52a04c1f229ca1db Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 30 Oct 2022 13:58:42 +0200 Subject: [PATCH 0265/1892] Update 2022.1.5.rst Add bug list --- releases/2022.1.5.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 828ac3d5f..318934b41 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.5 ************************** -The 2022.1.5 release notes were released on 10/XX/2022 and describe the following: +The 2022.1.5 release notes were released on 11/02/2022 and describe the following: .. contents:: :local: @@ -27,7 +27,22 @@ Resolved Issues --------- The following table lists the issues that were resolved in Version 2022.1.5: -XXXXXX TBD XXXXXXXXXXXXXXXXXXXX ++--------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+==========================================================================================+ +| SQ-11473 | SQream Command Line Interface connectivity issues | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11551 | SQream Studio Logs pages filtering issues | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11631 | Log related configuration flags are not working as expected | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11745 | Missing validation of sufficient GPU memory | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11792 | CUME_DIST function causes query execution errors | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11905 | GetDate casting to as text returns DATE with 0s in the time part or no time part at all | ++--------------+------------------------------------------------------------------------------------------+ + From 1572206fde5df85eeadb39331fad00131dc28a95 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 31 Oct 2022 08:56:43 +0200 Subject: [PATCH 0266/1892] add features details --- releases/2022.1.5.rst | 16 ++++++++++++---- troubleshooting/lock_related_issues.rst | 2 ++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 318934b41..2ff841d42 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -9,13 +9,21 @@ The 2022.1.5 release notes were released on 11/02/2022 and describe the followin :local: :depth: 1 -Version Content +New Features ---------- -The 2022.1.5 Release Notes describes the following: +The 2022.1.5 Release Notes include the following new features: + +* keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. -XXXXXX TBD XXXXXXXXXXXXXXXXXXXX + :: - :: +* Automatically close database connections that have been open for 24 hours without any active statements. + + :: + +* release_defunct_locks utility function enhancement to receive new optional input parameter to specify timeout - for more details see `Lock Related Issues <../troubleshooting/lock_related_issues.html>`_. + + Known Issues diff --git a/troubleshooting/lock_related_issues.rst b/troubleshooting/lock_related_issues.rst index 1a15858ec..ed1e21579 100644 --- a/troubleshooting/lock_related_issues.rst +++ b/troubleshooting/lock_related_issues.rst @@ -26,4 +26,6 @@ If the locks still appear in the :ref:`show_locks` utility, we can force remove t=> SELECT RELEASE_DEFUNCT_LOCKS(); executed +.. tip:: ``RELEASE_DEFUNCT_LOCKS`` has an optional input parameter to specify the number of seconds, after which ``RELEASE_DEFUNCT_LOCKS`` will execute. + .. warning:: This operation can cause some statements to fail on the specific worker on which they are queued. This is intended as a "last resort" to solve stale locks. \ No newline at end of file From 0d17c656203004634229eb5e1f14f0b07ecdfe74 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 31 Oct 2022 12:53:59 +0200 Subject: [PATCH 0267/1892] Update 2022.1.5.rst --- releases/2022.1.5.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 2ff841d42..1466882cc 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -17,7 +17,7 @@ The 2022.1.5 Release Notes include the following new features: :: -* Automatically close database connections that have been open for 24 hours without any active statements. +* Automatically close database client connections that have been open for 24 hours without any active statements. :: @@ -28,7 +28,7 @@ The 2022.1.5 Release Notes include the following new features: Known Issues --------- -No relevant Known Issues. +Recently discovered issue with the encryption feature, at this time SQream recommends to avoid using this feature - a fix will be introduced in the near future. Resolved Issues From 1e139a42cf6bc62f5ac9d9889772d7fc92e7f5a6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 1 Nov 2022 06:20:22 +0200 Subject: [PATCH 0268/1892] Update 2022.1.5.rst --- releases/2022.1.5.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 1466882cc..d63bf3b7a 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -38,6 +38,8 @@ The following table lists the issues that were resolved in Version 2022.1.5: +--------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+==========================================================================================+ +| SQ-11081 | Tableau connection are not getting closed | ++--------------+------------------------------------------------------------------------------------------+ | SQ-11473 | SQream Command Line Interface connectivity issues | +--------------+------------------------------------------------------------------------------------------+ | SQ-11551 | SQream Studio Logs pages filtering issues | From 2a5ea06da042851b5bbe51827ebaf29b731313e4 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Sun, 6 Nov 2022 11:58:52 +0200 Subject: [PATCH 0269/1892] Update catalog_reference_catalog_tables.rst --- reference/catalog_reference_catalog_tables.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 7ddb9c148..4f4d60b76 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -303,8 +303,6 @@ The ``roles`` data object identifies the roles in the database, as shown in the - Identifies whether the role can be used to log in to SQream (``1`` - yes, ``0`` - no). * - ``has_password`` - Identifies whether the role has a password (``1`` - yes, ``0`` - no). - * - ``can_create_function`` - - Identifies whether role can create UDFs (``1`` - yes, ``0`` - no). Role Memberships *********** From f6a1a094e274396619bf3f81d105045b1179364a Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 8 Nov 2022 10:54:20 +0200 Subject: [PATCH 0270/1892] Create external_data.rst --- operational_guides/external_data.rst | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 operational_guides/external_data.rst diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst new file mode 100644 index 000000000..c9a6cfb33 --- /dev/null +++ b/operational_guides/external_data.rst @@ -0,0 +1,26 @@ +.. _external_data: + +********************************** +Working with External Data +********************************** +SQream supports the following external data sources: + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + s3 + hdfs + mounting_an_nfs_shared_drive + +For more information, see the following: + +* :ref:`external_tables` + + :: + +* :ref:`copy_from` + + :: + +* :ref:`copy_to` \ No newline at end of file From ae7a7c79f6e3f8a24800ae1ce2ab4a9fa9fe52fd Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 8 Nov 2022 11:38:39 +0200 Subject: [PATCH 0271/1892] Removed NFS + Relocate Exteranl storage data Removed NFS + Relocate Exteranl storage data --- index.rst | 221 ++++++++++++++++++++--------- operational_guides/hdfs.rst | 265 +++++++++++++++++++++++++++++++++++ operational_guides/index.rst | 3 + operational_guides/s3.rst | 129 +++++++++++++++++ 4 files changed, 552 insertions(+), 66 deletions(-) create mode 100644 operational_guides/hdfs.rst create mode 100644 operational_guides/s3.rst diff --git a/index.rst b/index.rst index c4bee46da..00c01f392 100644 --- a/index.rst +++ b/index.rst @@ -4,6 +4,8 @@ SQream DB Documentation ************************* +For SQream version 2021.2. + .. only:: html .. tip:: @@ -14,67 +16,155 @@ SQream DB Documentation .. tip:: This documentation is available online at https://docs.sqream.com/ -SQream DB is a columnar analytic SQL database management system. - -SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. - -Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. - -SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. - -.. - .. ref`features_tour` - -.. list-table:: - :widths: 33 33 33 - :header-rows: 0 - - * - **Get Started** - - **Reference** - - **Guides** - * - - `Getting Started `_ - - :ref:`sql_feature_support` - - :ref:`Bulk load CSVs` - - - :ref:`SQL Reference` - - :ref:`sql_statements` - - :ref:`sql_functions` - - - `Setting up SQream `_ - - :ref:`Best practices` - - - * - **Releases** - - **Driver and Deployment** - - **Help and Support** - * - - :ref:`2022.1<2022.1>` - - :ref:`2021.2<2021.2>` - - :ref:`2021.1<2021.1>` - - :ref:`2020.3<2020.3>` - - :ref:`2020.2<2020.2>` - - :ref:`2020.1<2020.1>` - - :ref:`All recent releases` - - - - :ref:`Client drivers` - - - - :ref:`troubleshooting` guide - - :ref:`information_for_support` +SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. + +:ref:`client_platforms` + ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| Topic | Description | ++===================================================+========================================================================================================================================+ +| **Getting Started** | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`preparing_your_machine_to_install_sqream` | Set up your local machine according to SQream’s recommended pre-installation configurations. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`executing_statements_in_sqream` | Provides more information about the available methods for executing statements in SQream. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`performing_basic_sqream_operations` | Provides more information on performing basic operations. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hardware_guide` | Describes SQream’s mandatory and recommended hardware settings, designed for a technical audience. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **Installation Guides** | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`installing_and_launching_sqream` | Refers to SQream’s installation guides. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`sqream_studio_installation` | Refers to all installation guides required for installations related to Studio. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **Ingesting Data** | ++--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`csv` | :ref:`avro` | | ++--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`parquet` | :ref:`orc` | | ++--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`oracle` | ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Connecting to SQream** | ++--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_drivers` | Describes how to use the SQream client drivers and client applications with SQream. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **External Storage Platforms** | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`s3` | Describes how to insert data over a native S3 connector. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hdfs` | Describes how to configure an HDFS environment for the user sqream and is only relevant for users with an HDFS environment. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ + + + Loading and unloading data: + + * Loading data: + + * Overview of loading data + * Alternatives to loading data (foreign tables) + * Supported data types + * Ingesting data from external sources + * Inserting data from external tables + * Ingesting data from third party client platforms + * Using the **COPY FROM** statement + * Importing data using Studio + * Loading data using Amazon S3 + + * Unloading data: + + * Overview of unloading data + * Using the **COPY TO** statement + + Feature guides: + + * Query Healer + * Automatic schema Identification + * Compression + * Python UDF (User-Defined Functions) + * Workload Manager + * Transactions + * Concurrency and locks + * Concurrency and scaling in SQream DB + + Operational guides: + + * Access control + * Creating or cloning storage clusters + * Foreign tables + * Deleting data + * Exporting data + * Logging + * Monitoring query performance + * Security + * Saved queries + * Seeing system objects as DDL + * Optimization and best practices + + SQream Accelerated Studio 5.4.3: + + * Getting started with SQream Acceleration Studio 5.4.3 + * Monitoring workers and services from the dashboard + * Executing statements and running queries from the Editor + * Viewing logs + * Creating, assigning, and managing roles and permissions + * Configuring Your instance of SQream + + System architecture: + + * Internals and architecture + * Filesystem and usage + + Configuring SQream: + + * Configuration methods + * Configuration flags + + Reference guides: + + * SQL syntax, statements, and functions + * Catalog reference guide + * Command Line programs + * SQL feature checklist + * Python API reference guide + + Data type guides: + + * Converting and casting + * Supported data types + * Supported casts + + Release notes: + + * 2022.1 + * 2021.2 + * 2021.1 + * 2020.3 + * 2020.2 + * 2020.1 + + Troubleshooting: + + * Remedying slow queries + * Resolving common issues + * Examining logs + * Identifying configuration issues + * Lock related issues + * SAS Viya related issues + * Tableau related issues + * Solving “Code 126” ODBC errors + * Log related issues + * Node.js related issues + * Core dumping related issues + * SQream SQL installation related issues + * Gathering information for SQream support + + Glossary + @@ -85,9 +175,9 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? -This version of the documentation is for SQream DB Version 2022.1. +This version of the documentation is for SQream DB Version 2021.2. -If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com. +If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . .. toctree:: :caption: Contents: @@ -100,7 +190,6 @@ If you're looking for an older version of the documentation, versions 1.10 throu installation_guides/index data_ingestion/index connecting_to_sqream/index - external_storage_platforms/index loading_and_unloading_data/index feature_guides/index operational_guides/index @@ -114,9 +203,9 @@ If you're looking for an older version of the documentation, versions 1.10 throu glossary .. - Indices and Tables + Indices and tables ================== * :ref:`genindex` * :ref:`modindex` - * :ref:`search` \ No newline at end of file + * :ref:`search` diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst new file mode 100644 index 000000000..e59c49cc7 --- /dev/null +++ b/operational_guides/hdfs.rst @@ -0,0 +1,265 @@ +.. _hdfs: + +.. _back_to_top_hdfs: + +Using SQream in an HDFS Environment +======================================= + +.. _configuring_an_hdfs_environment_for_the_user_sqream: + +Configuring an HDFS Environment for the User **sqream** +---------------------------------------------------------- + +This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. + +**To configure an HDFS environment for the user sqream:** + +1. Open your **bash_profile** configuration file for editing: + + .. code-block:: console + + $ vim /home/sqream/.bash_profile + +.. + Comment: - see below; do we want to be a bit more specific on what changes we're talking about? + + .. code-block:: console + + $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin + + $ #export PATH + + $ # PS1 + $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') + $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +2. Verify that the edits have been made: + + .. code-block:: console + + source /home/sqream/.bash_profile + +3. Check if you can access Hadoop from your machine: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +.. + Comment: - + **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos `_ + + +4. Verify that an HDFS environment exists for SQream services: + + .. code-block:: console + + $ ls -l /etc/sqream/sqream_env.sh + +.. _step_6: + + +5. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): + + .. code-block:: console + + $ #!/bin/bash + + $ SQREAM_HOME=/usr/local/sqream + $ export SQREAM_HOME + + $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + + + $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + $ export PATH + +:ref:`Back to top ` + +.. _authenticate_hadoop_servers_that_require_kerberos: + +Authenticating Hadoop Servers that Require Kerberos +--------------------------------------------------- +If your Hadoop server requires Kerberos authentication, do the following: + +1. Create a principal for the user **sqream**. + + .. code-block:: console + + $ kadmin -p root/admin@SQ.COM + $ addprinc sqream@SQ.COM + +2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: + + .. code-block:: console + + $ kadmin.local + + Running **kadmin.local** does not require a password. + +3. If a password is not required, change your password to **sqream@SQ.COM**. + + .. code-block:: console + + $ change_password sqream@SQ.COM + +4. Connect to the hadoop name node using ssh: + + .. code-block:: console + + $ cd /var/run/cloudera-scm-agent/process + +5. Check the most recently modified content of the directory above: + + .. code-block:: console + + $ ls -lrt + +6. Look for a recently updated folder containing the text **hdfs**. + + The following is an example of the correct folder name: + + .. code-block:: console + + cd -hdfs- + + This folder should contain a file named **hdfs.keytab** or another similar .keytab file. + + + +.. + Comment: - Does "something" need to be replaced with "file name" + + +7. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. + + :: + +8. Copy the following files to the **sqream sqream@server:/hdfs/hadoop/etc/hadoop:** directory: + + * core-site.xml + * hdfs-site.xml + +9. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: + + .. code-block:: console + + $ sudo chown sqream:sqream /home/sqream/hdfs.keytab + $ sudo chmod 600 /home/sqream/hdfs.keytab + +10. Log into the sqream server. + + :: + +11. Log in as the user **sqream**. + + :: + +12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: + + .. code-block:: console + + $ klist -kt hdfs.keytab + + The following is an example of the correct output: + + .. code-block:: console + + $ sqream@Host-121 ~ $ klist -kt hdfs.keytab + $ Keytab name: FILE:hdfs.keytab + $ KVNO Timestamp Principal + $ ---- ------------------- ------------------------------------------------------ + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + +13. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. + + :: + +14. Run the following: + + .. code-block:: console + + $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM + +15. Verify that the output is correct: + + .. code-block:: console + + $ klist + + The following is an example of the correct output: + + .. code-block:: console + + $ Ticket cache: FILE:/tmp/krb5cc_1000 + $ Default principal: sqream@SQ.COM + $ + $ Valid starting Expires Service principal + $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM + +16. List the files located at the defined server name or IP address: + + .. code-block:: console + + $ hadoop fs -ls hdfs://:8020/ + +17. Do one of the following: + + :: + + * If the list below is output, continue with Step 18. + + :: + + * If the list is not output, verify that your environment has been set up correctly. + +If any of the following are empty, verify that you followed :ref:`Step 6 ` in the **Configuring an HDFS Environment for the User sqream** section above correctly: + + .. code-block:: console + + $ echo $JAVA_HOME + $ echo $SQREAM_HOME + $ echo $CLASSPATH + $ echo $HADOOP_COMMON_LIB_NATIVE_DIR + $ echo $LD_LIBRARY_PATH + $ echo $PATH + +18. Verify that you copied the correct keytab file. + + :: + +19. Review this procedure to verify that you have followed each step. + +:ref:`Back to top ` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 25e2cdff2..048efb06f 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -14,12 +14,15 @@ This section summarizes the following operational guides: access_control creating_or_cloning_a_storage_cluster + external_data foreign_tables delete_guide exporting_data logging monitoring_query_performance security + saved_queries seeing_system_objects_as_ddl configuration optimization_best_practices + hardware_guide diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst new file mode 100644 index 000000000..5e4f8b264 --- /dev/null +++ b/operational_guides/s3.rst @@ -0,0 +1,129 @@ +.. _s3: + +*********************** +Inserting Data Using Amazon S3 +*********************** +SQream uses a native S3 connector for directly inserting data from a number of external sources directly into SQream. This is done using the ``s3://`` URI to specify an external file path on an S3 bucket. Your files can be saved in CSV or columnar format, such as Parquet and ORC, and your file names can include wildcard characters. + +The **Amazon S3** page describes the following topics: + +.. contents:: + :local: + :depth: 1 + +Configuring Amazon S3 +============================== +Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. + +Setting the S3 URI Format +=============== +With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. + +The following is an example of the general S3 syntax: + +.. code-block:: console + + s3://bucket_name/path + +Authenticating Users +================= + +SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. + +Examples +========== +You can use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. + +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Planning for Data Staging +-------------------------------- +The examples in this section are based on the CSV file shown in the following table: + +.. csv-table:: nba-t10 + :file: ../_static/samples/nba-t10.csv + :widths: auto + :header-rows: 1 + +This CSV file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make a record of your source file's structure and use it to reproduce a corresponding foreign table, as shown in the following section. + +Creating a Foreign Table +----------------------------- +Based on the source file's structure above, you can create a foreign table with the structure you want and point it to your file, as shown in the following example: + +.. code-block:: postgres + + CREATE FOREIGN TABLE nba + ( + Name text(40), + Team text(40), + Number tinyint, + Position text(2), + Age tinyint, + Height text(4), + Weight real, + College text(40), + Salary float + ) + WRAPPER csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba_players.csv', + RECORD_DELIMITER = '\r\n' -- DOS delimited file + ) + ; + +.. note:: In the example above the file format is CSV and is stored as an S3 object. If your file has an HDFS path, you must change the URI accordingly. Note that the record delimiter is a DOS newline (``\r\n``). + +For more information, see the following: + +* **Creating a foreign table** - see :ref:`creating a foreign table`. +* **Using SQream in an HDFS environment** - see :ref:`hdfs`. + +Querying Foreign Tables +------------------------------ +The following shows the data located in the foreign table: + +.. code-block:: psql + + t=> SELECT * FROM nba LIMIT 10; + name | team | number | position | age | height | weight | college | salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +Bulk Loading a File from a Public S3 Bucket +---------------------------------------------- +Youc an use the ``COPY FROM`` command to load data without staging it first. + +.. note:: The bucket must be publicly available and objects can be listed. + +The following is an example of bulk loading a file from a public S3 bucket: + +.. code-block:: postgres + + COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + +For more information on the ``COPY FROM`` command, see :ref:`copy_from`. + +Loading Files from an Authenticated S3 Bucket +--------------------------------------------------- +The following is an example of loading fles from an authenticated S3 bucket: + +.. code-block:: postgres + + COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' + AWS_ID '12345678' + AWS_SECRET 'super_secretive_secret'; \ No newline at end of file From 491cbfbe35c659fd7e84b7efcd7369300f90f14a Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 8 Nov 2022 15:24:32 +0200 Subject: [PATCH 0272/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index bd32a325f..0edb0a4d6 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -32,7 +32,7 @@ The following is the correct syntax for using the **COPY TO** statement: ) ; - fdw_name ::= csw_fdw | parquet_fdw | orc_fdw + fdw_name ::= csv_fdw | parquet_fdw | orc_fdw schema_name ::= identifer @@ -84,7 +84,7 @@ The following table shows the ``COPY_TO`` elements: * - ``query`` - An SQL query that returns a table result, or a table name * - ``fdw_name`` - - The name of the Foreign Data Wrapper to use. Supported FDWs are ``csv_fdw``, ``orc_fdw``, or ``parquet_fdw``. + - The name of the Foreign Data Wrapper to use. Supported FDWs are ``csv_fdw``, ``orc_fdw``, ``avro_fdw`` or ``parquet_fdw``. * - ``LOCATION`` - A path on the local filesystem, S3, or HDFS URI. For example, ``/tmp/foo.csv``, ``s3://my-bucket/foo.csv``, or ``hdfs://my-namenode:8020/foo.csv``. The local path must be an absolute path that SQream DB can access. * - ``HEADER`` @@ -545,4 +545,4 @@ The following is an example of exporting a table to an ORC file: Permissions ============= -The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. +The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. \ No newline at end of file From 950a058487677ae4b53a86ab6d1114de6fc62d72 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Wed, 16 Nov 2022 13:12:45 +0200 Subject: [PATCH 0273/1892] Added 2022.1.6 release notes --- releases/2022.1.6.rst | 116 ++++++++++++++++++++++++++++++++++++++ releases/2022.1_index.rst | 1 + 2 files changed, 117 insertions(+) create mode 100644 releases/2022.1.6.rst diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst new file mode 100644 index 000000000..be3e40b76 --- /dev/null +++ b/releases/2022.1.6.rst @@ -0,0 +1,116 @@ +.. _2022.1.5: + +************************** +Release Notes 2022.1.6 +************************** +The 2022.1.5 release notes were released on 11/02/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +---------- +The 2022.1.5 Release Notes include the following new features: + +* keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. + + :: + +* Automatically close database client connections that have been open for 24 hours without any active statements. + + :: + +* release_defunct_locks utility function enhancement to receive new optional input parameter to specify timeout - for more details see `Lock Related Issues <../troubleshooting/lock_related_issues.html>`_. + + + + +Known Issues +--------- +Recently discovered issue with the encryption feature, at this time SQream recommends to avoid using this feature - a fix will be introduced in the near future. + + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.5: + ++--------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+==========================================================================================+ +| SQ-11081 | Tableau connection are not getting closed | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11473 | SQream Command Line Interface connectivity issues | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11551 | SQream Studio Logs pages filtering issues | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11631 | Log related configuration flags are not working as expected | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11745 | Missing validation of sufficient GPU memory | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11792 | CUME_DIST function causes query execution errors | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-11905 | GetDate casting to as text returns DATE with 0s in the time part or no time part at all | ++--------------+------------------------------------------------------------------------------------------+ + + + + + +Operations and Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v2022.1.5 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index d6522a59b..1e2c0d256 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.6 2022.1.5 2022.1.4 2022.1.3 From 068ca0ebb206712b47d866a52fe31d2f5df1bbd5 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Wed, 16 Nov 2022 13:21:16 +0200 Subject: [PATCH 0274/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 9fd4bacf5..f32afe2dd 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The value may either be NULL or a literal. +The default value may be a literal, GETDATE(), or NULL. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. From 633adb18de6fa580a41d60ed2fbabe69335646d2 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Wed, 16 Nov 2022 13:56:02 +0200 Subject: [PATCH 0275/1892] Updates whole Client Drivers section --- .../client_drivers/cpp/connect_test.cpp | 34 ++ .../client_drivers/cpp/index.rst | 86 +++ .../client_drivers/cpp/insert_test.cpp | 39 ++ connecting_to_sqream/client_drivers/index.rst | 44 +- .../client_drivers/nodejs/index.rst | 382 ++++++++++++ .../client_drivers/nodejs/sample.js | 21 + .../client_drivers/python/index.rst | 568 ++++++++++++++++++ .../client_drivers/python/nba-t10.csv | 10 + .../client_drivers/python/test.py | 37 ++ 9 files changed, 1212 insertions(+), 9 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/cpp/connect_test.cpp create mode 100644 connecting_to_sqream/client_drivers/cpp/index.rst create mode 100644 connecting_to_sqream/client_drivers/cpp/insert_test.cpp create mode 100644 connecting_to_sqream/client_drivers/nodejs/index.rst create mode 100644 connecting_to_sqream/client_drivers/nodejs/sample.js create mode 100644 connecting_to_sqream/client_drivers/python/index.rst create mode 100644 connecting_to_sqream/client_drivers/python/nba-t10.csv create mode 100644 connecting_to_sqream/client_drivers/python/test.py diff --git a/connecting_to_sqream/client_drivers/cpp/connect_test.cpp b/connecting_to_sqream/client_drivers/cpp/connect_test.cpp new file mode 100644 index 000000000..82365af4e --- /dev/null +++ b/connecting_to_sqream/client_drivers/cpp/connect_test.cpp @@ -0,0 +1,34 @@ +// Trivial example + +#include + +#include "sqream.h" + +int main () { + + sqream::driver sqc; + + // Connection parameters: Hostname, Port, Use SSL, Username, Password, + // Database name, Service name + sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", + "raviga", "sqream"); + + // create table with data + run_direct_query(&sqc, "CREATE TABLE test_table (x int)"); + run_direct_query(&sqc, "INSERT INTO test_table VALUES (5), (6), (7), (8)"); + + // query it + sqc.new_query("SELECT * FROM test_table"); + sqc.execute_query(); + + // See the results + while (sqc.next_query_row()) { + std::cout << "Received: " << sqc.get_int(0) << std::endl; + } + + sqc.finish_query(); + + // Close the connection completely + sqc.disconnect(); + +} diff --git a/connecting_to_sqream/client_drivers/cpp/index.rst b/connecting_to_sqream/client_drivers/cpp/index.rst new file mode 100644 index 000000000..7cbabd1ef --- /dev/null +++ b/connecting_to_sqream/client_drivers/cpp/index.rst @@ -0,0 +1,86 @@ +.. _cpp_native: + +************************* +C++ Driver +************************* + +The SQream DB C++ driver allows C++ programs and tools to connect to SQream DB. + +This tutorial shows how to write a C++ program that uses this driver. + +.. contents:: In this topic: + :depth: 2 + :local: + + +Installing the C++ Driver +================================== + +Prerequisites +---------------- + +The SQream DB C++ driver was built on 64-bit Linux, and is designed to work with RHEL 7 and Ubuntu 16.04 and newer. + +Getting the Library +--------------------- + +The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. + + +Extract the Tarball Archive +----------------------------- + +Extract the library files from the tarball + +.. code-block:: console + + $ tar xf libsqream-3.0.tar.gz + +Examples +============================================== + +Assuming there is a SQream DB worker to connect to, we'll connect to it using the application and run some statements. + +Testing the Connection to SQream +-------------------------------------------- + +Download this file by right clicking and saving to your computer :download:`connect_test.cpp `. + +.. literalinclude:: connect_test.cpp + :language: cpp + :caption: Connect to SQream DB + :linenos: + + +Compiling and Running the Application +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To build this code, place the library and header file in ./libsqream-3.0/ and run + +.. code-block:: console + + $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream connect_test.cpp -o connect_test + $ ./connect_test + +Modify the ``-I`` and ``-L`` arguments to match the ``.so`` library and ``.h`` file if they are in another directory. + +Creating a Table and Inserting Values +-------------------------------------------- + +Download this file by right clicking and saving to your computer :download:`insert_test.cpp `. + +.. literalinclude:: insert_test.cpp + :language: cpp + :caption: Inserting data to a SQream DB table + :linenos: + + +Compiling and Running the Application +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +To build this code, use + +.. code-block:: console + + $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream insert_test.cpp -o insert_test + $ ./insert_test \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/cpp/insert_test.cpp b/connecting_to_sqream/client_drivers/cpp/insert_test.cpp new file mode 100644 index 000000000..d395be31a --- /dev/null +++ b/connecting_to_sqream/client_drivers/cpp/insert_test.cpp @@ -0,0 +1,39 @@ +// Insert with parameterized statement example + +#include + +#include "sqream.h" + +int main () { + + sqream::driver sqc; + + // Connection parameters: Hostname, Port, Use SSL, Username, Password, + // Database name, Service name + sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", + "raviga", "sqream"); + + run_direct_query(&sqc, + "CREATE TABLE animals (id INT NOT NULL, name VARCHAR(10) NOT NULL)"); + + // prepare the statement + sqc.new_query("INSERT INTO animals VALUES (?, ?)"); + sqc.execute_query(); + + // Data to insert + int row0[] = {1,2,3}; + std::string row1[] = {"Dog","Cat","Possum"}; + int len = sizeof(row0)/sizeof(row0[0]); + + for (int i = 0; i < len; ++i) { + sqc.set_int(0, row0[i]); + sqc.set_varchar(1, row1[i]); + sqc.next_query_row(); + } + + // This commits the insert + sqc.finish_query(); + + sqc.disconnect(); + +} diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 5365380b9..f7ae2710d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -1,7 +1,7 @@ .. _client_drivers: ************************************ -Client Drivers for 2022.1 +Client Drivers for 2022.1.6 ************************************ The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. @@ -17,15 +17,32 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file `_ - sqream-jdbc-4.5.4 (.jar) - * `JDBC driver `_ + * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC driver `_ + + +.. _python: + +* **Python** - Recommended installation via ``pip``: + + * `Python .tar file `_ - pysqream v3.1.3 (.tar.gz) + * `Python driver `_ + + +.. _nodejs: + +* **Node.JS** - Recommended installation via ``npm``: + + * `Node.JS `_ - sqream-v4.2.4 (.tar.gz) + * `Node.JS driver `_ + .. _tableau_connector: * **Tableau**: * `Tableau connector `_ - SQream (.taco) - * `Tableau manual installation `_ + * `Tableau manual installation `_ .. _powerbi_connector: @@ -33,17 +50,18 @@ The following are applicable to all operating systems: * **Power BI**: * `Power BI PowerQuery connector `_ - SQream (.mez) - * `Power BI manual installation `_ + * `Power BI manual installation `_ Windows -------------- The following are applicable to Windows: -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customization. Please contact your `SQream representative `_ for this installer. +* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `Sqream represenative `_ for this installer. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows `. + * **Net driver** - `SQream .Net driver v3.0.2 `_ @@ -53,17 +71,22 @@ Linux The following are applicable to Linux: * `SQream SQL (x86_64) `_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for Intel-based machines :: * `SQream SQL*(IBM POWER9) `_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines +* `Sqream SQL CLI Reference `_ - Interactive command-line SQL client for IBM POWER9-based machines :: * ODBC Installer - Please contact your SQream representative for this installer. + :: + +* C++ connector - `libsqream-4.0 `_ +* `C++ shared object library `_ + .. toctree:: :maxdepth: 4 @@ -71,7 +94,10 @@ The following are applicable to Linux: :titlesonly: jdbc/index + python/index + nodejs/index odbc/index + cpp/index @@ -81,4 +107,4 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older drivers? -If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. +If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/nodejs/index.rst b/connecting_to_sqream/client_drivers/nodejs/index.rst new file mode 100644 index 000000000..8ddd0d0bc --- /dev/null +++ b/connecting_to_sqream/client_drivers/nodejs/index.rst @@ -0,0 +1,382 @@ +.. _nodejs: + +************************* +Node.JS +************************* + +The SQream DB Node.JS driver allows Javascript applications and tools connect to SQream DB. +This tutorial shows you how to write a Node application using the Node.JS interface. + +The driver requires Node 10 or newer. + +.. contents:: In this topic: + :local: + +Installing the Node.JS driver +================================== + +Prerequisites +---------------- + +* Node.JS 10 or newer. Follow instructions at `nodejs.org `_ . + +Install with NPM +------------------- + +Installing with npm is the easiest and most reliable method. +If you need to install the driver in an offline system, see the offline method below. + +.. code-block:: console + + $ npm install @sqream/sqreamdb + +Install from an offline package +------------------------------------- + +The Node driver is provided as a tarball for download from the `SQream Drivers page `_ . + +After downloading the tarball, use ``npm`` to install the offline package. + +.. code-block:: console + + $ sudo npm install sqreamdb-4.0.0.tgz + + +Connect to SQream DB with a Node.JS application +==================================================== + +Create a simple test +------------------------------------------ + +Replace the connection parameters with real parameters for a SQream DB installation. + +.. code-block:: javascript + :caption: sqreamdb-test.js + + const Connection = require('@sqream/sqreamdb'); + + const config = { + host: 'localhost', + port: 3109, + username: 'rhendricks', + password: 'super_secret_password', + connectDatabase: 'raviga', + cluster: true, + is_ssl: true, + service: 'sqream' + }; + + const query1 = 'SELECT 1 AS test, 2*6 AS "dozen"'; + + const sqream = new Connection(config); + sqream.execute(query1).then((data) => { + console.log(data); + }, (err) => { + console.error(err); + }); + + +Run the test +---------------- + +A successful run should look like this: + +.. code-block:: console + + $ node sqreamdb-test.js + [ { test: 1, dozen: 12 } ] + + +API reference +==================== + +Connection parameters +--------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - Optional + - Default + - Description + * - ``host`` + - ✗ + - None + - Hostname for SQream DB worker. For example, ``127.0.0.1``, ``sqream.mynetwork.co`` + * - ``port`` + - ✗ + - None + - Port for SQream DB end-point. For example, ``3108`` for the load balancer, ``5000`` for a worker. + * - ``username`` + - ✗ + - None + - Username of a role to use for connection. For example, ``rhendricks`` + * - ``password`` + - ✗ + - None + - Specifies the password of the selected role. For example, ``Tr0ub4dor&3`` + * - ``connectDatabase`` + - ✗ + - None + - Database name to connect to. For example, ``master`` + * - ``service`` + - ✓ + - ``sqream`` + - Specifices service queue to use. For example, ``etl`` + * - ``is_ssl`` + - ✓ + - ``false`` + - Specifies SSL for this connection. For example, ``true`` + * - ``cluster`` + - ✓ + - ``false`` + - Connect via load balancer (use only if exists, and check port). For example, ``true`` + +Events +------------- + +The connector handles event returns with an event emitter + +getConnectionId + The ``getConnectionId`` event returns the executing connection ID. + +getStatementId + The ``getStatementId`` event returns the executing statement ID. + +getTypes + The ``getTypes`` event returns the results columns types. + +Example +^^^^^^^^^^^^^^^^^ + +.. code-block:: javascript + + const myConnection = new Connection(config); + + myConnection.runQuery(query1, function (err, data){ + myConnection.events.on('getConnectionId', function(data){ + console.log('getConnectionId', data); + }); + + myConnection.events.on('getStatementId', function(data){ + console.log('getStatementId', data); + }); + + myConnection.events.on('getTypes', function(data){ + console.log('getTypes', data); + }); + }); + +Input placeholders +------------------------- + +The Node.JS driver can replace parameters in a statement. + +Input placeholders allow values like user input to be passed as parameters into queries, with proper escaping. + +The valid placeholder formats are provided in the table below. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Placeholder + - Type + * - ``%i`` + - Identifier (e.g. table name, column name) + * - ``%s`` + - A text string + * - ``%d`` + - A number value + * - ``%b`` + - A boolean value + +See the :ref:`input placeholders example` below. + +Examples +=============== + +Setting configuration flags +----------------------------------- + +SQream DB configuration flags can be set per statement, as a parameter to ``runQuery``. + +For example: + +.. code-block:: javascript + + const setFlag = 'SET showfullexceptioninfo = true;'; + + const query_string = 'SELECT 1'; + + const myConnection = new Connection(config); + myConnection.runQuery(query_string, function (err, data){ + console.log(err, data); + }, setFlag); + + +Lazyloading +----------------------------------- + +To process rows without keeping them in memory, you can lazyload the rows with an async: + +.. code-block:: javascript + + + const Connection = require('@sqream/sqreamdb'); + + const config = { + host: 'localhost', + port: 3109, + username: 'rhendricks', + password: 'super_secret_password', + connectDatabase: 'raviga', + cluster: true, + is_ssl: true, + service: 'sqream' + }; + + const sqream = new Connection(config); + + const query = "SELECT * FROM public.a_very_large_table"; + + (async () => { + const cursor = await sqream.executeCursor(query); + let count = 0; + for await (let rows of cursor.fetchIterator(100)) { + // fetch rows in chunks of 100 + count += rows.length; + } + await cursor.close(); + return count; + })().then((total) => { + console.log('Total rows', total); + }, (err) => { + console.error(err); + }); + + +Reusing a connection +----------------------------------- + +It is possible to execeute multiple queries with the same connection (although only one query can be executed at a time). + +.. code-block:: javascript + + const Connection = require('@sqream/sqreamdb'); + + const config = { + host: 'localhost', + port: 3109, + username: 'rhendricks', + password: 'super_secret_password', + connectDatabase: 'raviga', + cluster: true, + is_ssl: true, + service: 'sqream' + }; + + const sqream = new Connection(config); + + (async () => { + + const conn = await sqream.connect(); + try { + const res1 = await conn.execute("SELECT 1"); + const res2 = await conn.execute("SELECT 2"); + const res3 = await conn.execute("SELECT 3"); + conn.disconnect(); + return {res1, res2, res3}; + } catch (err) { + conn.disconnect(); + throw err; + } + + })().then((res) => { + console.log('Results', res) + }, (err) => { + console.error(err); + }); + + +.. _input_placeholders_example: + +Using placeholders in queries +----------------------------------- + +Input placeholders allow values like user input to be passed as parameters into queries, with proper escaping. + +.. code-block:: javascript + + const Connection = require('@sqream/sqreamdb'); + + const config = { + host: 'localhost', + port: 3109, + username: 'rhendricks', + password: 'super_secret_password', + connectDatabase: 'raviga', + cluster: true, + is_ssl: true, + service: 'sqream' + }; + + const sqream = new Connection(config); + + const sql = "SELECT %i FROM public.%i WHERE name = %s AND num > %d AND active = %b"; + + sqream.execute(sql, "col1", "table2", "john's", 50, true); + + +The query that will run is ``SELECT col1 FROM public.table2 WHERE name = 'john''s' AND num > 50 AND active = true`` + + +Troubleshooting and recommended configuration +================================================ + + +Preventing ``heap out of memory`` errors +-------------------------------------------- + +Some workloads may cause Node.JS to fail with the error: + +.. code-block:: none + + FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory + +To prevent this error, modify the heap size configuration by setting the ``--max-old-space-size`` run flag. + +For example, set the space size to 2GB: + +.. code-block:: console + + $ node --max-old-space-size=2048 my-application.js + +BIGINT support +------------------------ + +The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. + +The error that appears is: +.. code-block:: none + + TypeError: Do not know how to serialize a BigInt + +This is because JSON specification do not support BIGINT values, even when supported by Javascript engines. + +To resolve this issue, objects with BIGINT values should be converted to string before serializing, and converted back after deserializing. + +For example: + +.. code-block:: javascript + + const rows = [{test: 1n}] + const json = JSON.stringify(rows, , (key, value) => + typeof value === 'bigint' + ? value.toString() + : value // return everything else unchanged + )); + console.log(json); // [{"test": "1"}] + diff --git a/connecting_to_sqream/client_drivers/nodejs/sample.js b/connecting_to_sqream/client_drivers/nodejs/sample.js new file mode 100644 index 000000000..cf3e19099 --- /dev/null +++ b/connecting_to_sqream/client_drivers/nodejs/sample.js @@ -0,0 +1,21 @@ +const Connection = require('@sqream/sqreamdb'); + +const config = { + host: 'localhost', + port: 3109, + username: 'rhendricks', + password: 'super_secret_password', + connectDatabase: 'raviga', + cluster: true, + is_ssl: true, + service: 'sqream' + }; + +const query1 = 'SELECT 1 AS test, 2*6 AS "dozen"'; + +const sqream = new Connection(config); +sqream.execute(query1).then((data) => { + console.log(data); +}, (err) => { + console.error(err); +}); \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst new file mode 100644 index 000000000..e03df343d --- /dev/null +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -0,0 +1,568 @@ +.. _pysqream: + +************************* +Python (pysqream) +************************* +The **Python** connector page describes the following: + +.. contents:: + :local: + :depth: 1 + +Overview +============= +The SQream Python connector is a set of packages that allows Python programs to connect to SQream DB. + +* ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. + +* ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream`` + +The connector supports Python 3.6.5 and newer. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 `_. + +Installing the Python Connector +================================== + +Prerequisites +---------------- +Installing the Python connector includes the following prerequisites: + +.. contents:: + :local: + :depth: 1 + +Python +^^^^^^^^^^^^ + +The connector requires Python 3.6.5 or newer. To verify your version of Python: + +.. code-block:: console + + $ python --version + Python 3.7.3 + + +.. note:: If both Python 2.x and 3.x are installed, you can run ``python3`` and ``pip3`` instead of ``python`` and ``pip`` respectively for the rest of this guide + +.. warning:: If you're running on an older version, ``pip`` will fetch an older version of ``pysqream``, with version <3.0.0. This version is currently not supported. + +PIP +^^^^^^^^^^^^ +The Python connector is installed via ``pip``, the Python package manager and installer. + +We recommend upgrading to the latest version of ``pip`` before installing. To verify that you are on the latest version, run the following command: + +.. code-block:: console + + $ python -m pip install --upgrade pip + Collecting pip + Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) + |████████████████████████████████| 1.4MB 1.6MB/s + Installing collected packages: pip + Found existing installation: pip 19.1.1 + Uninstalling pip-19.1.1: + Successfully uninstalled pip-19.1.1 + Successfully installed pip-19.3.1 + +.. note:: + * On macOS, you may want to use virtualenv to install Python and the connector, to ensure compatibility with the built-in Python environment + * If you encounter an error including ``SSLError`` or ``WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.`` - please be sure to reinstall Python with SSL enabled, or use virtualenv or Anaconda. + +OpenSSL for Linux +^^^^^^^^^^^^^^^^^^^^^^^^^^ +Some distributions of Python do not include OpenSSL. The Python connector relies on OpenSSL for secure connections to SQream DB. + +* To install OpenSSL on RHEL/CentOS + + .. code-block:: console + + $ sudo yum install -y libffi-devel openssl-devel + +* To install OpenSSL on Ubuntu + + .. code-block:: console + + $ sudo apt-get install libssl-dev libffi-dev -y + +Installing via PIP +----------------- +The Python connector is available via `PyPi `_. + +Install the connector with ``pip``: + +.. code-block:: console + + $ pip install pysqream pysqream-sqlalchemy + +``pip`` will automatically install all necessary libraries and modules. + +Upgrading an Existing Installation +-------------------------------------- +The Python drivers are updated periodically. To upgrade an existing pysqream installation, use pip's ``-U`` flag: + +.. code-block:: console + + $ pip install pysqream pysqream-sqlalchemy -U + +Validating Your Installation +----------------------------- +This section describes how to validate your installation. + +**To validate your installation**: + +1. Create a file called ``test.py``, containing the following: + +.. literalinclude:: test.py + :language: python + :caption: pysqream Validation Script + :linenos: + +2. Verify that the parameters in the connection have been replaced with your respective SQream installation parameters. + + :: + +3. Run the test file to verify that you can connect to SQream: + + .. code-block:: console + + $ python test.py + Version: v2020.1 + + If the validation was successful, you can build an application using the SQream Python connector. If you receive a connection error, verify the following: + + * You have access to a running SQream database. + + :: + + * The connection parameters are correct. + +SQLAlchemy Examples +======================== +SQLAlchemy is an **Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. + +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Standard Connection Example +--------------------------------- +The following is a standard connection example: + +.. code-block:: python + + import sqlalchemy as sa + from sqlalchemy.engine.url import URL + + engine_url = URL('sqream' + , username='rhendricks' + , password='secret_passwor" + , host='localhost' + , port=5000 + , database='raviga' + , query={'use_ssl': False}) + + engine = sa.create_engine(engine_url) + + res = engine.execute('create table test (ints int)') + res = engine.execute('insert into test values (5), (6)') + res = engine.execute('select * from test') + +Pulling a Table into Pandas +--------------------------------- +The following example shows how to pull a table in Pandas. This examples uses the URL method to create the connection string: + +.. code-block:: python + + import sqlalchemy as sa + import pandas as pd + from sqlalchemy.engine.url import URL + + + engine_url = URL('sqream' + , username='rhendricks' + , password='secret_passwor" + , host='localhost' + , port=5000 + , database='raviga' + , query={'use_ssl': False}) + + engine = sa.create_engine(engine_url) + + table_df = pd.read_sql("select * from nba", con=engine) + +API Examples +=============== +This section includes the following examples: + +.. contents:: + :local: + :depth: 1 + +Describing Your Connection +--------------------------------------- +This example shows how to describe the connection. + +**Describing your connection**: + +1. Import the package and create a connection: + + .. code-block:: python + + # Import pysqream package + + import pysqream + + """ + Connection parameters include: + * IP/Hostname + * Port + * database name + * username + * password + * Connect through load balancer, or direct to worker (Default: false - direct to worker) + * use SSL connection (default: false) + * Optional service queue (default: 'sqream') + """ + + # Create a connection object + + con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga' + , username='rhendricks', password='Tr0ub4dor&3' + , clustered=True) + +2. Run a query and fetch the results: + + .. code-block:: python + + cur = con.cursor() # Create a new cursor + # Prepare and execute a query + cur.execute('select show_version()') + + result = cur.fetchall() # `fetchall` gets the entire data set + + print (f"Version: {result[0][0]}") + + The SQream version should be output, such as ``v2020.1``. + +3. Close the connection: + + .. code-block:: python + + con.close() + +Using the Cursor +-------------------------------------------- +The DB-API specification includes several methods for fetching results from the cursor. This sections shows an example using the ``nba`` table, which looks as follows: + +.. csv-table:: nba + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +As before, you must import the library and create a :py:meth:`~Connection`, followed by :py:meth:`~Connection.execute` on a simple ``SELECT *`` query: + +.. code-block:: python + + import pysqream + con = pysqream.connect(host='127.0.0.1', port=3108, database='master' + , username='rhendricks', password='Tr0ub4dor&3' + , clustered=True) + + cur = con.cursor() # Create a new cursor + # The select statement: + statement = 'SELECT * FROM nba' + cur.execute(statement) + +When the statement has finished executing, you have a :py:meth:`Connection` cursor object waiting. A cursor is iterable, meaning that it advances the cursor to the next row when fetched. + +You can use :py:meth:`~Connection.fetchone` to fetch one record at a time: + +.. code-block:: python + + first_row = cur.fetchone() # Fetch one row at a time (first row) + + second_row = cur.fetchone() # Fetch one row at a time (second row) + +To fetch several rows at a time, use :py:meth:`~Connection.fetchmany`: + +.. code-block:: python + + # executing `fetchone` twice is equivalent to this form: + third_and_fourth_rows = cur.fetchmany(2) + +To fetch all rows at once, use :py:meth:`~Connection.fetchall`: + +.. code-block:: python + + # To get all rows at once, use `fetchall` + remaining_rows = cur.fetchall() + + # Close the connection when done + con.close() + +The following is an example of the contents of the row variables used in our examples: + +.. code-block:: pycon + + >>> print(first_row) + ('Avery Bradley', 'Boston Celtics', 0, 'PG', 25, '6-2', 180, 'Texas', 7730337) + >>> print(second_row) + ('Jae Crowder', 'Boston Celtics', 99, 'SF', 25, '6-6', 235, 'Marquette', 6796117) + >>> print(third_and_fourth_rows) + [('John Holland', 'Boston Celtics', 30, 'SG', 27, '6-5', 205, 'Boston University', None), ('R.J. Hunter', 'Boston Celtics', 28, 'SG', 22, '6-5', 185, 'Georgia State', 1148640)] + >>> print(remaining_rows) + [('Jonas Jerebko', 'Boston Celtics', 8, 'PF', 29, '6-10', 231, None, 5000000), ('Amir Johnson', 'Boston Celtics', 90, 'PF', 29, '6-9', 240, None, 12000000), ('Jordan Mickey', 'Boston Celtics', 55, 'PF', 21, '6-8', 235, 'LSU', 1170960), ('Kelly Olynyk', 'Boston Celtics', 41, 'C', 25, '7-0', 238, 'Gonzaga', 2165160), + [...] + +.. note:: Calling a fetch command after all rows have been fetched will return an empty array (``[]``). + +Reading Result Metadata +---------------------------- +When you execute a statement, the connection object also contains metadata about the result set, such as **column names**, **types**, etc). + +The metadata is stored in the :py:attr:`Connection.description` object of the cursor: + +.. code-block:: pycon + + >>> import pysqream + >>> con = pysqream.connect(host='127.0.0.1', port=3108, database='master' + ... , username='rhendricks', password='Tr0ub4dor&3' + ... , clustered=True) + >>> cur = con.cursor() + >>> statement = 'SELECT * FROM nba' + >>> cur.execute(statement) + + >>> print(cur.description) + [('Name', 'STRING', 24, 24, None, None, True), ('Team', 'STRING', 22, 22, None, None, True), ('Number', 'NUMBER', 1, 1, None, None, True), ('Position', 'STRING', 2, 2, None, None, True), ('Age (as of 2018)', 'NUMBER', 1, 1, None, None, True), ('Height', 'STRING', 4, 4, None, None, True), ('Weight', 'NUMBER', 2, 2, None, None, True), ('College', 'STRING', 21, 21, None, None, True), ('Salary', 'NUMBER', 4, 4, None, None, True)] + +You can fetch a list of column names by iterating over the ``description`` list: + +.. code-block:: pycon + + >>> [ i[0] for i in cur.description ] + ['Name', 'Team', 'Number', 'Position', 'Age (as of 2018)', 'Height', 'Weight', 'College', 'Salary'] + +Loading Data into a Table +--------------------------- +This example shows how to load 10,000 rows of dummy data to an instance of SQream. + +**To load data 10,000 rows of dummy data to an instance of SQream:** + +1. Run the following: + + .. code-block:: python + + import pysqream + from datetime import date, datetime + from time import time + + con = pysqream.connect(host='127.0.0.1', port=3108, database='master' + , username='rhendricks', password='Tr0ub4dor&3' + , clustered=True) + +2. Create a table for loading: + + .. code-block:: python + + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' + con.execute(create) + +3. Load your data into table using the ``INSERT`` command. + + :: + +4. Create dummy data matching the table you created: + + .. code-block:: python + + data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "Marty McFly" , u"キウイは楽しい鳥です" , date(2019, 12, 17), datetime(1955, 11, 4, 1, 23, 0, 0)) + + row_count = 10**4 + +5. Get a new cursor: + + .. code-block:: python + + cur = con.cursor() + insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)' + start = time() + cur.executemany(insert, [data] * row_count) + print (f"Total insert time for {row_count} rows: {time() - start} seconds") + +6. Close this cursor: + + .. code-block:: python + + cur.close() + +7. Verify that the data was inserted correctly. + + :: + +8. Get a new cursor: + + .. code-block:: python + + cur = con.cursor() + cur.execute('select count(*) from perf') + result = cur.fetchall() # `fetchall` collects the entire data set + print (f"Count of inserted rows: {result[0][0]}") + +9. Close the cursor: + + .. code-block:: python + + cur.close() + +10. Close the connection: + + .. code-block:: python + + con.close() + +Reading Data from a CSV File for Loading into a Table +---------------------------------------------------------- +This example shows how to write a helper function to create an :ref:`insert` statement, by reading an existing table's metadata. + +**To read data from a CSV file for loading into a table:** + +1. Run the following: + + .. code-block:: python + + import pysqream + import datetime + + def insert_from_csv(cur, table_name, csv_filename, field_delimiter = ',', null_markers = []): + """ +2. Ask SQream for some table information. + + This is important for determining the number of columns, and helps create a matching ``INSERT`` statement: + + .. code-block:: python + + """ + + column_info = cur.execute(f"SELECT * FROM {table_name} LIMIT 0").description + + + def parse_datetime(v): + try: + return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S.%f') + except ValueError: + try: + return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S') + except ValueError: + return datetime.datetime.strptime(row[i], '%Y-%m-%d') + +3. Create enough placeholders (`?`) for the ``INSERT`` query string: + + + .. code-block:: python + + qstring = ','.join(['?'] * len(column_info)) + insert_statement = f"insert into {table_name} values ({qstring})" + +4. Open the CSV file: + + .. code-block:: python + + with open(csv_filename, mode='r') as csv_file: + csv_reader = csv.reader(csv_file, delimiter=field_delimiter) + +5. Execute the ``INSERT`` statement with the CSV data: + + .. code-block:: python + + cur.executemany(insert_statement, [row for row in csv_reader]) + + + con = pysqream.connect(host='127.0.0.1', port=3108, database='master' + , username='rhendricks', password='Tr0ub4dor&3' + , clustered=True) + + cur = con.cursor() + insert_from_csv(cur, 'nba', 'nba.csv', field_delimiter = ',', null_markers = []) + + con.close() + +Using SQLAlchemy ORM to Create and Populate Tables +----------------------------------------------------------------------- +This section shows how to use the ORM to create and populate tables from Python objects. + +**To use SQLAlchemy ORM to create and populate tables:** + +1. Run the following: + + .. code-block:: python + + import sqlalchemy as sa + import pandas as pd + from sqlalchemy.engine.url import URL + + + engine_url = URL('sqream' + , username='rhendricks' + , password='secret_passwor" + , host='localhost' + , port=5000 + , database='raviga' + , query={'use_ssl': False}) + + engine = sa.create_engine(engine_url) + +2. Build a metadata object and bind it: + + .. code-block:: python + + metadata = sa.MetaData() + metadata.bind = engine + +3. Create a table in the local metadata: + + .. code-block:: python + + employees = sa.Table( + 'employees' + , metadata + , sa.Column('id', sa.Integer) + , sa.Column('name', sa.VARCHAR(32)) + , sa.Column('lastname', sa.VARCHAR(32)) + , sa.Column('salary', sa.Float) + ) + + The ``create_all()`` function uses the SQream engine object. + +4. Create all the defined table objects: + + .. code-block:: python + + metadata.create_all(engine) + +5. Populate your table. + + :: + +6. Build the data rows: + + .. code-block:: python + + insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks', 'salary': 12000.75} + ,{'id': 3, 'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0} + ,{'id': 8, 'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40} + ] + +7. Build the ``INSERT`` command: + + .. code-block:: python + + ins = employees.insert(insert_data) + +8. Execute the command: + + .. code-block:: python + + result = engine.execute(ins) + +For more information, see the :ref:`python_api_reference_guide`. \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/python/nba-t10.csv b/connecting_to_sqream/client_drivers/python/nba-t10.csv new file mode 100644 index 000000000..024530355 --- /dev/null +++ b/connecting_to_sqream/client_drivers/python/nba-t10.csv @@ -0,0 +1,10 @@ +Name,Team,Number,Position,Age,Height,Weight,College,Salary +Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 +Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 +John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, +R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 +Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 +Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 +Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 +Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 +Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 diff --git a/connecting_to_sqream/client_drivers/python/test.py b/connecting_to_sqream/client_drivers/python/test.py new file mode 100644 index 000000000..d7de6305a --- /dev/null +++ b/connecting_to_sqream/client_drivers/python/test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python + +import pysqream + +""" +Connection parameters include: +* IP/Hostname +* Port +* database name +* username +* password +* Connect through load balancer, or direct to worker (Default: false - direct to worker) +* use SSL connection (default: false) +* Optional service queue (default: 'sqream') +""" + +# Create a connection object + +con = pysqream.connect(host='127.0.0.1', port=5000, database='master' + , username='sqream', password='sqream' + , clustered=False) + +# Create a new cursor +cur = con.cursor() + +# Prepare and execute a query +cur.execute('select show_version()') + +result = cur.fetchall() # `fetchall` gets the entire data set + +print (f"Version: {result[0][0]}") + +# This should print the SQream DB version. For example ``Version: v2020.1``. + +# Finally, close the connection + +con.close() \ No newline at end of file From d17ce9fd22c666672b481ee2d716e44ae23cecb8 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Wed, 16 Nov 2022 14:44:48 +0200 Subject: [PATCH 0276/1892] Removed C++ from Client Driver documentation --- .../client_drivers/cpp/connect_test.cpp | 34 -------- .../client_drivers/cpp/index.rst | 86 ------------------- .../client_drivers/cpp/insert_test.cpp | 39 --------- connecting_to_sqream/client_drivers/index.rst | 5 -- 4 files changed, 164 deletions(-) delete mode 100644 connecting_to_sqream/client_drivers/cpp/connect_test.cpp delete mode 100644 connecting_to_sqream/client_drivers/cpp/index.rst delete mode 100644 connecting_to_sqream/client_drivers/cpp/insert_test.cpp diff --git a/connecting_to_sqream/client_drivers/cpp/connect_test.cpp b/connecting_to_sqream/client_drivers/cpp/connect_test.cpp deleted file mode 100644 index 82365af4e..000000000 --- a/connecting_to_sqream/client_drivers/cpp/connect_test.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Trivial example - -#include - -#include "sqream.h" - -int main () { - - sqream::driver sqc; - - // Connection parameters: Hostname, Port, Use SSL, Username, Password, - // Database name, Service name - sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", - "raviga", "sqream"); - - // create table with data - run_direct_query(&sqc, "CREATE TABLE test_table (x int)"); - run_direct_query(&sqc, "INSERT INTO test_table VALUES (5), (6), (7), (8)"); - - // query it - sqc.new_query("SELECT * FROM test_table"); - sqc.execute_query(); - - // See the results - while (sqc.next_query_row()) { - std::cout << "Received: " << sqc.get_int(0) << std::endl; - } - - sqc.finish_query(); - - // Close the connection completely - sqc.disconnect(); - -} diff --git a/connecting_to_sqream/client_drivers/cpp/index.rst b/connecting_to_sqream/client_drivers/cpp/index.rst deleted file mode 100644 index 7cbabd1ef..000000000 --- a/connecting_to_sqream/client_drivers/cpp/index.rst +++ /dev/null @@ -1,86 +0,0 @@ -.. _cpp_native: - -************************* -C++ Driver -************************* - -The SQream DB C++ driver allows C++ programs and tools to connect to SQream DB. - -This tutorial shows how to write a C++ program that uses this driver. - -.. contents:: In this topic: - :depth: 2 - :local: - - -Installing the C++ Driver -================================== - -Prerequisites ----------------- - -The SQream DB C++ driver was built on 64-bit Linux, and is designed to work with RHEL 7 and Ubuntu 16.04 and newer. - -Getting the Library ---------------------- - -The C++ driver is provided as a tarball containing the compiled ``libsqream.so`` file and a header ``sqream.h``. Get the driver from the `SQream Drivers page `_. The library can be integrated into your C++-based applications or projects. - - -Extract the Tarball Archive ------------------------------ - -Extract the library files from the tarball - -.. code-block:: console - - $ tar xf libsqream-3.0.tar.gz - -Examples -============================================== - -Assuming there is a SQream DB worker to connect to, we'll connect to it using the application and run some statements. - -Testing the Connection to SQream --------------------------------------------- - -Download this file by right clicking and saving to your computer :download:`connect_test.cpp `. - -.. literalinclude:: connect_test.cpp - :language: cpp - :caption: Connect to SQream DB - :linenos: - - -Compiling and Running the Application -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To build this code, place the library and header file in ./libsqream-3.0/ and run - -.. code-block:: console - - $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream connect_test.cpp -o connect_test - $ ./connect_test - -Modify the ``-I`` and ``-L`` arguments to match the ``.so`` library and ``.h`` file if they are in another directory. - -Creating a Table and Inserting Values --------------------------------------------- - -Download this file by right clicking and saving to your computer :download:`insert_test.cpp `. - -.. literalinclude:: insert_test.cpp - :language: cpp - :caption: Inserting data to a SQream DB table - :linenos: - - -Compiling and Running the Application -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -To build this code, use - -.. code-block:: console - - $ g++ -Wall -Ilibsqream-3.0 -Llibsqream-3.0 -lsqream insert_test.cpp -o insert_test - $ ./insert_test \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/cpp/insert_test.cpp b/connecting_to_sqream/client_drivers/cpp/insert_test.cpp deleted file mode 100644 index d395be31a..000000000 --- a/connecting_to_sqream/client_drivers/cpp/insert_test.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Insert with parameterized statement example - -#include - -#include "sqream.h" - -int main () { - - sqream::driver sqc; - - // Connection parameters: Hostname, Port, Use SSL, Username, Password, - // Database name, Service name - sqc.connect("127.0.0.1", 5000, false, "rhendricks", "Tr0ub4dor&3", - "raviga", "sqream"); - - run_direct_query(&sqc, - "CREATE TABLE animals (id INT NOT NULL, name VARCHAR(10) NOT NULL)"); - - // prepare the statement - sqc.new_query("INSERT INTO animals VALUES (?, ?)"); - sqc.execute_query(); - - // Data to insert - int row0[] = {1,2,3}; - std::string row1[] = {"Dog","Cat","Possum"}; - int len = sizeof(row0)/sizeof(row0[0]); - - for (int i = 0; i < len; ++i) { - sqc.set_int(0, row0[i]); - sqc.set_varchar(1, row1[i]); - sqc.next_query_row(); - } - - // This commits the insert - sqc.finish_query(); - - sqc.disconnect(); - -} diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index f7ae2710d..43141714d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -82,10 +82,6 @@ The following are applicable to Linux: * ODBC Installer - Please contact your SQream representative for this installer. - :: - -* C++ connector - `libsqream-4.0 `_ -* `C++ shared object library `_ .. toctree:: @@ -97,7 +93,6 @@ The following are applicable to Linux: python/index nodejs/index odbc/index - cpp/index From 3546cb57a7b3c10b26abf89dc9eccdedd23c4590 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Wed, 16 Nov 2022 15:02:03 +0200 Subject: [PATCH 0277/1892] Added .NET to Client Driver --- connecting_to_sqream/client_drivers/index.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 43141714d..780f5a324 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -20,6 +20,12 @@ The following are applicable to all operating systems: * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) * `JDBC driver `_ +.. _.net: + +* **.NET**: + + * `.NET integration + .. _python: From 03d3ab18e0f8938d5e93d3b38da2dcc436f3ba12 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 20 Nov 2022 15:08:34 +0200 Subject: [PATCH 0278/1892] Brand update --- .../SQream_logo_without background-15.png | Bin 0 -> 128962 bytes conf.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 _static/images/SQream_logo_without background-15.png diff --git a/_static/images/SQream_logo_without background-15.png b/_static/images/SQream_logo_without background-15.png new file mode 100644 index 0000000000000000000000000000000000000000..1a4460581981aa00ed03e21f2691a33389cc4c39 GIT binary patch literal 128962 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

HW& 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 lN(g=(&k+CDXNc#hZ%glfyYYjE_|dNxE7yH_ Date: Sun, 20 Nov 2022 16:23:40 +0200 Subject: [PATCH 0279/1892] Password policy --- .../client_drivers/dotnet/index.rst | 129 ++++++++++++++++++ connecting_to_sqream/client_drivers/index.rst | 1 + .../access_control_password_policy.rst | 6 +- releases/2022.1.6.rst | 48 +++---- 4 files changed, 155 insertions(+), 29 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/dotnet/index.rst diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst new file mode 100644 index 000000000..64e9ddeb4 --- /dev/null +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -0,0 +1,129 @@ +.. _net: + +************************* +.NET +************************* +The SqreamNet ADO.NET Data Provider allows you to connect to a SQream database server through .NET environments. This page describes how to establish such connection. + +The .NET page includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Integrating SQreamNet +================================== +The **Integrating SQreamNet** section describes the following: + +.. contents:: + :local: + :depth: 1 + +Prerequisites +---------------- +The SqreamNet provider requires a .NET Framework 6 or newer. + +Verifying the Correct .NET Framework Version is Installed +--------------------- +To verify the correct version of .NET Framework is installed, go to your Framework directory, under Microsoft.NET and look for a v6.x.x directory. In case an older version of .NET Framework exists, you may follow Microsoft guidelines: ____ + +Integrating SQreamNet +------------------------- +To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your Visual Studio, add a reference to the Sqreamnet.dll file to your project. +If you wish to upgrade SQreamNet within an existing project, you may replace the .dll file with an updated one or add a reference to the updated .dll file within its new location. + +Using SQreamNet in your Visual Studio project +---------------------------- + + +Connecting to SQream For the First Time +============================================== +An initial connection to SQream must be established by creating a **SqreamConnection** object by using a connection string. + +.. contents:: + :local: + :depth: 1 + +Connection string +-------------- +Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. + +Connection String +-------------------- +JSQreamNet Data Provider relies on a connection string. + +The following is the syntax for SQream: + +.. code-block:: text + + "Data Source=,;User=;Password=;Initial \ Catalog=master;Integrated Security=true"; + +Connection Parameters +^^^^^^^^^^^^^^^^^^^^^^^^ +The following table shows the connection string parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - State + - Default + - Description + * - ```` + - Mandatory + - None + - Hostname/IP/FQDN and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` + * - ```` + - Mandatory + - None + - Database name to connect to. For example, ``master`` + * - ``username=`` + - Mandatory + - None + - Username of a role to use for connection. For example, ``username=rhendricks`` + * - ``password=`` + - Mandatory + - None + - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` + * - ``service=`` + - Optional + - ``sqream`` + - Specifices service queue to use. For example, ``service=etl`` + * - ```` + - Optional + - ``false`` + - Specifies SSL for this connection. For example, ``ssl=true`` + * - ```` + - Optional + - ``true`` + - Connect via load balancer (use only if exists, and check port). + +Connection String Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following is an example of a SQream cluster with load balancer and no service queues (with SSL): + +.. code-block:: text + + jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true + +The following is a minimal example for a local standalone SQream database: + +.. code-block:: text + + jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 + +The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` + +.. code-block:: text + + jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl + +Sample Java Program +-------------------- +You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. + +.. literalinclude:: sample.java + :language: java + :caption: JDBC Application Sample + :linenos: diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 780f5a324..8339a0a28 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -99,6 +99,7 @@ The following are applicable to Linux: python/index nodejs/index odbc/index + .net/index diff --git a/operational_guides/access_control_password_policy.rst b/operational_guides/access_control_password_policy.rst index 055d674bb..6c69257ed 100644 --- a/operational_guides/access_control_password_policy.rst +++ b/operational_guides/access_control_password_policy.rst @@ -31,7 +31,7 @@ As part of our compliance with GDPR standards SQream relies on a strong password * Must include at least one special character, such as **?**, **!**, **$**, etc. -You can grant a password through the Studio graphic interface or through the CLI, as in the following example command: +You can create a password by using the Studio graphic interface or using the CLI, as in the following example command: .. code-block:: console @@ -39,7 +39,7 @@ You can grant a password through the Studio graphic interface or through the CLI GRANT LOGIN to user_a ; GRANT PASSWORD 'BBAu47?fqPL' to user_a ; -Granting a password that does not comply with the above requirements generates an error message with a request to modify it; +Creating a password which does not comply with the password policy generates an error message with a request to include any of the missing above requirements: .. code-block:: console @@ -59,7 +59,7 @@ Granting a password that does not comply with the above requirements generates a Brute Force Prevention ============================== -Unsuccessfully attempting to log in three times displays the following message: +Unsuccessfully attempting to log in five times displays the following message: .. code-block:: console diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index be3e40b76..158bc46a2 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -1,9 +1,9 @@ -.. _2022.1.5: +.. _2022.1.6: ************************** Release Notes 2022.1.6 ************************** -The 2022.1.5 release notes were released on 11/02/2022 and describe the following: +The 2022.1.6 release notes were released on 11/xx/2022 and describe the following: .. contents:: :local: @@ -11,7 +11,7 @@ The 2022.1.5 release notes were released on 11/02/2022 and describe the followin New Features ---------- -The 2022.1.5 Release Notes include the following new features: +The 2022.1.6 Release Notes include the following new features: * keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. @@ -28,36 +28,32 @@ The 2022.1.5 Release Notes include the following new features: Known Issues --------- -Recently discovered issue with the encryption feature, at this time SQream recommends to avoid using this feature - a fix will be introduced in the near future. +No known issues. -Resolved Issues +Version 2022.1.6 resolved Issues --------- -The following table lists the issues that were resolved in Version 2022.1.5: -+--------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+==============+==========================================================================================+ -| SQ-11081 | Tableau connection are not getting closed | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11473 | SQream Command Line Interface connectivity issues | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11551 | SQream Studio Logs pages filtering issues | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11631 | Log related configuration flags are not working as expected | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11745 | Missing validation of sufficient GPU memory | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11792 | CUME_DIST function causes query execution errors | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11905 | GetDate casting to as text returns DATE with 0s in the time part or no time part at all | -+--------------+------------------------------------------------------------------------------------------+ ++-------------------------------+---------------------------------------------------------+ +| **SQ No.** | **Description** | ++===============================+=========================================================+ +| SQ-10160 | Spotfire casting issues when reading SQream data | ++-------------------------------+---------------------------------------------------------+ +| SQ-11811, SQ-11772 | Queries containing JOIN TEXT columns slow runtime | ++-------------------------------+---------------------------------------------------------+ +| SQ-11940, SQ-11926, SQ-11874 | Version 2022.1.5 encryption issues | ++-------------------------------+---------------------------------------------------------+ +| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | ++-------------------------------+---------------------------------------------------------+ +| | | ++-------------------------------+---------------------------------------------------------+ +| | | ++-------------------------------+---------------------------------------------------------+ - -Operations and Configuration Changes +Configuration Changes -------- No configuration changes were made. @@ -78,7 +74,7 @@ End of Support ------- No End of Support changes were made. -Upgrading to v2022.1.5 +Upgrading to v2022.1.6 ------- 1. Generate a back-up of the metadata by running the following command: From 75bd5b065022fa00c53eb9df764a494673c51e77 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Sun, 20 Nov 2022 17:20:47 +0200 Subject: [PATCH 0280/1892] Documentation landing page --- .../client_drivers/dotnet/index.rst | 12 +- connecting_to_sqream/client_drivers/index.rst | 2 +- index.rst | 125 ++---------------- 3 files changed, 16 insertions(+), 123 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 64e9ddeb4..caa1952e5 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -50,7 +50,7 @@ Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. Connection String -------------------- -JSQreamNet Data Provider relies on a connection string. +SQreamNet Data Provider relies on a connection string. The following is the syntax for SQream: @@ -105,21 +105,23 @@ The following is an example of a SQream cluster with load balancer and no servic .. code-block:: text - jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=master;Integrated Security=true;ssl=true;cluster=true; + The following is a minimal example for a local standalone SQream database: .. code-block:: text - jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 + + Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=master; The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` .. code-block:: text - jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=raviga;Integrated Security=true;service=etl;cluster=true; -Sample Java Program +Sample C# Program -------------------- You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 8339a0a28..fa1155c01 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -99,7 +99,7 @@ The following are applicable to Linux: python/index nodejs/index odbc/index - .net/index + dotnet/index diff --git a/index.rst b/index.rst index 00c01f392..c3d41c39c 100644 --- a/index.rst +++ b/index.rst @@ -4,21 +4,9 @@ SQream DB Documentation ************************* -For SQream version 2021.2. - -.. only:: html - - .. tip:: - Want to read this offline? - `Download the documentation as a single PDF `_ . - -.. only:: pdf or latex - - .. tip:: This documentation is available online at https://docs.sqream.com/ SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL`, uses :ref:`serializable transactions`, and :ref:`scales horizontally` for concurrent statements. Even a :ref:`basic SQream DB machine` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau` comes with standard SQL client drivers, including :ref:`JDBC`, :ref:`ODBC`, and :ref:`Python DB-API`. -:ref:`client_platforms` +---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ | Topic | Description | @@ -61,111 +49,15 @@ SQream DB is a columnar analytic SQL database management system. SQream DB suppo +---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ - Loading and unloading data: - - * Loading data: - - * Overview of loading data - * Alternatives to loading data (foreign tables) - * Supported data types - * Ingesting data from external sources - * Inserting data from external tables - * Ingesting data from third party client platforms - * Using the **COPY FROM** statement - * Importing data using Studio - * Loading data using Amazon S3 - - * Unloading data: - - * Overview of unloading data - * Using the **COPY TO** statement - - Feature guides: - - * Query Healer - * Automatic schema Identification - * Compression - * Python UDF (User-Defined Functions) - * Workload Manager - * Transactions - * Concurrency and locks - * Concurrency and scaling in SQream DB - - Operational guides: - - * Access control - * Creating or cloning storage clusters - * Foreign tables - * Deleting data - * Exporting data - * Logging - * Monitoring query performance - * Security - * Saved queries - * Seeing system objects as DDL - * Optimization and best practices - - SQream Accelerated Studio 5.4.3: - - * Getting started with SQream Acceleration Studio 5.4.3 - * Monitoring workers and services from the dashboard - * Executing statements and running queries from the Editor - * Viewing logs - * Creating, assigning, and managing roles and permissions - * Configuring Your instance of SQream - - System architecture: - - * Internals and architecture - * Filesystem and usage - - Configuring SQream: - - * Configuration methods - * Configuration flags - - Reference guides: - - * SQL syntax, statements, and functions - * Catalog reference guide - * Command Line programs - * SQL feature checklist - * Python API reference guide - - Data type guides: - - * Converting and casting - * Supported data types - * Supported casts - - Release notes: - - * 2022.1 - * 2021.2 - * 2021.1 - * 2020.3 - * 2020.2 - * 2020.1 - - Troubleshooting: - - * Remedying slow queries - * Resolving common issues - * Examining logs - * Identifying configuration issues - * Lock related issues - * SAS Viya related issues - * Tableau related issues - * Solving “Code 126” ODBC errors - * Log related issues - * Node.js related issues - * Core dumping related issues - * SQream SQL installation related issues - * Gathering information for SQream support - - Glossary +.. only:: html + .. tip:: + Want to read this offline? + `Download the documentation as a single PDF `_ . +.. only:: pdf or latex + + .. tip:: This documentation is available online at https://docs.sqream.com/ .. rubric:: Need help? @@ -175,9 +67,8 @@ If you couldn't find what you're looking for, we're always happy to help. Visit .. rubric:: Looking for older versions? -This version of the documentation is for SQream DB Version 2021.2. -If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . +If you're looking for an older version of the documentation, go to http://previous.sqream.com . .. toctree:: :caption: Contents: From bb84ce82c7f49ed9649f4a6e51cf91010a9a33a7 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 11:13:05 +0200 Subject: [PATCH 0281/1892] .NET --- .../client_drivers/dotnet/index.rst | 29 +++--- .../client_drivers/dotnet/sample.cs | 93 +++++++++++++++++++ 2 files changed, 107 insertions(+), 15 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/dotnet/sample.cs diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index caa1952e5..5de839eae 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -3,7 +3,7 @@ ************************* .NET ************************* -The SqreamNet ADO.NET Data Provider allows you to connect to a SQream database server through .NET environments. This page describes how to establish such connection. +The SqreamNet ADO.NET Data Provider lets you connect to SQream through your .NET environment. The .NET page includes the following sections: @@ -25,32 +25,32 @@ The SqreamNet provider requires a .NET Framework 6 or newer. Verifying the Correct .NET Framework Version is Installed --------------------- -To verify the correct version of .NET Framework is installed, go to your Framework directory, under Microsoft.NET and look for a v6.x.x directory. In case an older version of .NET Framework exists, you may follow Microsoft guidelines: ____ +To verify the correct version of .NET Framework is installed, go to the Microsoft.NET directory, open the Framework directory, and verify that a v6.x.x directory exists. +In case an older version of .NET Framework exists, you may follow Microsoft guidelines for upgrading .NET Framework: ________________ Integrating SQreamNet ------------------------- -To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your Visual Studio, add a reference to the Sqreamnet.dll file to your project. -If you wish to upgrade SQreamNet within an existing project, you may replace the .dll file with an updated one or add a reference to the updated .dll file within its new location. +To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your Visual Studio, add a Sqreamnet.dll reference to your project. +If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. -Using SQreamNet in your Visual Studio project +Known Driver Limitations ---------------------------- +Unicode characters are not supported when using ``INSERT INTO AS SELECT``. +To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. Connecting to SQream For the First Time ============================================== -An initial connection to SQream must be established by creating a **SqreamConnection** object by using a connection string. +An initial connection to SQream must be established by creating a **SqreamConnection** object using a connection string. .. contents:: :local: :depth: 1 -Connection string --------------- -Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. Connection String -------------------- -SQreamNet Data Provider relies on a connection string. +The SQreamNet Data Provider relies on a connection string. The following is the syntax for SQream: @@ -60,7 +60,6 @@ The following is the syntax for SQream: Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ -The following table shows the connection string parameters: .. list-table:: :widths: auto @@ -123,9 +122,9 @@ The following is an example of a SQream cluster with load balancer and a specifi Sample C# Program -------------------- -You can download the :download:`JDBC Application Sample File ` below by right-clicking and saving it to your computer. +You can download the :download:`.NET Application Sample File ` below by right-clicking and saving it to your computer. -.. literalinclude:: sample.java - :language: java - :caption: JDBC Application Sample +.. literalinclude:: sample.cs + :language: C# + :caption: .NET Application Sample :linenos: diff --git a/connecting_to_sqream/client_drivers/dotnet/sample.cs b/connecting_to_sqream/client_drivers/dotnet/sample.cs new file mode 100644 index 000000000..54a19e0da --- /dev/null +++ b/connecting_to_sqream/client_drivers/dotnet/sample.cs @@ -0,0 +1,93 @@ + public void Test() + { + var connection = OpenConnection("192.168.4.62", 5000, "sqream", "sqream", "master"); + + ExecuteSQLCommand(connection, "create or replace table tbl_example as select 1 as x , 'a' as y;"); + + var tableData = ReadExampleData(connection, "select * from tbl_example;"); + } + + ///

+ /// Builds a connection string to sqream server and opens a connection + /// + /// host to connect + /// port sqreamd is running on + /// role username + /// role password + /// database name + /// optional - set to true when the ip,port endpoint is a server picker process + /// + /// SQream connection object + /// Throws SqreamException if fails to open a connction + /// + public SqreamConnection OpenConnection(string ipAddress, int port, string username, string password, string databaseName, bool isCluster = false) + { + // create the connection string according to the format + var connectionString = string.Format( + "Data Source={0},{1};User={2};Password={3};Initial Catalog={4};Cluster={5}", + ipAddress, + port, + username, + password, + databaseName, + isCluster + ); + + // create a sqeram connection object + var connection = new SqreamConnection(connectionString); + + // open a connection + connection.Open(); + + // returns the connection object + return connection; + } + + /// + /// Executes a SQL command to sqream server + /// + /// connection to sqream server + /// sql command + /// thrown when the connection is not open + public void ExecuteSQLCommand(SqreamConnection connection, string sql) + { + // validates the connection is open and throws exception if not + if (connection.State != System.Data.ConnectionState.Open) + throw new InvalidOperationException(string.Format("connection to sqream is not open. connection.State: {0}", connection.State)); + + // creates a new command object utilizing the sql and the connection + var command = new SqreamCommand(sql, connection); + + // executes the command + command.ExecuteNonQuery(); + } + + /// + /// Executes a SQL command to sqream server, and reads the result set usiing DataReader + /// + /// connection to sqream server + /// sql command + /// thrown when the connection is not open + public List> ReadExampleData(SqreamConnection connection, string sql) + { + // validates the connection is open and throws exception if not + if (connection.State != System.Data.ConnectionState.Open) + throw new InvalidOperationException(string.Format("connection to sqream is not open. connection.State: {0}", connection.State)); + + // creates a new command object utilizing the sql and the connection + var command = new SqreamCommand(sql, connection); + + // creates a reader object to iterate over the result set + var reader = (SqreamDataReader)command.ExecuteReader(); + + // list of results + var result = new List>(); + + //iterate the reader and read the table int,string values into a result tuple object + while (reader.Read()) + result.Add(new Tuple(reader.GetInt32(0), reader.GetString(1))); + + // return the result set + return result; + } + From f5fc472e31d4cee4ed9ab5d42e458e49fc213a4b Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 12:01:48 +0200 Subject: [PATCH 0282/1892] Update filesystem_and_filesystem_usage.rst --- architecture/filesystem_and_filesystem_usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst index d1838d4e8..c4e2e1d80 100644 --- a/architecture/filesystem_and_filesystem_usage.rst +++ b/architecture/filesystem_and_filesystem_usage.rst @@ -27,7 +27,7 @@ The **cluster root** is the directory in which all data for SQream DB is stored. The databases directory houses all of the actual data in tables and columns. -Each database is stored as it's own directory. Each table is stored under it's respective database, and columns are stored in their respective table. +Each database is stored as its own directory. Each table is stored under it's respective database, and columns are stored in their respective table. .. figure:: /_static/images/table_columns_storage.png From 751fa2c8b2516f3dd78dd4483afb7b0c73e65314 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 13:24:50 +0200 Subject: [PATCH 0283/1892] Update index.rst --- .../client_drivers/dotnet/index.rst | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 5de839eae..0800f3738 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -21,23 +21,19 @@ The **Integrating SQreamNet** section describes the following: Prerequisites ---------------- -The SqreamNet provider requires a .NET Framework 6 or newer. - -Verifying the Correct .NET Framework Version is Installed ---------------------- -To verify the correct version of .NET Framework is installed, go to the Microsoft.NET directory, open the Framework directory, and verify that a v6.x.x directory exists. -In case an older version of .NET Framework exists, you may follow Microsoft guidelines for upgrading .NET Framework: ________________ +The SqreamNet provider requires a .NET version 6 or newer. Integrating SQreamNet ------------------------- -To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your Visual Studio, add a Sqreamnet.dll reference to your project. +To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. + Known Driver Limitations ---------------------------- -Unicode characters are not supported when using ``INSERT INTO AS SELECT``. + * Unicode characters are not supported when using ``INSERT INTO AS SELECT``. -To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. + * To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. Connecting to SQream For the First Time ============================================== @@ -50,13 +46,13 @@ An initial connection to SQream must be established by creating a **SqreamConnec Connection String -------------------- -The SQreamNet Data Provider relies on a connection string. +To connect to SQream, instantiate a **SqreamConnection** object using this connection string. The following is the syntax for SQream: .. code-block:: text - "Data Source=,;User=;Password=;Initial \ Catalog=master;Integrated Security=true"; + "Data Source=,;User=;Password=;Initial Catalog=;Integrated Security=true"; Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -77,15 +73,15 @@ Connection Parameters - Mandatory - None - Database name to connect to. For example, ``master`` - * - ``username=`` + * - ```` - Mandatory - None - Username of a role to use for connection. For example, ``username=rhendricks`` - * - ``password=`` + * - ```` - Mandatory - None - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` - * - ``service=`` + * - ```` - Optional - ``sqream`` - Specifices service queue to use. For example, ``service=etl`` @@ -104,21 +100,21 @@ The following is an example of a SQream cluster with load balancer and no servic .. code-block:: text - Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=master;Integrated Security=true;ssl=true;cluster=true; - + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master;Integrated Security=true;ssl=true;cluster=true; + The following is a minimal example for a local standalone SQream database: .. code-block:: text - Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=master; + Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master; The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` .. code-block:: text - Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial \ Catalog=raviga;Integrated Security=true;service=etl;cluster=true; + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=raviga;Integrated Security=true;service=etl;cluster=true; Sample C# Program -------------------- From 51bcd4d98baa47be95349b0d0e10e19a23448c1c Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 13:33:47 +0200 Subject: [PATCH 0284/1892] .NET --- connecting_to_sqream/client_drivers/dotnet/index.rst | 2 +- connecting_to_sqream/client_drivers/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 0800f3738..1236f1932 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -25,7 +25,7 @@ The SqreamNet provider requires a .NET version 6 or newer. Integrating SQreamNet ------------------------- -To integrate SQreamNet, unzip the archive file and save to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. +To integrate SQreamNet,save the archive file to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index fa1155c01..76a6560c7 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ The following are applicable to all operating systems: * **.NET**: - * `.NET integration + * `.NET driver `_ .. _python: From 0d9aa3c89b2ffddcb560030aa79da4e41de4a895 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 13:49:10 +0200 Subject: [PATCH 0285/1892] Update index.rst --- connecting_to_sqream/client_drivers/dotnet/index.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 1236f1932..1d28069a7 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -23,9 +23,14 @@ Prerequisites ---------------- The SqreamNet provider requires a .NET version 6 or newer. +Getting the DLL file +---------------- +The .NET driver is available for download from the :ref:`client drivers download page`. + Integrating SQreamNet ------------------------- -To integrate SQreamNet,save the archive file to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. +After downloading the .NET driver, save the archive file to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. + If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. From 97815cf03be488f0b6372b723bcebdcbfe3c9628 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 22 Nov 2022 14:07:14 +0200 Subject: [PATCH 0286/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 76a6560c7..957fa3505 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,8 @@ The following are applicable to all operating systems: * **.NET**: - * `.NET driver `_ + * `.NET .dll file `_ + * `.NET driver `_ .. _python: From 940b55ae76791a2dfd003dd49ee6efc35fe42d24 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 24 Nov 2022 11:18:44 +0200 Subject: [PATCH 0287/1892] Saved queries --- operational_guides/saved_queries.rst | 130 ++++++++++++++++++ reference/sql/sql_statements/index.rst | 10 ++ .../utility_commands/drop_saved_query.rst | 2 +- .../recompile_saved_query.rst | 2 + 4 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 operational_guides/saved_queries.rst diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst new file mode 100644 index 000000000..2ec42f247 --- /dev/null +++ b/operational_guides/saved_queries.rst @@ -0,0 +1,130 @@ +.. _saved_queries: + +*********************** +Saved Queries +*********************** + + + +Using the ``save_query`` command will both generate and save an execution plan. This allows you to save time when running frequently used complex queries. + +Note that the saved execution plan is tightly coupled with the structure of its underlying tables, which means that if one or more of the objects mentioned in the query is modified, the saved query must be re-created. + + +How saved queries work +========================== + +Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. + +Parameters support +=========================== + +Query parameters can be used as substitutes for constants expressions in queries. + +* Parameters cannot be used to substitute identifiers like column names and table names. + +* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) + +Creating a saved query +====================== + +A saved query is created using the :ref:`save_query` utility command. + +Saving a simple query +--------------------------- + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); + executed + +Saving a parametrized query +------------------------------------------ + +Use parameters to replace them later at execution time. + + + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); + executed + +.. TODO tip Use dollar quoting (`$$`) to avoid escaping strings. +.. this makes no sense unless you have a query which would otherwise need escaping +.. t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); +.. executed + + +Executing saved queries +======================= + +Executing a saved query requires calling it by it's name in a :ref:`execute_saved_query` statement. A saved query with no parameter is called without parameters. + +.. code-block:: psql + + t=> SELECT EXECUTE_SAVED_QUERY('select_all'); + Name | Team | Number | Position | Age | Height | Weight | College | Salary + -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + [...] + +Executing a saved query with parameters requires specifying the parameters in the order they appear in the query: + +.. code-block:: psql + + t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + Name | Team | Number | Position | Age | Height | Weight | College | Salary + ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- + Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 + James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 + Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 + +Listing saved queries +======================= + +Saved queries are saved as a database objects. They can be listed in one of two ways: + +Using the :ref:`catalog`: + +.. code-block:: psql + + t=> SELECT * FROM sqream_catalog.savedqueries; + name | num_parameters + --------------------------+--------------- + select_all | 0 + select_by_weight | 1 + select_by_weight_and_team | 2 + +Using the :ref:`list_saved_queries` utility function: + +.. code-block:: psql + + t=> SELECT LIST_SAVED_QUERIES(); + saved_query + ------------------------- + select_all + select_by_weight + select_by_weight_and_team + + +Dropping a saved query +============================= + +When you're done with a saved query, or would like to replace it with another, you can drop it with :ref:`drop_saved_query`: + +.. code-block:: psql + + t=> SELECT DROP_SAVED_QUERY('select_all'); + executed + t=> SELECT DROP_SAVED_QUERY('select_by_weight_and_team'); + executed + + t=> SELECT LIST_SAVED_QUERIES(); + saved_query + ------------------------- + select_by_weight \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 960200937..af6e9f06a 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -106,8 +106,16 @@ The following table shows the Utility commands: * - Command - Usage + * - :ref:`DROP SAVED QUERY` + - Drops a saved query + * - :ref:`EXECUTE SAVED QUERY` + - Executes a previously saved query * - :ref:`EXPLAIN` - Returns a static query plan, which can be used to debug query plans + * - :ref:`LIST SAVED QUERIES` + - Lists previously saved query names, one per row. + * - :ref:`RECOMPILE SAVED QUERY` + - Recompiles a saved query that has been invalidated due to a schema change * - :ref:`SELECT GET_LICENSE_INFO` - View a user's license information * - :ref:`SELECT GET_DDL` @@ -126,6 +134,8 @@ The following table shows the Utility commands: - Returns a list of locks from across the cluster * - :ref:`SHOW NODE INFO` - Returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases + * - :ref:`SHOW SAVED QUERY` + - Returns a single row result containing the saved query string * - :ref:`SHOW SERVER STATUS` - Returns a list of active sessions across the cluster * - :ref:`SHOW VERSION` diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst index f7faef6c5..9e7d8d725 100644 --- a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst @@ -6,7 +6,7 @@ DROP_SAVED_QUERY ``DROP_SAVED_QUERY`` drops a :ref:`previously saved query`. -Read more in the :ref:`saved_queries` guide. +Read more in the :ref:`saved_queries` guide. See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. diff --git a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst index d6b63e30e..97b1139e9 100644 --- a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst @@ -6,6 +6,8 @@ RECOMPILE_SAVED_QUERY ``RECOMPILE_SAVED_QUERY`` recompiles a saved query that has been invalidated due to a schema change. +Read more in the :ref:`saved_queries` guide. + Permissions ============= From ee576fde06e1711088bf7017afa26f6ffa620520 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 24 Nov 2022 11:58:49 +0200 Subject: [PATCH 0288/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 957fa3505..3cdcc54b7 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -17,7 +17,7 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC .jar file `_ - sqream-jdbc-4.5.3 (.jar) * `JDBC driver `_ .. _.net: From 1aee577821bf4294cbcffafd74ace41ee212fec1 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 24 Nov 2022 14:35:02 +0200 Subject: [PATCH 0289/1892] Update drop_role.rst --- .../sql/sql_statements/access_control_commands/drop_role.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/access_control_commands/drop_role.rst b/reference/sql/sql_statements/access_control_commands/drop_role.rst index f519870cd..61c4d5bb9 100644 --- a/reference/sql/sql_statements/access_control_commands/drop_role.rst +++ b/reference/sql/sql_statements/access_control_commands/drop_role.rst @@ -13,7 +13,7 @@ See also :ref:`create_role`. Permissions ============= -To drop a role, the current role must have the ``SUPERUSER`` permission. +To drop a role, the current role must have a ``SUPERUSER`` cluster-level permission. Syntax ========== From 19fcd24b65fbace1c0939092adc4b313b7f29e66 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 24 Nov 2022 17:23:21 +0200 Subject: [PATCH 0290/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 49 +++++++++++++++++-------------------------- 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 158bc46a2..7f9eb19ea 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -11,46 +11,35 @@ The 2022.1.6 release notes were released on 11/xx/2022 and describe the followin New Features ---------- -The 2022.1.6 Release Notes include the following new features: -* keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. +* Improved ZLIB compression performance. :: -* Automatically close database client connections that have been open for 24 hours without any active statements. - - :: - -* release_defunct_locks utility function enhancement to receive new optional input parameter to specify timeout - for more details see `Lock Related Issues <../troubleshooting/lock_related_issues.html>`_. - - - - Known Issues --------- -No known issues. - +:ref:`Percentile` is not supported for Window functions. Version 2022.1.6 resolved Issues --------- -+-------------------------------+---------------------------------------------------------+ -| **SQ No.** | **Description** | -+===============================+=========================================================+ -| SQ-10160 | Spotfire casting issues when reading SQream data | -+-------------------------------+---------------------------------------------------------+ -| SQ-11811, SQ-11772 | Queries containing JOIN TEXT columns slow runtime | -+-------------------------------+---------------------------------------------------------+ -| SQ-11940, SQ-11926, SQ-11874 | Version 2022.1.5 encryption issues | -+-------------------------------+---------------------------------------------------------+ -| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | -+-------------------------------+---------------------------------------------------------+ -| | | -+-------------------------------+---------------------------------------------------------+ -| | | -+-------------------------------+---------------------------------------------------------+ - - ++-------------------------------+-------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++===============================+===========================================================================================+ +| SQ-10160 | Spotfire casting issues when reading SQream data | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-11772 | Queries containing JOIN TEXT columns slow runtime | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-12117 | Running TCPH-21 results in out of memory | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | ++-------------------------------+-------------------------------------------------------------------------------------------+ +| SQ-11295??????? | | ++-------------------------------+-------------------------------------------------------------------------------------------+ Configuration Changes From 7b1a44b54b4507093b7182a717670c3403a5fc57 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 28 Nov 2022 13:55:42 +0200 Subject: [PATCH 0291/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 7f9eb19ea..c11fbb099 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -23,23 +23,22 @@ Known Issues Version 2022.1.6 resolved Issues --------- -+-------------------------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+===============================+===========================================================================================+ -| SQ-10160 | Spotfire casting issues when reading SQream data | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-11772 | Queries containing JOIN TEXT columns slow runtime | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-12117 | Running TCPH-21 results in out of memory | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | -+-------------------------------+-------------------------------------------------------------------------------------------+ -| SQ-11295??????? | | -+-------------------------------+-------------------------------------------------------------------------------------------+ ++--------------------------------+--------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++================================+============================================================================================+ +| SQ-10160 | Spotfire casting issues when reading SQream data | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-12117 | Running TCPH-21 results in out of memory | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | ++--------------------------------+--------------------------------------------------------------------------------------------+ + Configuration Changes From bde0616602cc2237cae57c1d5936a05051a1ca52 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 28 Nov 2022 13:58:05 +0200 Subject: [PATCH 0292/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index c11fbb099..56580f26e 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -38,7 +38,7 @@ Version 2022.1.6 resolved Issues +--------------------------------+--------------------------------------------------------------------------------------------+ | SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | +--------------------------------+--------------------------------------------------------------------------------------------+ - + Configuration Changes From 8bf7f16cefb34b57e611b4f818a7debe62464ea5 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 29 Nov 2022 09:39:38 +0200 Subject: [PATCH 0293/1892] Update data_encryption_methods.rst --- feature_guides/data_encryption_methods.rst | 3 --- 1 file changed, 3 deletions(-) diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst index 0e5638058..db789d02f 100644 --- a/feature_guides/data_encryption_methods.rst +++ b/feature_guides/data_encryption_methods.rst @@ -5,9 +5,6 @@ Encryption Methods *********************** Data exists in one of following states and determines the encryption method: -.. contents:: - :local: - :depth: 1 Encrypting Data in Transit ---------------- From 0db6d80ac0ea70374a4316a0c86dbc20aacd26df Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 29 Nov 2022 10:35:21 +0200 Subject: [PATCH 0294/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index a37325e52..925abdbbe 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -21,6 +21,9 @@ Encryption can be used for the following: * Selecting data from an encrypted column. +.. note:: Executing ``CREATE TABLE AS`` ``SELECT`` when one or more columns contain encrypted data will result in newly created table containing unencrypted data. + + For more information on the encryption syntax, see :ref:`data_encryption_syntax`. For more information on GDPR compliance requirements, see the `GDPR checklist `_. \ No newline at end of file From 02cc00ec67fe78ced3380afebe7828dd5ee0d7a8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 29 Nov 2022 12:08:58 +0200 Subject: [PATCH 0295/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 56580f26e..b848d9296 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -13,6 +13,7 @@ New Features ---------- * Improved ZLIB compression performance. +* :ref:`.Net Driver` now supports .NET version 6 or newer. :: From e29f67ebaa8e090b7fd9316247ae5857e70e008e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 29 Nov 2022 14:16:33 +0200 Subject: [PATCH 0296/1892] RN updates --- releases/2022.1.6.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index b848d9296..56cdaa568 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.6 ************************** -The 2022.1.6 release notes were released on 11/xx/2022 and describe the following: +The 2022.1.6 release notes were released on 11/29/2022 and describe the following: .. contents:: :local: @@ -56,7 +56,7 @@ SQream is declaring end of support of VARCHAR data type, the decision resulted b VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). -TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. End of Support From 1c0016a009c09feecdef5477f8fd1fb808b64ce9 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 29 Nov 2022 14:49:10 +0200 Subject: [PATCH 0297/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 925abdbbe..919700131 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -11,7 +11,7 @@ The demand for confidentiality has steadily increased to protect the growing vol Encryption can be used for the following: -* Creating tables up to three encrypted columns. +* Creating tables with up to three encrypted columns. :: @@ -21,7 +21,7 @@ Encryption can be used for the following: * Selecting data from an encrypted column. -.. note:: Executing ``CREATE TABLE AS`` ``SELECT`` when one or more columns contain encrypted data will result in newly created table containing unencrypted data. +.. note:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS`` ``SELECT``, re-encryption of confidential information is required. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. From 6475feaaf6ef81251765727e44624aff28c36a9c Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 29 Nov 2022 14:54:01 +0200 Subject: [PATCH 0298/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index 919700131..f2fb60b57 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -21,7 +21,7 @@ Encryption can be used for the following: * Selecting data from an encrypted column. -.. note:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS`` ``SELECT``, re-encryption of confidential information is required. +.. note:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, re-encryption of confidential information is required. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. From f8b17a13d25132dd86a7013b7492b0610ee3a6fb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 29 Nov 2022 16:07:47 +0200 Subject: [PATCH 0299/1892] Update window_functions.rst --- reference/sql/sql_syntax/window_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 39d072d33..7718e8b3a 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -161,7 +161,7 @@ Without ``PARTITION BY``, all rows produced by the query are treated as a single ``ORDER BY`` ---------------------- -The ``ORDER BY`` clause determines the order in which the rows of a partition are processed by the window function. It works similarly to a query-level ``ORDER BY`` clause, but cannot use output-column names or numbers. +The ``ORDER BY`` clause determines the order in which the rows of a partition are processed by the window function. It works similarly to a query-level ``ORDER BY`` clause, but cannot use output-column names or indexes. Without ``ORDER BY``, rows are processed in an unspecified order. From 40e6bbfdaaff5ac400fd20069d8ce9dfc2f02988 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Tue, 29 Nov 2022 17:34:33 +0200 Subject: [PATCH 0300/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index f2fb60b57..ca953ce2a 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -21,8 +21,7 @@ Encryption can be used for the following: * Selecting data from an encrypted column. -.. note:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, re-encryption of confidential information is required. - +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. From e6a9eb800bfd51958a75b2bcb6a43a3ad090b389 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 30 Nov 2022 11:59:33 +0200 Subject: [PATCH 0301/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 56cdaa568..05caecddf 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -39,6 +39,8 @@ Version 2022.1.6 resolved Issues +--------------------------------+--------------------------------------------------------------------------------------------+ | SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | +--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-12204 | Possible issue when trying to INSERT Unicode data using .Net client | ++--------------------------------+--------------------------------------------------------------------------------------------+ From 682cb1ed2ae7af9b79cfe1d2e823e059b26e6eac Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 1 Dec 2022 08:33:12 +0200 Subject: [PATCH 0302/1892] Update 2022.1.6.rst --- releases/2022.1.6.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 05caecddf..67eb46222 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -12,7 +12,6 @@ The 2022.1.6 release notes were released on 11/29/2022 and describe the followin New Features ---------- -* Improved ZLIB compression performance. * :ref:`.Net Driver` now supports .NET version 6 or newer. :: From 726485821d8fc436d757a3839ab8b7b4503c810d Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 1 Dec 2022 13:11:21 +0200 Subject: [PATCH 0303/1892] 2022.1.7 --- conf.py | 2 +- releases/2022.1.7.rst | 102 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 releases/2022.1.7.rst diff --git a/conf.py b/conf.py index a821348da..104b75e03 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '2022.1.6' +release = '2022.1.7' diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst new file mode 100644 index 000000000..f879b41a1 --- /dev/null +++ b/releases/2022.1.7.rst @@ -0,0 +1,102 @@ +.. _2022.1.7: + +************************** +Release Notes 2022.1.7 +************************** +The 2022.1.7 release notes were released on 11/xx/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +---------- + + * Inserting data from a JSON file. + + :: + + * ZLIB compression type performance enhancements. + + :: + + +Known Issues +--------- +:ref:`Percentile` is not supported for Window functions. + +Version 2022.1.7 resolved Issues +--------- + ++--------------------------------+--------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++================================+============================================================================================+ +| SQ-12228 | Executing ``CREATE AS SELECT`` with ``UNION`` and ``GROUP BY`` fails. | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command. | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns. | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-11772 | ``JOIN`` query performance issue. | ++--------------------------------+--------------------------------------------------------------------------------------------+ +| SQ-11523 | ``SAVED QUERY`` execution internal error. | ++--------------------------------+--------------------------------------------------------------------------------------------+ + + +Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v2022.1.7 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From fcb4608588ecc6b948daff6afef73fb168ae8a93 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Sun, 4 Dec 2022 17:32:45 +0200 Subject: [PATCH 0304/1892] JSON --- data_ingestion/avro.rst | 4 +- data_ingestion/index.rst | 1 + data_ingestion/json.rst | 234 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+), 3 deletions(-) create mode 100644 data_ingestion/json.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index 7679df816..cfa048645 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -5,9 +5,7 @@ Inserting Data from Avro ************************** The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png - :align: middle - :width: 110 + .. contents:: :local: diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index c11d47faa..f75df595f 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -15,5 +15,6 @@ The **Data Ingestion Sources** provides information about the following: parquet orc oracle + json For information about database tools and interfaces that SQream supports, see `Third Party Tools `_. \ No newline at end of file diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst new file mode 100644 index 000000000..5cdd8d3f2 --- /dev/null +++ b/data_ingestion/json.rst @@ -0,0 +1,234 @@ +.. _json: + +************************** +Inserting Data from JSON +************************** + + +.. contents:: In this topic: + :local: + + +Overview +======== +JSON (Java Script Object Notation) is a popular textual format. It’s flexibility makes it a common choice for representing dynamic, nested and semi-structured data. It’s used both as a file format and as a way for serializing messages. + +SQream DB's JSON parser handles `RFC 8259 `_. SQream supports JSON files consisting of either as a continuous batch of JSON objects, or as an array of JSON objects. + +SQream supports the `JSON Lines `_ standard, in which each lines in the input file contains exactly one JSON value (either an array or an object). When exporting data, SQream will always use objects. +Note that in JSONLines files every newlines (ASCII 10) character always marked the end of a JSON object. Therefore, value strings containing newline must escape it as \n. + + +Making JSON Files Accessible to Workers +================ +To give workers access to files every node must have the same view of the storage being used. + +The following apply for JSON files to be accessible to workers: + +* For files hosted on NFS, ensure that the mount is accessible from all servers. + +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. + +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. + +For more information about restricted worker access, see :ref:`workload_manager`. + +Preparing Your Table +=============== +You can build your table structure on both local and foreign tables: + + +Creating a Table +--------------------- +Before loading data, you must build the ``CREATE TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.json`` table shown below: + +.. csv-table:: nba.json + :file: nba-t10.json + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE TABLE`` statement based on the **nba.json** table: + +.. code-block:: postgres + + CREATE TABLE ext_nba + ( + + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER json_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.json' + ); + +.. tip:: + + An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.json** file is stored on S3 at ``s3://sqream-demo-data/nba.json``. + +Creating a Foreign Table +--------------------- +Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. + +The example in this section is based on the source ``nba.json`` table shown below: + +.. csv-table:: nba.json + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to create the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER json_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.json' + ); + +.. tip:: + + An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + +.. note:: The **nba.json** file is stored on S3 at ``s3://sqream-demo-data/nba.json``. + +.. note:: The examples in the sections above are identical except for the syntax used to create the tables. + + +Mapping JSON to SQream +======================= +A JSON field consists of a key name and a value. JSON values may be the lower-case ``false``, ``true``, and ``null``, or any of the following data types: + + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - JSON Data Type + - Representation in SQream + - Notes + * - Number + - + - + * - String + - ``TEXT``, ``VARCHAR``, NVARCHAR + - Support in ``VARCHAR`` and ``NVARCHAR`` data types is about to end. + * - JSON Literal + - ``null``, ``true``, ``false`` + - + * - JSON Array + - ``TEXT`` + - + * - JSON Object + - ``TEXT`` + - + +JSON key names are mapped to SQream columns. Key names are case sensitive. +Note that using the jsonpath_location option overrides this mapping. - Verify meaning with Ben or Eyal. +A JSON row containing more than one field is registered as an error unless the fdw is configured to ignore. +An JSON row which is missing a field, automatically receives ``null`` as the value. + + +Ingesting Data into SQream +========================== + + +Syntax +------- +Before ingesting data into SQream from a JSON file, you must create a table using the following syntax: + +.. code-block:: + + COPY [schema name.]table_name + FROM WRAPPER fdw_name + ; + +After creating a table you can ingest data from an Avro file into SQream using the following syntax: + +.. code-block:: + + json_fdw + +To access JSON files, use the ``json_fdw`` with a ``copy_from``, ``copy_to``, or ``create_foreign_table`` statement. +The FDW syntax is: + +.. code-block:: + + json_fdw [OPTIONS(option=value[,...])] + +.. note:: Accessing JSON files is possible only by using the FDW syntax. + +Parameters +---------- +The following parameters are supported by json_fdw: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``datetime_format`` + - Default value is ``DEFAULT``. Supported date formats can be found in :ref:```COPY_TO```. + * - ``ignore_extra_fields`` + - Default is ``false``. + * - ``location`` + - A path on the local filesystem, S3, or HDFS URI. The local path must be an absolute path that SQream DB can access. + * - ``offset`` + - The row number to start with. + * - ``limit`` + - When specified, tells SQream DB to stop loading after the specified number of rows. Unlimited if unset. + * - ``error_log`` + - + * - ``continue_on_error + - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT`` When reading multiple files, if an entire file can’t be opened it will be skipped. + * - ``error_count`` + - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. + * - ``enforce_single_file`` + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``FALSE``. + * - ``max_file_size`` + - Sets the maximum file size (bytes). + * - ``aws_id``, ``aws_secret`` + - Specifies the authentication details for secured S3 buckets + + +Automatic Schema Inference +--------------------------- +You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. + + + +Examples +-------- + + + +Limitations +=========== +Currently SQream does not support compressed JSON files. \ No newline at end of file From a64e1126a7cc2b21cc553f7209045633a80319fe Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 09:37:04 +0200 Subject: [PATCH 0305/1892] Update ceiling.rst --- .../sql/sql_functions/scalar_functions/numeric/ceiling.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index 2f4e2d988..fad39aae6 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -15,7 +15,7 @@ Syntax CEILING( expr ) - CEIL ( expr ) --> DOUBLE + CEIL ( expr ) Arguments ============ @@ -34,7 +34,6 @@ Returns * ``CEIL`` Always returns a floating point result. -* ``CEILING`` returns the same type as the argument supplied. Notes ======= From 934ac91c5b64b0ddbbf939e4be89108f209750aa Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 16:29:09 +0200 Subject: [PATCH 0306/1892] JSON documentation --- data_ingestion/avro.rst | 4 +- data_ingestion/csv.rst | 7 +- data_ingestion/index.rst | 4 +- ...{inserting_data.rst => ingesting_data.rst} | 14 +- data_ingestion/json.rst | 120 ++++++++++-------- data_ingestion/nba-t10.csv | 18 +-- data_ingestion/nba.json | 9 ++ data_ingestion/orc.rst | 8 +- data_ingestion/parquet.rst | 6 +- ...automatic_foreign_table_ddl_resolution.rst | 2 +- 10 files changed, 109 insertions(+), 83 deletions(-) rename data_ingestion/{inserting_data.rst => ingesting_data.rst} (97%) create mode 100644 data_ingestion/nba.json diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index cfa048645..a548ec265 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -1,9 +1,9 @@ .. _avro: ************************** -Inserting Data from Avro +Ingesting Data from Avro ************************** -The **Inserting Data from Avro** page describes inserting data from Avro into SQream and includes the following: +The **Ingesting Data from Avro** page describes ingesting data from Avro into SQream and includes the following: diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 47c6d94a1..f902a5ed2 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -1,14 +1,15 @@ .. _csv: ********************** -Inserting Data from a CSV File +Ingesting Data from a CSV File ********************** -This guide covers inserting data from CSV files into SQream DB using the :ref:`copy_from` method. +This guide covers ingesting data from CSV files into SQream DB using the :ref:`copy_from` method. -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 1. Prepare CSVs ===================== diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index f75df595f..6e8530710 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -3,13 +3,13 @@ ************************* Data Ingestion Sources ************************* -The **Data Ingestion Sources** provides information about the following: +The **Data Ingestion Sources** page provides information about the following: .. toctree:: :maxdepth: 1 :glob: - inserting_data + ingesting_data avro csv parquet diff --git a/data_ingestion/inserting_data.rst b/data_ingestion/ingesting_data.rst similarity index 97% rename from data_ingestion/inserting_data.rst rename to data_ingestion/ingesting_data.rst index e20e37920..97d57ef4c 100644 --- a/data_ingestion/inserting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -1,9 +1,9 @@ -.. _inserting_data: +.. _ingesting_data: *************************** -Inserting Data Overview +Ingesting Data Overview *************************** -The **Inserting Data Overview** page provides basic information useful when ingesting data into SQream from a variety of sources and locations, and describes the following: +The **Ingesting Data Overview** page provides basic information useful when ingesting data into SQream from a variety of sources and locations, and describes the following: .. contents:: :local: @@ -20,8 +20,8 @@ SQream supports ingesting data using the following methods: * Executing the ``COPY FROM`` statement or ingesting data from foreign tables: * Local filesystem and locally mounted network filesystems - * Inserting Data using the Amazon S3 object storage service - * Inserting Data using an HDFS data storage system + * Ingesting Data using the Amazon S3 object storage service + * Ingesting Data using an HDFS data storage system SQream supports loading files from the following formats: @@ -149,7 +149,7 @@ Text files, such as CSV, rarely conform to `RFC 4180 `_. SQream supports JSON files consisting of either as a continuous batch of JSON objects, or as an array of JSON objects. +JSON (Java Script Object Notation) is both a file format and a serializer. It is a flexible file format commonly used for dynamic, nested, and semi-structured data representations. -SQream supports the `JSON Lines `_ standard, in which each lines in the input file contains exactly one JSON value (either an array or an object). When exporting data, SQream will always use objects. -Note that in JSONLines files every newlines (ASCII 10) character always marked the end of a JSON object. Therefore, value strings containing newline must escape it as \n. +SQream DB's JSON parser handles `RFC 8259 `_. SQream supports JSON files either as a continuous batch of JSON objects, or as an array of JSON objects. + +SQream supports the `JSON Lines `_ standard, in which each line in the input file contains exactly one JSON row. When exporting data, SQream will always use objects. +Note that in JSON Line files, every newline (ASCII 10) character always marks the end of a JSON object; therefore, if a value string contains a newline character, it must be escaped as \\n. Making JSON Files Accessible to Workers -================ -To give workers access to files every node must have the same view of the storage being used. +======================================= +To give workers access to files, every node in your system must have access to the storage being used. -The following apply for JSON files to be accessible to workers: +The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. -* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct **user-id**. For more information, see :ref:`hdfs`. +* For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about restricted worker access, see :ref:`workload_manager`. + Preparing Your Table -=============== +==================== You can build your table structure on both local and foreign tables: +.. contents:: + :local: + :depth: 1 Creating a Table --------------------- @@ -44,8 +48,8 @@ Before loading data, you must build the ``CREATE TABLE`` to correspond with the The example in this section is based on the source ``nba.json`` table shown below: -.. csv-table:: nba.json - :file: nba-t10.json +.. csv-table:: nba.avro + :file: nba-t10.csv :widths: auto :header-rows: 1 @@ -84,7 +88,7 @@ Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond w The example in this section is based on the source ``nba.json`` table shown below: -.. csv-table:: nba.json +.. csv-table:: nba.avro :file: nba-t10.csv :widths: auto :header-rows: 1 @@ -123,7 +127,7 @@ The following example shows the correct file structure used to create the ``CREA Mapping JSON to SQream ======================= -A JSON field consists of a key name and a value. JSON values may be the lower-case ``false``, ``true``, and ``null``, or any of the following data types: +A JSON field consists of a key name and a value. JSON values may be one of the following reserved words (lower-case) ``false``, ``true``, and ``null``, or any of the following data types: .. list-table:: @@ -134,10 +138,10 @@ A JSON field consists of a key name and a value. JSON values may be the lower-ca - Representation in SQream - Notes * - Number - - + - ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``numeric`` - * - String - - ``TEXT``, ``VARCHAR``, NVARCHAR + - ``TEXT``, ``VARCHAR``, ``NVARCHAR`` - Support in ``VARCHAR`` and ``NVARCHAR`` data types is about to end. * - JSON Literal - ``null``, ``true``, ``false`` @@ -150,42 +154,32 @@ A JSON field consists of a key name and a value. JSON values may be the lower-ca - JSON key names are mapped to SQream columns. Key names are case sensitive. -Note that using the jsonpath_location option overrides this mapping. - Verify meaning with Ben or Eyal. -A JSON row containing more than one field is registered as an error unless the fdw is configured to ignore. -An JSON row which is missing a field, automatically receives ``null`` as the value. + +By default, rows containing extra fields will be treated as errors. This behavior can be changed so they will be ignored instead. + +An empty JSON field is automatically mapped with ``null`` as the value. Ingesting Data into SQream -========================== +=========================== +.. contents:: In this topic: + :local: Syntax ------- -Before ingesting data into SQream from a JSON file, you must create a table using the following syntax: - -.. code-block:: - - COPY [schema name.]table_name - FROM WRAPPER fdw_name - ; - -After creating a table you can ingest data from an Avro file into SQream using the following syntax: - -.. code-block:: - - json_fdw - -To access JSON files, use the ``json_fdw`` with a ``copy_from``, ``copy_to``, or ``create_foreign_table`` statement. +To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIG TABLE`` statement. The FDW syntax is: .. code-block:: - json_fdw [OPTIONS(option=value[,...])] + json_fdw [OPTIONS(option=value[,...])] -.. note:: Accessing JSON files is possible only by using the FDW syntax. +.. note:: Reading and writing JSON files can be done only by using the ``json-fdw`` file format specifier. Parameters ----------- +------------ + The following parameters are supported by json_fdw: .. list-table:: @@ -195,9 +189,11 @@ The following parameters are supported by json_fdw: * - Parameter - Description * - ``datetime_format`` - - Default value is ``DEFAULT``. Supported date formats can be found in :ref:```COPY_TO```. + - Default value is ``default``. Supported date formats can be found in the :ref:`COPY FROM ` page. * - ``ignore_extra_fields`` - - Default is ``false``. + - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. + * - ``compression`` + - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``location`` - A path on the local filesystem, S3, or HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``offset`` @@ -206,12 +202,12 @@ The following parameters are supported by json_fdw: - When specified, tells SQream DB to stop loading after the specified number of rows. Unlimited if unset. * - ``error_log`` - - * - ``continue_on_error - - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT`` When reading multiple files, if an entire file can’t be opened it will be skipped. + * - ``continue_on_error`` + - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``error_count``. When reading multiple files, if an entire file can’t be opened it will be skipped. * - ``error_count`` - - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. + - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``enforce_single_file`` - - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``FALSE``. + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``false``. * - ``max_file_size`` - Sets the maximum file size (bytes). * - ``aws_id``, ``aws_secret`` @@ -220,15 +216,31 @@ The following parameters are supported by json_fdw: Automatic Schema Inference --------------------------- -You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. - +You may let SQream DB to automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. Examples --------- +------------ +The following is an example of creating a table: +.. code-block:: postgres + + COPY t + FROM WRAPPER fdw_name + OPTIONS + ( + [ copy_from_option [, ...] ] + ) + ; -Limitations -=========== -Currently SQream does not support compressed JSON files. \ No newline at end of file +The following is an example of loading data from a JSON file into SQream: + +.. code-block:: postgres + + WRAPPER json_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.json' + ); + diff --git a/data_ingestion/nba-t10.csv b/data_ingestion/nba-t10.csv index 024530355..e57ad3131 100644 --- a/data_ingestion/nba-t10.csv +++ b/data_ingestion/nba-t10.csv @@ -1,10 +1,10 @@ Name,Team,Number,Position,Age,Height,Weight,College,Salary -Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0 -Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0 -John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University, -R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0 -Jonas Jerebko,Boston Celtics,8.0,PF,29.0,6-10,231.0,,5000000.0 -Amir Johnson,Boston Celtics,90.0,PF,29.0,6-9,240.0,,12000000.0 -Jordan Mickey,Boston Celtics,55.0,PF,21.0,6-8,235.0,LSU,1170960.0 -Kelly Olynyk,Boston Celtics,41.0,C,25.0,7-0,238.0,Gonzaga,2165160.0 -Terry Rozier,Boston Celtics,12.0,PG,22.0,6-2,190.0,Louisville,1824360.0 +Avery Bradley,Boston Celtics,0,PG,25,44714,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,44718,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,44717,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,44717,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,44722,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,44721,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,44720,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,36708,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,44714,190,Louisville,1824360 diff --git a/data_ingestion/nba.json b/data_ingestion/nba.json new file mode 100644 index 000000000..e4df53204 --- /dev/null +++ b/data_ingestion/nba.json @@ -0,0 +1,9 @@ +{"name":"Avery Bradley","team":"Boston Celtics","number":0,"position":"PG","age":25,"height":"6-2","weight":180.0,"college":"Texas","salary":7730337.0} +{"name":"Jae Crowder","team":"Boston Celtics","number":99,"position":"SF","age":25,"height":"6-6","weight":235.0,"college":"Marquette","salary":6796117.0} +{"name":"John Holland","team":"Boston Celtics","number":30,"position":"SG","age":27,"height":"6-5","weight":205.0,"college":"Boston University","salary":null} +{"name":"R.J. Hunter","team":"Boston Celtics","number":28,"position":"SG","age":22,"height":"6-5","weight":185.0,"college":"Georgia State","salary":1148640.0} +{"name":"Jonas Jerebko","team":"Boston Celtics","number":8,"position":"PF","age":29,"height":"6-10","weight":231.0,"college":null,"salary":5000000.0} +{"name":"Amir Johnson","team":"Boston Celtics","number":90,"position":"PF","age":29,"height":"6-9","weight":240.0,"college":null,"salary":12000000.0} +{"name":"Jordan Mickey","team":"Boston Celtics","number":55,"position":"PF","age":21,"height":"6-8","weight":235.0,"college":"LSU","salary":1170960.0} +{"name":"Kelly Olynyk","team":"Boston Celtics","number":41,"position":"C","age":25,"height":"7-0","weight":238.0,"college":"Gonzaga","salary":2165160.0} +{"name":"Terry Rozier","team":"Boston Celtics","number":12,"position":"PG","age":22,"height":"6-2","weight":190.0,"college":"Louisville","salary":1824360.0} \ No newline at end of file diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index cfcf6c38b..f7ea1fdea 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -1,10 +1,14 @@ .. _orc: ********************** -Inserting Data from an ORC File +Ingesting Data from an ORC File ********************** -This guide covers inserting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. +.. contents:: + :local: + :depth: 1 + +This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. 1. Prepare the files diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 9a8e4c24b..2128cf17c 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -1,9 +1,9 @@ .. _parquet: ********************** -Inserting Data from a Parquet File +Ingesting Data from a Parquet File ********************** -This guide covers inserting data from Parquet files into SQream using :ref:`FOREIGN TABLE`, and describes the following; +This guide covers ingesting data from Parquet files into SQream using :ref:`FOREIGN TABLE`, and describes the following; .. contents:: :local: @@ -11,7 +11,7 @@ This guide covers inserting data from Parquet files into SQream using :ref:`FORE Overview =================== -SQream supports inserting data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of inserting it into SQream. SQream supports executing queries on external Parquet files. +SQream supports ingesting data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of ingesting it into SQream. SQream supports executing queries on external Parquet files. Preparing Your Parquet Files ===================== diff --git a/feature_guides/automatic_foreign_table_ddl_resolution.rst b/feature_guides/automatic_foreign_table_ddl_resolution.rst index 3ce1cc49f..6c0d1605c 100644 --- a/feature_guides/automatic_foreign_table_ddl_resolution.rst +++ b/feature_guides/automatic_foreign_table_ddl_resolution.rst @@ -15,7 +15,7 @@ SQream must be able to access a schema when reading and mapping external files t Usage Notes ---------- -The automatic foreign table DDL resolution feature supports Parquet, ORC, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. +The automatic foreign table DDL resolution feature supports Parquet, ORC, JSON, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. From bed2cdd8df602a71ad57119e3d4200f6ebc8c27e Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 17:21:07 +0200 Subject: [PATCH 0307/1892] Update json.rst --- data_ingestion/json.rst | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 489ffc9e5..121b1d62a 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -11,12 +11,14 @@ Ingesting Data from JSON Overview ======== -JSON (Java Script Object Notation) is both a file format and a serializer. It is a flexible file format commonly used for dynamic, nested, and semi-structured data representations. +JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. -SQream DB's JSON parser handles `RFC 8259 `_. SQream supports JSON files either as a continuous batch of JSON objects, or as an array of JSON objects. +The SQream DB JSON parser handles `RFC 8259 `_. +SQream DB supports: -SQream supports the `JSON Lines `_ standard, in which each line in the input file contains exactly one JSON row. When exporting data, SQream will always use objects. -Note that in JSON Line files, every newline (ASCII 10) character always marks the end of a JSON object; therefore, if a value string contains a newline character, it must be escaped as \\n. +* JSON files either as a continuous batch of JSON objects, or as an array of JSON objects +* The `JSON Lines `_ standard, in which every newline (ASCII 10) character always marks the end of a JSON object; therefore, if a value string contains a newline character, it must be escaped as \\n +When exporting data, SQream will always use objects. Making JSON Files Accessible to Workers @@ -44,7 +46,7 @@ You can build your table structure on both local and foreign tables: Creating a Table --------------------- -Before loading data, you must build the ``CREATE TABLE`` to correspond with the file structure of the inserted table. +Before loading data, you must build the ``CREATE TABLE`` statement to correspond with the file structure of the inserted table. The example in this section is based on the source ``nba.json`` table shown below: @@ -53,7 +55,7 @@ The example in this section is based on the source ``nba.json`` table shown belo :widths: auto :header-rows: 1 -The following example shows the correct file structure used to create the ``CREATE TABLE`` statement based on the **nba.json** table: +The following example shows the correct file structure used to build the ``CREATE TABLE`` statement based on the **nba.json** table: .. code-block:: postgres @@ -84,7 +86,7 @@ The following example shows the correct file structure used to create the ``CREA Creating a Foreign Table --------------------- -Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. +Before loading data, you must build the ``CREATE FOREIGN TABLE`` statement to correspond with the file structure of the inserted table. The example in this section is based on the source ``nba.json`` table shown below: @@ -93,7 +95,7 @@ The example in this section is based on the source ``nba.json`` table shown belo :widths: auto :header-rows: 1 -The following example shows the correct file structure used to create the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: +The following example shows the correct file structure used to build the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: .. code-block:: postgres @@ -153,11 +155,9 @@ A JSON field consists of a key name and a value. JSON values may be one of the f - ``TEXT`` - -JSON key names are mapped to SQream columns. Key names are case sensitive. - -By default, rows containing extra fields will be treated as errors. This behavior can be changed so they will be ignored instead. +JSON key names, which are case sensitive, are mapped to SQream columns. By default, key names which do not have corresponding SQream table columns are treated as errors, though this behavior can be changed so that they are ignored instead. -An empty JSON field is automatically mapped with ``null`` as the value. +An empty JSON field is automatically mapped to SQream with ``null`` as a value. Ingesting Data into SQream @@ -175,12 +175,12 @@ The FDW syntax is: json_fdw [OPTIONS(option=value[,...])] -.. note:: Reading and writing JSON files can be done only by using the ``json-fdw`` file format specifier. +.. note:: Reading and writing JSON files is enabled only by using the ``json-fdw`` file format specifier. Parameters ------------ -The following parameters are supported by json_fdw: +The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto @@ -217,7 +217,7 @@ The following parameters are supported by json_fdw: Automatic Schema Inference --------------------------- -You may let SQream DB to automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. +You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. Examples ------------ From da569cdbafc704617de1c8d70df18e7ef5f24585 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 17:24:41 +0200 Subject: [PATCH 0308/1892] JSON JSON --- data_ingestion/json.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 121b1d62a..12370279d 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -50,7 +50,7 @@ Before loading data, you must build the ``CREATE TABLE`` statement to correspond The example in this section is based on the source ``nba.json`` table shown below: -.. csv-table:: nba.avro +.. csv-table:: nba.json :file: nba-t10.csv :widths: auto :header-rows: 1 @@ -90,7 +90,7 @@ Before loading data, you must build the ``CREATE FOREIGN TABLE`` statement to co The example in this section is based on the source ``nba.json`` table shown below: -.. csv-table:: nba.avro +.. csv-table:: nba.json :file: nba-t10.csv :widths: auto :header-rows: 1 From 90eb9599c40d921e3cf81108f1944d1795930686 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 18:14:35 +0200 Subject: [PATCH 0309/1892] Update json.rst --- data_ingestion/json.rst | 63 ++++++----------------------------------- 1 file changed, 8 insertions(+), 55 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 12370279d..b5ccf661d 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -36,57 +36,10 @@ The following are required for JSON files to be accessible to workers: For more information about restricted worker access, see :ref:`workload_manager`. -Preparing Your Table -==================== -You can build your table structure on both local and foreign tables: - -.. contents:: - :local: - :depth: 1 - -Creating a Table ---------------------- -Before loading data, you must build the ``CREATE TABLE`` statement to correspond with the file structure of the inserted table. - -The example in this section is based on the source ``nba.json`` table shown below: - -.. csv-table:: nba.json - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The following example shows the correct file structure used to build the ``CREATE TABLE`` statement based on the **nba.json** table: - -.. code-block:: postgres - - CREATE TABLE ext_nba - ( - - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) - WRAPPER json_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.json' - ); - -.. tip:: - - An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. - -.. note:: The **nba.json** file is stored on S3 at ``s3://sqream-demo-data/nba.json``. Creating a Foreign Table ---------------------- -Before loading data, you must build the ``CREATE FOREIGN TABLE`` statement to correspond with the file structure of the inserted table. +========================= +When creating a foreign table statement, make sure that the table schema corresponds with the JSON file structure. The example in this section is based on the source ``nba.json`` table shown below: @@ -102,14 +55,14 @@ The following example shows the correct file structure used to build the ``CREAT CREATE FOREIGN TABLE ext_nba ( - Name TEXT(40), - Team TEXT(40), + Name TEXT, + Team TEXT, Number BIGINT, - Position TEXT(2), + Position TEXT, Age BIGINT, - Height TEXT(4), + Height TEXT, Weight BIGINT, - College TEXT(40), + College TEXT, Salary FLOAT ) WRAPPER json_fdw @@ -222,7 +175,7 @@ You may let SQream DB automatically infer the schema of a foreign table when usi Examples ------------ -The following is an example of creating a table: +The following is an example of creating a table using the COPY FROM statement: .. code-block:: postgres From 982c35427d48487e939a36ef94da96e13fc93893 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Mon, 5 Dec 2022 18:34:43 +0200 Subject: [PATCH 0310/1892] Update json.rst --- data_ingestion/json.rst | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index b5ccf661d..c744c6cd7 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -175,15 +175,38 @@ You may let SQream DB automatically infer the schema of a foreign table when usi Examples ------------ -The following is an example of creating a table using the COPY FROM statement: +The following is an example of creating a table using the ``COPY FROM``, ``COPY TO``, and ``CREATE FOREIGN TABLE`` statements: .. code-block:: postgres COPY t - FROM WRAPPER fdw_name + FROM WRAPPER json_fdw OPTIONS ( - [ copy_from_option [, ...] ] + location = 'somefile.json' + ) + ; + +.. code-block:: postgres + + COPY t + TO WRAPPER json_fdw + OPTIONS + ( + location = 'somefile.json' + ) + ; + +.. code-block:: postgres + + CREATE FOREIGN TABLE t + ( + id int not null + ) + WRAPPER json_fdw + OPTIONS + ( + location = 'somefile.json' ) ; From a96817cd5ef5074efca3fbc293b74527a3c2a3a5 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 8 Dec 2022 14:26:44 +0200 Subject: [PATCH 0311/1892] Update json.rst --- data_ingestion/json.rst | 204 ++++++++++++++++++++++++---------------- 1 file changed, 122 insertions(+), 82 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index c744c6cd7..b9eb6c5b9 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -13,12 +13,7 @@ Overview JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. -The SQream DB JSON parser handles `RFC 8259 `_. -SQream DB supports: - -* JSON files either as a continuous batch of JSON objects, or as an array of JSON objects -* The `JSON Lines `_ standard, in which every newline (ASCII 10) character always marks the end of a JSON object; therefore, if a value string contains a newline character, it must be escaped as \\n -When exporting data, SQream will always use objects. +The SQream DB JSON parser handles `RFC 8259 `_ and supports both JSON objects and object arrays. Making JSON Files Accessible to Workers @@ -36,53 +31,16 @@ The following are required for JSON files to be accessible to workers: For more information about restricted worker access, see :ref:`workload_manager`. +Mapping between JSON and SQream +=============================== -Creating a Foreign Table -========================= -When creating a foreign table statement, make sure that the table schema corresponds with the JSON file structure. - -The example in this section is based on the source ``nba.json`` table shown below: - -.. csv-table:: nba.json - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The following example shows the correct file structure used to build the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_nba - ( - - Name TEXT, - Team TEXT, - Number BIGINT, - Position TEXT, - Age BIGINT, - Height TEXT, - Weight BIGINT, - College TEXT, - Salary FLOAT - ) - WRAPPER json_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.json' - ); - -.. tip:: - - An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. - -.. note:: The **nba.json** file is stored on S3 at ``s3://sqream-demo-data/nba.json``. +The only JSON standard supported by SQream is the `JSON Lines `_ standard. -.. note:: The examples in the sections above are identical except for the syntax used to create the tables. +A JSON field consists of a key name and a value. +Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. -Mapping JSON to SQream -======================= -A JSON field consists of a key name and a value. JSON values may be one of the following reserved words (lower-case) ``false``, ``true``, and ``null``, or any of the following data types: +Values may be one of the following reserved words (lower-case): ``false``, ``true``, and ``null``, or any of the following data types: .. list-table:: @@ -91,27 +49,26 @@ A JSON field consists of a key name and a value. JSON values may be one of the f * - JSON Data Type - Representation in SQream - - Notes * - Number - - ``tinyint``, ``smallint``, ``int``, ``bigint``, ``float``, ``double``, ``numeric`` - - + - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - - ``TEXT``, ``VARCHAR``, ``NVARCHAR`` - - Support in ``VARCHAR`` and ``NVARCHAR`` data types is about to end. + - ``TEXT`` * - JSON Literal - - ``null``, ``true``, ``false`` - - + - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` - - * - JSON Object - ``TEXT`` - - -JSON key names, which are case sensitive, are mapped to SQream columns. By default, key names which do not have corresponding SQream table columns are treated as errors, though this behavior can be changed so that they are ignored instead. - An empty JSON field is automatically mapped to SQream with ``null`` as a value. +Character Escaping +------------------ + +The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to avoid a new line within a value string. + +When exporting data, SQream will always use objects. + Ingesting Data into SQream =========================== @@ -121,14 +78,16 @@ Ingesting Data into SQream Syntax ------- -To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIG TABLE`` statement. -The FDW syntax is: +To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. + +The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] -.. note:: Reading and writing JSON files is enabled only by using the ``json-fdw`` file format specifier. +.. note:: The ``json_fdw`` is the only file format specifier which may be used for reading and writing JSON files. + Parameters ------------ @@ -141,41 +100,49 @@ The following parameters are supported by ``json_fdw``: * - Parameter - Description - * - ``datetime_format`` - - Default value is ``default``. Supported date formats can be found in the :ref:`COPY FROM ` page. - * - ``ignore_extra_fields`` + * - ``DATETIME_FORMAT`` + - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. + * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. - * - ``compression`` + * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. - * - ``location`` + * - ``LOCATION`` - A path on the local filesystem, S3, or HDFS URI. The local path must be an absolute path that SQream DB can access. - * - ``offset`` + * - ``OFFSET`` - The row number to start with. - * - ``limit`` + * - ``LIMIT`` - When specified, tells SQream DB to stop loading after the specified number of rows. Unlimited if unset. - * - ``error_log`` - - - * - ``continue_on_error`` - - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``error_count``. When reading multiple files, if an entire file can’t be opened it will be skipped. - * - ``error_count`` + * - ``ERROR_LOG`` + - When used, the ``COPY`` process will write error information from unparsable rows to the file specified by this parameter. + + * If an existing file path is specified, it will be overwritten. + + * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. + + * Specifing an error log when creating a foreign table will write a new error log for every query on the foreign table. + * - ``CONTINUE_ON_ERROR`` + - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. + * - ``ERROR_COUNT`` - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. - * - ``enforce_single_file`` - - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``false``. - * - ``max_file_size`` + * - ``ENFORCE_SINGLE_FILE`` + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``max_file_size``. When set to ``true``, the single file size is not limited by the ``max_file_size`` setting. When set to ``false``, the combined file sizes cannot exceed the ``max_file_size``. Default value: ``false``. + * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). - * - ``aws_id``, ``aws_secret`` + * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets Automatic Schema Inference --------------------------- -You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. +You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. + +For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. Examples ------------ -The following is an example of creating a table using the ``COPY FROM``, ``COPY TO``, and ``CREATE FOREIGN TABLE`` statements: +Using the ``COPY FROM`` statement: .. code-block:: postgres @@ -187,6 +154,8 @@ The following is an example of creating a table using the ``COPY FROM``, ``COPY ) ; +Using the ``COPY TO`` statement: + .. code-block:: postgres COPY t @@ -197,6 +166,8 @@ The following is an example of creating a table using the ``COPY FROM``, ``COPY ) ; +When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. + .. code-block:: postgres CREATE FOREIGN TABLE t @@ -217,6 +188,75 @@ The following is an example of loading data from a JSON file into SQream: WRAPPER json_fdw OPTIONS ( - LOCATION = 's3://sqream-demo-data/nba.json' + LOCATION = 'somefile.json' ); + + +JSON object array: + +.. code-block:: postgres + + { + "name":"Avery Bradley", + "age":25, + "position":"PG" + } + { + "name":"Jae Crowder", + "age":25, + "position":"PG" + } + { + "name":"John Holland", + "age":27, + "position":"SG" + } + +JSON objects: + +.. code-block:: postgres + + [ + { "name":"Avery Bradley", "age":25, "position":"PG" }, + { "name":"Jae Crowder", "age":25, "position":"SF" }, + { "name":"John Holland", "age":27, "position":"SG" } + ] + + +The example in this section is based on the source ``nba.json`` table shown below: + +.. csv-table:: nba.json + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + +The following example shows the correct file structure used to build the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: + +.. code-block:: postgres + + CREATE FOREIGN TABLE ext_nba + ( + + Name TEXT, + Team TEXT, + Number BIGINT, + Position TEXT, + Age BIGINT, + Height TEXT, + Weight BIGINT, + College TEXT, + Salary FLOAT + ) + WRAPPER json_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba.json' + ); + +.. tip:: + + An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. + + + From f9112474ad464ee2fa95f883ec9a38dc78d414a7 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Thu, 8 Dec 2022 17:01:46 +0200 Subject: [PATCH 0312/1892] JSON --- data_ingestion/csv.rst | 8 +-- data_ingestion/json.rst | 110 ++++++++++++++-------------------------- data_ingestion/orc.rst | 10 ++-- 3 files changed, 47 insertions(+), 81 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index f902a5ed2..afe819fb5 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -11,7 +11,7 @@ This guide covers ingesting data from CSV files into SQream DB using the :ref:`c :local: :depth: 1 -1. Prepare CSVs +Prepare CSVs ===================== Prepare the source CSVs, with the following requirements: @@ -45,7 +45,7 @@ Prepare the source CSVs, with the following requirements: .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. -2. Place CSVs where SQream DB workers can access +Place CSVs where SQream DB workers can access ======================================================= During data load, the :ref:`copy_from` command can run on any worker (unless explicitly speficied with the :ref:`workload_manager`). @@ -57,7 +57,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. -3. Figure out the table structure +Figure out the table structure =============================================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -96,7 +96,7 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st ); -4. Bulk load the data with COPY FROM +Bulk load the data with COPY FROM ==================================== The CSV is a standard CSV, but with two differences from SQream DB defaults: diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index b9eb6c5b9..16f0b20f1 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -15,9 +15,12 @@ JSON (Java Script Object Notation) is used both as a file format and as a serial The SQream DB JSON parser handles `RFC 8259 `_ and supports both JSON objects and object arrays. +The only JSON standard supported by SQream is `JSON Lines `_. + Making JSON Files Accessible to Workers ======================================= + To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: @@ -34,15 +37,12 @@ For more information about restricted worker access, see :ref:`workload_manager` Mapping between JSON and SQream =============================== -The only JSON standard supported by SQream is the `JSON Lines `_ standard. - A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. Values may be one of the following reserved words (lower-case): ``false``, ``true``, and ``null``, or any of the following data types: - .. list-table:: :widths: auto :header-rows: 1 @@ -60,18 +60,16 @@ Values may be one of the following reserved words (lower-case): ``false``, ``tru * - JSON Object - ``TEXT`` -An empty JSON field is automatically mapped to SQream with ``null`` as a value. +Missing JSON fields are automatically mapped to SQream with ``null`` as a value. Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to avoid a new line within a value string. -When exporting data, SQream will always use objects. - -Ingesting Data into SQream -=========================== +Ingesting JSON Data into SQream +=============================== .. contents:: In this topic: :local: @@ -86,8 +84,6 @@ The Foreign Data Wrapper (FDW) syntax is: json_fdw [OPTIONS(option=value[,...])] -.. note:: The ``json_fdw`` is the only file format specifier which may be used for reading and writing JSON files. - Parameters ------------ @@ -139,9 +135,40 @@ You may let SQream DB automatically infer the schema of a foreign table when usi For more information, follow the :ref:`Automatic Foreign Table DDL Resolution` page. +Automatic Schema Inference example: + +.. code-block:: postgres + + CREATE FOREIGN TABLE t + WRAPPER json_fdw + OPTIONS + ( + location = 'somefile.json' + ) + ; + + Examples ------------ +JSON object array: + +.. code-block:: postgres + + { "name":"Avery Bradley", "age":25, "position":"PG" } + { "name":"Jae Crowder", "age":25, "position":"PG" } + { "name":"John Holland", "age":27, "position":"SG" } + +JSON objects: + +.. code-block:: postgres + + [ + { "name":"Avery Bradley", "age":25, "position":"PG" }, + { "name":"Jae Crowder", "age":25, "position":"SF" }, + { "name":"John Holland", "age":27, "position":"SG" } + ] + Using the ``COPY FROM`` statement: .. code-block:: postgres @@ -154,7 +181,7 @@ Using the ``COPY FROM`` statement: ) ; -Using the ``COPY TO`` statement: +Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres @@ -193,67 +220,6 @@ The following is an example of loading data from a JSON file into SQream: -JSON object array: - -.. code-block:: postgres - - { - "name":"Avery Bradley", - "age":25, - "position":"PG" - } - { - "name":"Jae Crowder", - "age":25, - "position":"PG" - } - { - "name":"John Holland", - "age":27, - "position":"SG" - } - -JSON objects: - -.. code-block:: postgres - - [ - { "name":"Avery Bradley", "age":25, "position":"PG" }, - { "name":"Jae Crowder", "age":25, "position":"SF" }, - { "name":"John Holland", "age":27, "position":"SG" } - ] - - -The example in this section is based on the source ``nba.json`` table shown below: - -.. csv-table:: nba.json - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The following example shows the correct file structure used to build the ``CREATE FOREIGN TABLE`` statement based on the **nba.json** table: - -.. code-block:: postgres - - CREATE FOREIGN TABLE ext_nba - ( - - Name TEXT, - Team TEXT, - Number BIGINT, - Position TEXT, - Age BIGINT, - Height TEXT, - Weight BIGINT, - College TEXT, - Salary FLOAT - ) - WRAPPER json_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.json' - ); - .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index f7ea1fdea..4906a80de 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -11,7 +11,7 @@ Ingesting Data from an ORC File This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE`. -1. Prepare the files +Prepare the files ===================== Prepare the source ORC files, with the following requirements: @@ -157,7 +157,7 @@ Prepare the source ORC files, with the following requirements: .. [#f7] Will succeed if all values fit the destination type -2. Place ORC files where SQream DB workers can access them +Place ORC files where SQream DB workers can access them ================================================================ Any worker may try to access files (unless explicitly speficied with the :ref:`workload_manager`). @@ -169,7 +169,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. -3. Figure out the table structure +Figure out the table structure =============================================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -213,7 +213,7 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA If the column type isn't supported, a possible workaround is to set it to any arbitrary type and then exclude it from subsequent queries. -4. Verify table contents +Verify table contents ==================================== External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. @@ -236,7 +236,7 @@ External tables do not verify file integrity or structure, so verify that the ta If any errors show up at this stage, verify the structure of the ORC files and match them to the external table structure you created. -5. Copying data into SQream DB +Copying data into SQream DB =================================== To load the data into SQream DB, use the :ref:`create_table_as` statement: From 2aacceeff2202e104ed06ff58a87293596bf0ab0 Mon Sep 17 00:00:00 2001 From: RosinTalia Date: Sun, 11 Dec 2022 09:08:03 +0200 Subject: [PATCH 0313/1892] System architecture --- _static/images/chunks_and_extents.png | Bin 75743 -> 70037 bytes _static/images/storage_organization.png | Bin 84955 -> 79471 bytes _static/images/table_columns_storage.png | Bin 46261 -> 54784 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/_static/images/chunks_and_extents.png b/_static/images/chunks_and_extents.png index bb092fab7dc403e87f92cc405d41f2ddf8150f67..8b3cc8d0523a62b8c4b841ecb92d8bce58c8f8d9 100644 GIT binary patch literal 70037 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

RSYQTD~ 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 literal 75743 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 F{{YiA!f^lq diff --git a/_static/images/storage_organization.png b/_static/images/storage_organization.png index 8cde6d70e90f6784b7e2c12b784edda47d4acf6e..d6a06d7635e20e31f31f136389bf242b7b47494a 100644 GIT binary patch literal 79471 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 O!<-%54l?b7&;JWR(f17i literal 84955 zcmeFZ`8$;H-!^`wq)3vrY(*vemVGUv2xZ^NBqIC1j*^I&N_LTijD6qNER~(?%UH6F zWiZBAXP)=e=f0os_xa)Z1D@k{933um=)Jy{^E_X#%bSN<YSfgMDIo}=zJE_e2ZAVq zA?TFUnbY8t<-ulU@a?S2J!5wWqPj@>cVb{F=m>(YK=)N{>-nUtP5Hn3v=GR>XNhvI z@mRG!dq21;+@)CQm2gop>`8n~LbPr>3x)OvoRX;NuAcOD<+jA4v2l@~9B&-LcyEo{ zh~DpR^%2#Qh~Va$`?~eygOPfjY4CF{yO5~sFN7}|g*$mx{>D!XyC1OjUlh1npDmP) zA_O3(WwK3=6_x_iDi1SPF#Gb2$e%xdf|ZiKthRE!s89TR-o6c;`}g#Yj?C)cQ*g=! z=;Xi0Kd&I>e@|DqPc{8}f~2oPq`iZ$A7@Vp|9eu>Iurb#A>Ho$&yfFfmj7c!5cEIZ z1N~3ffc_temtTfMPeBPx`LxCPdv}r}O;fP@A9l8WNlSfO;{0Me-m$X(;u!}<zITa~ z27>Q?v3GMDC?|t%TJro52(6vS3Um@|ncOca+>`OomZuCS{nqC@XF<{soT|7~(Z;&{ zG?q64LH~WGzO5s*+LwovS7xk9S!H@^_t}K`;_A!PWX3ZX+B2lw)O2(a<fyK-)MpcU zdiY(Mw6}!!F`-M`2Nnw0{nQsDuqOe_d4()DgQlLF)E=QrRUI4~_|XnYl)a{x$G=pk z=Wia#F9nz<>RdVU5jm$Y=TA+VZ!r#}yBWtEZ_G(rS9n~Xw?}}m*7>?eXFSw8Ue9&w z>Rxr8oqu)$WBs0Nt|lo<?Dp0;gP~fWCag@t`G?<WZI#xZXUDJp9)R%;kR%hfT~q>Q zt(Q3US5l>LZnGlf^^xL#x_Luec+LpQTUZZmHdyxseg2|FLKl#m5=fl<p80JNzfA>i z(PTE^M}IO=>NmI-t6;6;;}W!PZ?;#k2xX~PRWg$)HvC@tyXL1cV9iEo9mp5;!2MmE zN6<pPbI1G21~&PV&ipvvnroioQN_jUSyfI`hl2E{@r?0P8#!I2qzQxD)c($xbAT^c zaes#lwDdW~P&NxKXmqNe%4WZZD*2q|_)Yg00X)^tuRaC&OwdHb#m*mX7Iy#OS05TA zV$v0P_-T&`0%;N8KqgaINaN}y*&CjMtbS2-5VZDW!*pmCoCAmmN)3m<sKQ+tO#1L+ zT;NluO#2xax8<!)(ti?GBLR%A+@AT~L>JNr30!{Qis{+dnBQo2<Fa7qaR|-U?V6!# zc}2+Talm>t3MH)|;zs;2I-?$MMYuIA;9p;Z+^~f2#Gwv;=}6mx{gF=e;f@K>W%kVl zAE%wD=njqg5ZAHGjW5Zd(j^CqAWR|JA$h{N{vbviV;oeT_(`optD$IiC7yWH>7RN$ z#kWz7Lmd%5NV`J8l(uK>px|dZXO2E?5TrzI*_%AQk35j~u)k@sd?~#6=TEZ~I_Tjg zFAUsnVtKD`ilb&$tOZ401P*_%kD7>l8eqLMJ9WrmZ|+71K@ZbET0&3?%qM`iNY2eq zYFJ{Jp(4%%lUz$b9~09rFURP7K8leSegazjv8$O|F+4nUD-lILFkW}n1emb%X1614 zvG;u~GDs<u793QH8qy#T=JK^j{I^~QxC|qGOBTLWhc8*kUuB=T$m^f2va<{59g{&_ zA;WP864<(?%l7d@YIW6Lmw+dJAUT@g9VDf~`--`NzDy-4{nM4dwd4geA4-weorKMY zb`XkP^&3bR^YAL^rY@zNeU-g#Vye&3-KJDkQG>j2fjhIK?M7(rGoB^-&1h}ao#?j= ziUw0ukv}(%X&j@&y9dup3-n8y23|(cSAIB&pC+`iqpm1rN{tR-OuD`Z<eIv<3qp|Z zU(dPz?C0`;=nt_(i|chIgmugBJ=Eb#$fUi=d0z6`pM85OSAVCjtOoxo_a`dnw<&pJ zrA-fx1gKnRYVnGCel>-AK36#X)Dd8kyT?~w_+tMw&)bB?9a{Jb4F4ux!4j0`1-2Gl zV0vw<HYwZNMiUR2qQu9(uStdpMUJTD!k)NY!!oa~4!0K|o_E$MLJ*eZD#F@XhCOjC zC8;bIY2Iqmli6KqjEJq9h?v-&oBu_rFk9Q>%YXB9Yat_F7@jd?ww^caMfJNDRBdHm zr`$GS<a`^0K(Fm|qqm273bRubde2}{<OWPR&%r)A*0Vzl(JyJiWUgH9>Nn@HC^9@! z_^VC`OsoMWE;?iU`cm9$U_3S4oEto+8w?khzZUX4*|v}j%CCU=Ot!F3Zwos+xE_8B zGArQQlsb7kfmO^$25zC4=e3ztflhcrm><{NR`{qdX5CUwv@whns3J|vS1BN<Xj4ZK z1%?{GL|drR8mPg4ByT8#@6D_pttY03@vZiOU;SJ{3fB<t_f+fUpJNRV&$WY}f+Mex z*np80k&xWjuTak+h`GWH1`Lk;N&&b*6PZ8Es;nlzLBbx1G>f>jgV5BQ6gd&8jGwv3 zx`yrz$jhJ;@0YC+#1f8Sz@YiTd5{i8a|a>*WLoi3vR!l*GHF}=_KjmnO314CFEimU z8idVfTLPy`Hc1X`TDmujnbi$p@O;oT*Do%7Ijlz8R$&^6Ug)ow+gLlK(QLQThq>-Y zB#R>YWp6R!#LN4~6OJ2cxVhV{4}ZNj8h#k#`_`~FObkQypS%L;1=D*3W#=jiIusx} zlhAPi7v$s=XbY*|w!TU4r<A&ERXko&bA4m_L;XuheH!>&y<vPgobq$0{Og;k8V1_z za_l1oCI-XIwW)s6Sl~2WLL{Q36v~{O@^<7PjA~-Mz2-j-8ux%%PC@$8)OT3Fyr_ZC zDR9t&pGd6hGg;=Z5gptr$(M~SS-QoCswrRT#yTSdHdxpY4gDhZLE!wY82=J4-bp<r znV`ih4!OuL)fF-(_6}dtvyht!cV^?p(Gha*>DRK*(;nwxbTR#k66_~obfFQpU?wZC zzgNnbSZtjjBTp~L6Z-u=<!guBY-FedGD{&<P{YoQ(!G~3>GPIJQT&#|qi<_b)-I&H z^Pe3>e{7k(&_o6<`olF~2aK^K8&X*Jsl2P=Al-oq!a6%y3>S?{Hk0iSzi+G~F3|Np z7s3wVwfuwrOiwiWJn7dw1qpN4P^isW8NwISDLUFa$B9NLD-Y_oapLXxpx<mL*=^NZ zcXuUm9)?3|gVcskrxhatCr&^{tRM_2-Q_u52ha%5j3$C_X-<kl%}*JsbJ3!y_eAm6 z?J;G+i$H+L%sz}jP;h?9W~QeKKM@@1Rh7-HP<5Clsy#a1zOcnNf?}n0Oze;vQe@U{ z+;cm(yZe+KhFgg5*cCl#1wo87;P#5FKw!T~UON$K>bFs-)0I^l0gGj)y1fO08;((V zmi`P!6@FJ}Lu3_tr=6RGhIOLjx|Spqq-i@2YCDsX<7&_)(X)O1Nq6@AYjXLp%$*~7 zZ=(2;e#u0?PSRMtL<2Rokm5KN$$X&j@LV8y1OKbowue<0&N1=5P74p0C&kMSb6Rlr z5Th7akg!lhGp6U+P{PCe3UL+S+|^MTG${W=Chr;<(l7C=4m*M5F$vZ;MMv992{%5a z<GGmu;^Wtgq?8_f_dbX$UDfa3{1i&EVN5(U111W_<|2)~R1>Dg(k&W!pE&wzl^lHB z^o8Wl!b=v?@&Qktix$-7<p=_o=CyA@$>H4c%!52<eFHsVZy%f!*b@<8ILXC5|EGzC z!Mh?bV}45qV@1w-7J66^Vt!2PDu=!4IppcuG43FSY5Y>aqqT!*i=imx_|A8du6QAf zg;P~c6d^M9`=X^U`tT9Q80wD~vfW?i1jI=7ciR@L9MO`eRp&|;4?x^zp%#xVzVH)Z z4M7w1gf%v4;!9?_wCZW{CU?jA2+hz<d@=>`nra6hx1GGmt;?jON@fLJ;V_UKX)Di- zvr&l0321Jyj7)y;B~CYQeT&|XPS2^h;bewlWHG#D!#@9$$uhEDn=QO~db$hte1FR^ z5l;?T1p&ti_7#(mHa_!ma9GEbjSp=P(^qz!-M?dSS`qupvb8vsX`adH$mb}2iE!(6 zyB@qJc0zLMQk1I<;n3S#z-KQx&KGzx->C-R`&54XP}8K*kRFGrLFE&6e|?zp(Hzdu zW?E7I3I|%jd|2e;N3nLrA$_J6)S$Wf7>(7P$a4VTkhB*5aQX%uBC3@oL|0=h^MaH< zdFAh66?aX~-v)+lAbR-9mJw!ST&HS=_i(Zt;fjF-#g5g$jsRHKm-g|jy&rLDk!f{v za9%z0UfVrc5a+)CixS`GbrHw_5M!VpeBj_8(q@s(zPZFFqH)`WGMpt+Lv2Lw?p1yT zL*zBB$J-Cuxw)wdT?-tOgJgo{BGRO>V-tl(dTZlE)R(7oL!-Z+-(Pk+r>)n)mp#(X z?Q~RKwThge<Z`T?%P4+^L#TC75wEKD<W%&y9k<`O0kb+<@5M(y2&BpE^Y$^z{ELq@ zB0*UE=3|Q#U;1p1Eyz{yG1xn7Qan;Vs>K9k@Acahe{te3FjlxAS&<r19>vvQEO>`9 zkOnW_F{>-!x~J#<IINK4SoO%VH%OAb@o-~wHx=KS6i2-^yQ)Y>+)ZvYoVERnP$Nkb z84Xkv)Gl<bq_GjSR#@_*Y-<haE9g%<+h2;%><$SPHo78roxDNqkY(NuuFJ}1_m)l> zCl)m2&aKtDt4PF3ZLesnIVdYXH!2n>Ft5LU-jgkb7(&v`f>TJ;h5p!e$y-Q@f#+OM zv90mr$d(Vk=|V3^k+<-$T0ByWJG`DT$of@)yn*}mWy;6S2Yc4I^E4fe@ZFWYby>xt zzHAV3A*h-Zb8lY0q&>Udb!=-ZDrbQVaFkoM)M$3ON?*VtPj_BYPg^fw$OVK)^(9Y_ z&p9pyOSx<HdgjM!ORFAM{YFz&&x}XjrBMfu?e6r)xEAFqV!w49ytW?E6|$X%yLia? zg&oc}v5aB1xaNoYjcWOm(DtGT*Q4Kd&#Tvm!?)H1^zD<AME^T;(odB)@DX-#<u=-C zJj@O6bZ(k`K!#__;!&NR8(TY3!=KLj*@{gDO7cL&6+VNWPKRde0dbF=7L5yiwSR1( zAAh1X9bNHpo{8K-p^dT|buw52Pe9NY?3=1DEBjrro#=wdb;aG4QILMI%>NSYxY;oC z!l~K+<Rqp3sQhdy?cHNL&-B7|vm}dWEMlk1d_B6iU+g7Pb92ryqTF1f)h0M(x2-yC z;o_VPPn@Q&hBo32M@4|GE43v}G(IPT_(ge65y}M$+det?Q))=)HvDGVr!#DzRfO+v zwQP?zb+J3b*S5m<W=2(p2D9wcT?H%T#|fjU>QW>OW^_&u+;Iw5=tu7YdE-%wHDksw z?ef-H-R`WFi(fNSb=xptm6V;vCou)+_i83w1vT9HMoB@hoy><=M)H`A+?-YK=W>1Z z-zYWb8^p@$;4m5MTQ20Rm%-rtlpufwQ{7`|&df~Lz2aKd$P<13R*z}#WE&^BUb4w+ zYu!$(t9uLwcW&hT!WERkYC7osJ~UeRDc>dj?lr<b+;}P>P@NXn+}L!CqvByrJ33n8 zFiPM$b;Y@1cM^kPO=GTxKY8ww87T|Dyc$<;VXluaRP^g~4z$Th5rg>YK`>~#tKR%{ zT%Gboo09I;yn74|8rSKy9y?Qh)nP8LaIM-jo1t3R|B)uY8=1L@H(Qz3scK9~I0)Mj zlf=18n(RsQA3qR0J&1`1=G_wzK&!w+3-<JDxBMiy2V8mgdZoqj&m=s5<M^wd3_uY_ zH+MSWga!Ft!Uh9=^1wL={xd}i;)lRWlvH&Y3T+MNGlgM3bu|~xWq0V@OhJw_#?UV_ zRvgU1rtD_7Cb8sC)l83Pn_r`Gq4uNR?l&$7PI^oe<_3D#^sdO6?U_-&)~K)4P#kf; z8d{Zk#rvRMD70=RMIGP1;uW;4T<o|$9x0PlgZ{Zwguh55Pu@-u5J~p11VD=k``lFw z;m0tA1KK{Rt5a@b)Jr#D`88Z0i$@)Xgn47&%QPGH$C2_H_GFM1I|*(*eUw9q3Anwo zbKy^`i=TzAkAl1~4^QZgg@hbY;n3TIit#VM=pY`Q5aNG})BK*TSiB##hkoBF$a^aF z=gx&)>%%y0nsA{5PgQ%N3VVDVDU?-VvXTWoD=+bV6}m#+J`vhfRK~W3Mug8NE`9cQ zxt1ztG)<8I&H}TR^B<Lx>!<H!U5!?r$`(VsU%bkuAr0H1Ub1eBUr#o0%x547rVKAq z_Yd?j28K90b#5*SLNlDCbuaes%;=9&K8W9-X{=Z%_o?u=k((&zbiWY5!)U*9aBkL_ zF{g08$NJ1U{zo8-wN9B1+bHbQr^M9~>4=*T>b3?n5<844{5+4a6mX=A;20ai!BBwD z;cbp^V84T7j&tXCUw(V)@=i3@v>AF3g51?Xb^~-%M||UxgEnIYlYd+r2<4$c^H|!` zz44A1-(KTFk3T@~5Gy=tGpqMQUTz=)RJrF9nxX(4rAr#v2c$$^Q;hR?tf6xz#V;~D zVycbxO!lTXhFj5haULi|OQJ^t`vU+Zv60}L3FYNrs$chG-P>*!+Ot77!$2lTaE}u2 zJP2zq#j~6=LJxe{8jOz;!clA2w;rmZDSNZ=P{FNdzN;u=Q`meAfRdePmLArrAA3jq zp+w!0W3-`ew8ibg4=u|Syfacz!VR3iAa~g${+B~>7J(uW&vDuLjbs>02Cs$Cd<j3I zoZ7SBC`P_3$bGNGC$LOL^@f_@T&`_JgOlUh!H<fr!;{bg2`9Qc*&Xc=*=aF+yRcVn zGo1w&WBCOb0-bJ}=}?Bn&|jcIjL@etk<Gm?B{B)?U$nI6n4w>k(9^ENx{K?knLd)d z%!h8L?A7SNcS^!}olrZyJ>#}O?*ihE16H*2lUid?can{vnXcjBEulhh+JS-J`OkdO z>e5%BUzkhv#BycVyPeoXJciAjiTkx_hD<}O@7tfF7gm#!U^Y`*AXG<<+#Px7n3DQ~ zaAO*W%Oxd=kJ^7BCn@@Fg6La`iy9_`F?hlh9olpBxafw=aYJ;()r@t-y6bzRJoQ<Z z2UJ!}<Lk*Aa;s;eKLuR100Pw)+nFd|>5?58)E<GOt$jF|*IGfMVv0Gxn`MIz91JAP z1c*UXO0M6Z_ru}2?9t(An);7N_&LH^Otl$!+pW?wDSvzq>;{NHgH>UuPKMKKBVg-2 zS4<kQE+}1?BDxN@zQ25Uc%J7}YGKp<)X~hI<b22oTqd-M!Bq~J)gKZ(NTA_4(u~y# zy?!rk-Qv-x4s!}}a9H9zQ_GBIckH7a)rL$=bJ?HuenOU%OrO-?cBP?e>-5}qUK77* z_-5t6+h`gF-Vcg|c^V;HPOvn-l_t6k9<XtkX!%rE!*tCLz0h??6CK@gkSoz~pgD%x z6frhugCDJ9R2=npCAG7rOL~cRp0|dEp0Lm7pKzW&1sU=G-F0oy!XM)H@ifxA?g8Z- zDe=&D_5=uqw(y}ltaY(gv-4t|36x>gr+9vA#@6Sco~2_}?96Ak?BMfl=f7Br3uo(` zIoDMmlOewquhtN=@5x@b|Gjv=Cszyu2k79uXW`Al!nOVo*O@T5xq<cw$1aMMqt?|S zy~EMqe<xw#3^uk;IYP6Gmk5r%1-tq2Ww$oE9TjD^f8}`Q>R!P+Wwq2iyFK;Bd&9*^ zyHm#~AV=rs-p}-ds`kpJmt**hp)Hf%b4>f3AMZ?k&>59w*)W@kS@q2hDD_2<2y%iZ z$QCmJI>E*6uhoB0czJj@HGT|+DP#LqEGM>2)?^!MjJ8Zu-E*ac(veuU*BvPNk54zg zs!wHWmFah#%T~wAj-&>3B%iZ7UFwB+6<U^&Ay)r>mOw7`imNUEBHP$dL%9xuIzf3V zgew%eo~O!f|Hb>3f4Mi&$n>%2*Pl0GKR1o&j$za`nggRM?zi-ZR6b%G)nhPbCn%u= zMX)$4Ri3(gS5=Fd&^y6g@+kkD6KcxcDo0(f>0C!@3Zw#%(&y9cdE{E|XmmzfmIhpL zdM>ZOe3zODR)Kk66s!Xsku%Lamz9wbTIlqTbfz40V1SG!Yfh`qKg6$eEj`q)mm4>j z{1iw`|5=r1&o5}{s=FxS7uNozAxpx9rIe!RzqO5b^|m{?Q{PFP<rg<Vi#-m4WYP4e zP@{e|MR$w+@XJcN=@)M~mX^N~O3_AcYu?6;x6j_mbfyfxN_ACO`aQ2X-1dZ)jj2kR z!7{y5ZL7uRiUWq%$#S&6f8WgHs+Hm4aL3Xn^9$*Be%Im$3#I?6Aq%^270h=<RJP1Y z{I+Mds=S6o<uguL(PEhlpqZD8GBfv1OjdWUXFZg{Q7MT079OJWd4e{K%Q!g}@Aq`& z-V3Mkfn;i(zKMro><%od)_0E+isFsAPZgX48m;H^+PS5S^8J!FujQChso{n>ou2qI z4_DWm`7qlpskjtic@q)ot~E@PbhMQ!t??1{EgUX1z-ktgf#3QVV%c0ilFgR!WA?j# z<0V04e5<!V_E7%Op1KA>Ft6;|UJ_c8vg6&tLH%*{`#UpKRJYI66#>cB`Vg09@k{ri zo1qBAxY$!V*Xupbj_U7EL?&_Ebn<4voS^x3+CmC9<XK#7qrW(kmXgPt+km9=hM<4F z0NiWE4b3ejEemg5k9JgwC7*jK(+Pyacse$#Q00Jlli00>))tL>rVT~q{`snFMC~m^ zC-tD0$-ChBN#raxaAWEWHPi5T)_buLflgc}$;n!h+j6Zp-fR5SWKl4ang}cm;A#lk zbhft3s|$vSIOI8wi`<gf+XErhT!%rp)E3-VDt!xPdHKN$%zPUlizmY__&lEMtB?qC z`+m?>7?|gsmzP=u48LFA$ii}LBOM520cytb=7%>r=0|gynORwS<=QtBP|5!x<kg1f z0x&#+o$(cX<~ZYcvS@kQVrknYa;jOXr}EyDTub+mgsHm43aQ_o!n*;O+-kWF4X~!s zEXpcT`uO2#i*qkAbYwy)rX!WHL)zjv5rIk$2MfQNINi2$|Ma+broa<0JOtVum{`iZ zJ8i$NSwT!>WzcJM#n(#al9LOEZ0=Qd)oMMZtHbq;n=f;=<Hhud2Jg(*O)=Wdn6e9d z!9(EwgR6nEe8n3?i#T4(EW-l@!@P#^+T6h0KFN^3M)P9-LG$ZO&Bt+T_9&#AGp!pU z1@0-XX^Vu@cypN9XTuc=6~+k(l!KJI=U$jbI;#hmQC<9I_Uz||8}FyVixX5+Vh8?; z=x7X^FIN)hp&M#SAJ^}p>`P_4a)}zE0z$5mQ`d!~T}I-Miqfic9G5hyBn(o;URs?r z+MeWMYWG}4F@b6g65hK=eJysCVC}gpu;Oi?aa&n|ZDZvP%?2U6YpJ5b)%WNZPEt+9 zbWubLN7Fti)W8~2Uk{*F;Qm5!eHV$l8i5eRSPwRp9C;gK-sbKrethCL$MDlItCKTF zU@BE4L9<gammnXBMp0Je20HXcNB7Y8DVm%^oAZ5B0`gTSItIv+f3+)_;{U65h3+~e zgBGxs)(~U4^$_O8vsq{Kr)teTS=m!8(9#lnwTm9H=N`^EbYiH%({_vCvJf4u71(?N z3YN|wV-CLSpr&R^>5JiGhoiUr5t*sBy*lS4(77zIC)VG{qECJEC=EoI{pG2Bk4BC; zKO*6^6t#N922C7h?tQ`F(f|h3ByDrF+XE8NnSOFuzRc7jZFYWV;_t!oN!Y#fo@qUD zs!3tDv`8=)VKdDH1@B*nPFwYl_4kjN9L<k)M05}^Ugge#O|dC-V*1&vKOOp}2l`mK zLda&Sz1ESd+kr3nuY*Lfc3I}Y93{=PgcPr2$b}QFMOZfi9v#>Etnr*~nut44>53of z_H<oG+9X=8@6QL?ti$u1g;S*uJnANob^glQ0Y|SbZ}R_4)*s2CD-QbO41?+KUa4{4 z&Ui-sngs2H;UJ6i^R{hD>YGjJ$Zc4bPhuyHcs1hBN1spiB?vhmJ~%>YufI(%Zl>B$ z_NsKQ5d-SNLKk7`<O1$qNT}!p{>T59+y41tVPry()+cT#9_U@?SPVexlh$jGs__QL z{@~C&PTIgpdn9W-sbn|JjTbqGD^a}({EydqS}I7cz%fW1%S_F!4`3BPBPhoejjr(! zn)wBaeRDVC-Ht1n8vSl;PE}d!9xZAgJG*ux1r|Ny%Ej{|ENj;Xw*at2cQwIxkJ9Mx zuv)2$v>yIr%TJyrk4!Rl;~ckeA#AZeK2$bK19Izk1&-O1r$?)NbF@K@7nTGJy2y^+ zpD-P}#9r3bNUucLkR%}X7Lti~>%6DBi;>SfpPOL&eU364BZfRX=G%wY0tdpSMD#d> zaQV?`wHwN=zN@&<-cPJ+f~PQ_I?}|Hg*At`5M`=nv2n2tFvt0OlQl@m0%MU2)I)Sx zIm`7dig^e4=k;VWcUP3QyvOOGrIP&9{01PK733B~$_`s3`w|&EHC?~J^YR)73(q}h zjZ1b4XJ-2;*ZxFTBVZv1qZast$o5B16Sf$5B6u5+CL?+fZnD@L@eByuiCLji9)Xj` zX${9=Ti6kz&e2l5R$IKKPrB5>_^5Y)rx^eO1;*2sK7Xb%`#@%f)s2?cZOZKrn-VSM z2veB$jkHEt!qz7I4J=Tt`&!*#s`X91y|Mj?kr7oBkz1k7E9_-CHa8{2g{Bl1GSMjc zUgCXnR?W82eY-=Lyhh+f=&44ve8x!Stu|+~n7~l{fAr3)0;WOp2NflLs*3w_4#oJK zlOm%N$-Zv|6bpu=A^vM1FEKa+b2(7#P>bx?mj$KUip<P3UGh!hetvvbXru1yj@<dS zRGUzNL`tjER0y7rj}j#r^fW^oG=VxHa-eEUV89MFH0&i7ZoJ8cFIcwYqlvIJ{{<Fo zP~O8Fg>75Ju{94UIjz|8YdtttuEBqGybFlC#m5chmH9f|<HPev_=%^+VDX0H60JfO zaQ($&UGnYpjlt4BZ<$}0=hM(gs#(lRf#`VogFWIk$mkv^0*2_!)H;KV7iM1EmR+2c z>19{f$cc~*ZEOr$I@xbDK@XqYw?yGqb(<0^R&IAi)D#;{NTnQJdFu1!;K79<Ngcp! zR<jr9F75#F4Sw8=pRdFmsXVS;FQdP8q2B=RQ<Ux(IJ>kq1!|!&bk1-9I`Y49@J)xk zrb^?hdzATfZXI68k{mOp<$QFrexIw}HOnJ_r06Z}EZ43Po&E+!P~(HdfF$^^pJXac z_&Dp>PWgi2xm&lUiTU9^me<*j)GCh5t{!Qswhs;<G3*Tw3@NPvd`uMyH=cOc62B$J z!5v%kYIO(724x=P^a@As>jFZ~LYiXHen=?qj9$Oti;_Zbic5LUmlclRbUU{iBFwxV zUEO?;MLfr}ai8h2pHe`7p_q>Uv^ufcZK?(j5<@cDvg+Q#uE#n%D^D(m!#G@2qE+Qc z1q88ngSaV#=QlsmnsJ2-VQQt7x1_}@<o>(L#XySZ4rsioT*Gg?VQlAI?8~F!XMrhv zs=8AX^~D<|DDfe8cgBw|6R60uc{~y=1myHTNghNOCbP3!MkHGJ`_yGUtTq)z-PWRP zgdar2+A3HK)gdpQoH4AQeHHp{gW~@bAA0mI8WsVqNX8^tC{j`XSoYI@)*iUA++1b9 ztdWQ><S=H!m>(0WHsq7V5L+z{*>jjQ1tSB+;h}g-c8(fCbjd+WgVdfX@LMRs64(x} zF(q7AXD6khG1Bya%M-*6xg!{#c41?Q&8DsMb9wXkOEJ-Wq4|I$A|Bonh>=N-Esxz8 z)(;GQCqFkFAvZw($}`ohA9wU~fkr!sfCb$Dozcqy7Uc~y|B|B2>3N_B(r?fKA;S=v zyhD(W2WvhB&f5`rDas+)Qo!L?m_rimP+u|5m)P9!eQU&K7iQk@RP*YQfUV$V`?w8w zB!G-8B-dP-L|Ym@b0zUzP(j6KPTTNVqRkl(qYI-Q;%Hj47Mt&&Cacl+6Yt8T>b;16 z84p-c_n~OE@5h%o`ltE>o`TXceavBpCX|Ra^&dmDTbW2T_A!P1{a%zMEyd3du|Zzy z&Ivp_92|DM0cnDy-T-2Oc~ChTRhmNpwV|1pM|bIh)jf%2XjFZ{z?|1YNs>^bpWjhe zO=HfsIC<W)$hnIh&sGM@qrQiB40KTC(ARzaywEni5UTcgvrXd!QM~hz3K2hU=^^;F zDDQXSe(S^UiAzi_mRky^7_Qb!Uw6E|qF{0+gd(X&E^Ydxln{_ZXO=&sQI%l+1Z8aw zdE+&fPu;~0>7%&coj_4xWkXEQ5~McU`@3Lo-x{jH)=TV=xgbn$>1Gr!RG4zLgKGPu ziI0KRuF&TILd036OkVxt11{V1WkYFZ`}TQKm^UBqM1Ids>OBa^!8<DBRIai{Upko0 z`Yd(qZ@`7oxhpB}kw|HJ8HoRbA1puM%vNN+5*m_CK=5N?If#yv4qHij(0D%cdbvh@ zv_|u2CbHGuCPDD{?I#w>_y@#>v;*mcgOe_^7P4-;M6$SPR#%><H5f((!=q~L`YsJc zWid8X8?Qbw=y(QIwd<UWL!(G&ZfS;E2#Z^+PX*9cV2q|KNmin~jij@&3;y5K@{+j2 zpnp7Uv84Sb_Zf=6T=4VU8lVB4<d%s9ls*O(Fxt?tdQZPKw%037kt8+RSGa$l9dqj) zKB$`I>_|fDu=DJcL|N}i>3bS_XWjAP(L0+REE&2P8nOQReF<4AcTkn!ZbL=U(Dah} z$eyi4%C~Q@ml}^K!!o)cuXIOaBH<1W(_q*zd(h}8IL#bSHY3!volq)2?Yq9b98f8A zUw@DyB7KMbg$U?Jpa*5`Zz`F*ALR?Qf+j&x!O48ebUD|*s!*C~s5Dc_2OUzWXo)<p zr9rJ-*s3w~J@R(?uNtSk3!IwzxG1KV)AR?6)uIyQ6QCF*Gw9A>Bqc!YSX_*22W#jX z{mdt_(CPmB5PwhQsE0p#<TCBVQ`b7GF|&Zdnb5C{^xh1WLf~)$1j$#XpPT`bPa?z| ztX@{{^MGt7<^JsB^b)u4dUu^4^DMk*f1t5rP@>ajj)u#|taKJ>=~It<+D9hF*$GH{ zSI=Xs`$|Ta3{E=Pv&&%`7tC`;Jka_nJyRvU52c;PHy;l*Vs<vo&eh}wuD-9nTziq; zFmBA?=y*Fdyy`k<!(U-ycJl;7^S&W~X(JR9bH%W<pLN6;AM<mXs;ubF23Duurh8+@ zMi~VPgzdJGPBhiwu#!#wI2qKm4*<xwn}9o+M#2*!eb+cT$nMQ9?*!k{@6NJ_4dn8) zjWg(RKuqa`3ShH;$NM1d{i`;YFDu!o4>baWmIc5NXbrn}ovqLM(K(;NU7sy{7e$0A z^2~H?Mh5o8P}9DIth{+CQ+f90KF}pfqSNWE;!%U1iKzt;qybvTgVl8pR)4wIj#u`y ziH7NY(|aMUOKyMl411wMu8vn0@0f<Uh3|oA2Y(8EYnF?|DlWNT=UCUIL`Hq6uRw&K z7YVohI6*nJuXi-HJqzrgXEU&lnJn9W<^mbe`FuH{)1L=E#=$FCImm7O)_UGov!_vM z)Tc`h*FTO6CL3xL(>a#yjOes*7CPOGKl=hujyfQnK73{p*)dP^2`Xy+M)>p|jgl?_ zr+>_|_lc2=qmPa`t|Dil0%4mPveEp$#cg6?4JB3w(jI6Z5&0*b3-ZgS>L-PH@GrdW zm&}`@{0EU@v&v4DDK?yFx~O9~`1Jt)31s(T>oY0S!F$DXC4FPb^<<G2==Ww$jf-x0 z_#8*-8%Ya49?%D1P#6s-%xK3BVWdN60N5176@X3()pB2o&v#acRFK9GKn%104Tw18 z`Xb5c1gMKIQAg@AkQPvYFo2rSH@#zjkhwb=xQL$*@Qz6M(odkf$q%-8rON_$S~eyF zrK4c-SR{Pa{<1zXRr7*00&t$GY9M`e@5hn|Hc-7hdp}6;r}!T%|163761e}wIiO&^ zF<#_8b#dNfP2&z>DH#i&=YJ!q=}G0SZVvXy8uXhk*tw`7+yCNK5M<R1I9i(Y!N<P= z+MGFuVsnXeE;alDwA9L$JpK#)^S~5-h!7FoHB7{(y`^@YPa;YOEyU%5m`sW2T<JK7 zU20%DM95##-||}&K|3fW`hr%u#rW%=Pk_>zFhI7297ilnvtXA@sysVW6~DDuL6Mq? zr1nEpS>PnxiYD$RlxX8HEu&yl&Re0*#`a6+Nz(1VF)sWwZ*WC|dDG!W;1Jxg;J9A; z7+I(8H5cz8dIJ@)_nqyZMVf2Zr}z?oV|<VGlVQhM)QKGlc?HpmgkA41751P<jMPVV zgfNI7^OiYW1=9Rq1-j_UbnVu6z~kePaJ<E@^IbKdpVZI~en;g@@Z&eq(&Kb+-#@a6 z+6T?aimb95{DmlN`UZmyE`J)nW5v2RYuWLuW<IfF?=i7^tC*!SZpgbP<q9iwGwtu{ z6TEW{DyvEScTA5+1_~q+e>aZR!eL~;krJ|%ff4Dpt!4#sGN0;`$hT0}i?XjyD!Z93 zs}2So-K#<JSVG|U7+34hf~j%|$ILYp*?u|fXoXL{Z%4G%_#LX`(a11h?^1Dr(pIFS z2ciOG^@3F4d`}^(aF`1~LZ*uVVBsNX%LJ~RuxHZ8db+_!e3c(325}x^9T(c%c{<8- z3;G5bAgeb;r*4tzFg|6+#T{I8Aw1{0u(;7tuNXASTj!VxG?(N(IssZy!amWu#wR|d z-7kr3yK~dvg%iAJzI1|f?nQVNH>bhkinUqgMj$xVtOKUccYYg=w6(|SC(=B1D?vYK z^J45cIGy2ORhB0bot7F-D6S~E;bHeB(}jP5nLX{M104D+2Vk95&)+I7*n@xWm4v&W zCH3b>A80W}hVB58M8P>n@Ho>ZEJfZtfpwuV2d%?<A<hDCVhe=g(3ZiJuF4bRdq1gH z#W=c(r;AJc#Iu8Xr$RCoqC|dQ=uE<d54R&h;X^aJqgXdYL`ovn_wB3*xSYQf3iRtd zR?R`K6RZ<lGsm*;$kEdJM`&!`xyv)HNb@l|$A?36V$u5M<Yn4Qy={G#%Pem}cZL`T zz~ag{Atmx^&p=b-<0Rd*KW>NehIe|GxoOz{Q$KS<Cj4WY!M^(EL<dT;Xy}#SuD3ZR zD<$|2n4TNdS$4ak|1H^vF~<Gm><6&-+G=LXN=8i1qk!iE3MjcS{Fouv+`TQ|-m-ZO zguHXAf<n;U)y2ZtxYFq&Ygpa1_w)O3)R4hQow$SuL5ZA|)Q%y|1=M85uCfdBU2e5B zUIAYIB40=41gb{kD%lgdA_Lo)q#vI9sx#yNr+>F2Iw5HL+g`o-0iofWqy#-Ge9({9 zQpS8ZEn~+7q0%aJbihW_Ufhsjdptkd`Xi_8Q|;i7Jr~rE(LPxPMLCI4NjZtV=w6!W zRP-vxihsuv-_M-)&G8K=96C*IoM5DVorC+&Z4;f!6!q4!QyX{i9s-q24j(`xkAb!! z6r4%wlF|F<ZAw|nd?EhHS;3x?l42Y|=Wa?w*?zI-)CAv9fuk{gLD`(5lln<Ey!VXH z>_xChG0TD8MeYFy@gZ^0DpXme*Oa2sYzr)%Lal?TF53ZUI3m)UW;=~z$$@WQ@MR#; zPvy-|Kyhcll^1<Wp}WwlifUcYg!bZ{2~1lg+V7{^lWtkFuUqWemL(?Sg7Js1Z26-O zH4ZGvAa_ojus~%R`X$~Ya6X?IzPevku|L!WYc=HvUzKng`RhsFywXoVSzoQTB~io) z*TXDX(1)!tG?Z39|6<Q}krCVrwD^${v<EyJDEZnLfX$xcG98DZ_)y`t(FzR8um!xi zDRR1YWAV<iY~a|E`!f72=%GtMx+$dYKOFdg`YW83J@>8dc=xe%&FB9oo83$!NsDMN z)mHPRo@Qj$(AE}<;-gU+gd!7AR}jkPibZleckiWRfZs>vuR05M&6BT1hVQQ_0()61 zuc;O+FfZrFo|1>x73LiyaMbN$YH88&wU)ntev<bFf!d@hcD)M<89JyH92cC0CAWm4 z|5FS{RQReWh6eihuUXxnb8en?%SR<I<(Z%k&OYZQ&Ir}t;`QzDvyv3&Wrt)+4O`1v zKaHz9nh2(qPTH-eI~<^W_hX(tQYcs3P1jM=_)uG#0b~|quCJSwc|pA$ToTb7Lb(`^ z@Any+prUuAe5!kObJ1FSGmt3>LGP92=qEG*Y=bJ@1#dNy7%YY8RJAO%*LeJ9ZGiRb zx;bxv?FVEKM|5~S)~%0p14XT*p3JPT7G-#*Tpf&%(~_f^ta<u@=j&f1^rvW|&uhs? zQ>);uygg_<7zpbw_~wYD-HI%I+m^|J>aW3-ITgO>V!^|UZnXWT=f=EEwl6^m+P=#x z<DNA#H^LMF>81cZICegoJFKh2f6ao_7Mqfv&8)Y<Z$OUHot*CH-kbV5b1RD+xui=O zp`ml#b^NKR$rs-m<1=1De}=4=Yb*E8K*AW_^z79?PxOspUu{CUhU10?aew+_id}tS z#;^c<x9)$px<NgdA7#Q)V-}MY43&JgunqOwTN8pc2&d~~hIt!PrU7zuhm??!U2NZ= zr_1vI#)B4BFy=3m+hL2uZ@vEw4yt_odsoaSWCYGl%dNW_yqu*hFEqLyXl2spU~C(F z*GWxn$&q#|jP^adWpsEi&?yhR2Yc-+8bISza5YeEp&tdduOC)DF%`KoZ8oX?*j3Nv zUR~kdsF=X-DgPcWXunLBvp_J_*l)5PK-45aleD#DC&msg2S@0gmCxXYDL-h{e!>p3 zes1$muX_M~_^W07T9pm7fA0HV!X32O-e%CIMe|xieRk`)?89^38h&~hvLY}l`dPZ; zeN$JyQ<bGSaVR!#GPS>#O`h41I*<oTz;Uh4)#su(M(S<d7ey?5*7c5#2Pt4hm6BNI zT%kre1&?Dk8{FF<*UhNEx;Y6i@aLso;tkiIAQN^b$<V&w5IUD$RdQ#CRs5S_Ewx`f z!_^U+Yx8N=MbrIxBf3Krqd4j<MX0Hi)bjSUVTbJ}iTkOZY~oyMYy}qBR8PCLKF9y{ z0)F~ZoMUQ!AplNR=X1dMLBZFZfFedeZc()I=XoG?SEZX@NrCC`!(l=OU5to?!lPa0 zpFmej>|h2g8dL9y%oF*QbNW9Wk6`E@nV_BB{W0jjb>lzr_YD*XdPm0#3_ctnbRrk0 zf?VJYu#J3CF-X|fL~}iFd4;3@sb4xZ;uE{^xER1I#v~UL0~N%?mOi5ES$FJ1m6XXL z(8JipT{LPw!@ft?#$L$e2y`S<l>k1@0tMT&-YQ!HaczpqMQ`L2=1}o7g%H=-kml3p zRIOy2sij6;qp?u-m10@fJ5Nu4K=N3|RG(GQ-}Sf`YkS3gL%v-<`{|XKoOfEHo?Q<# z@9AVao&TkoAT{Vk7W2b*?}h{=LL%tpxo}CNi`rMOrJE9m$E_V4FdI{~-jxSi$9kSG zYVa2R>q7=%%h^PD`W^AeA3C(g{G76Th%2_;9pf>9pfz_zWC+$CyO;kltA~&K&z+IP z%d}&rX#92ujBUHeKmKGI{7dfb2LGcsO-tT5{m!AF_aRIsClUR=3rSs;ZiV+OEoVf& z)~E(;ADq2pD1T$~!cxJeEV#9|*8pmPf?b|}c=1`8IQb6okSp$<V6ov!d&c|jI&X;b zf#STu6W^cZg0q<LH`hO`I*v@oI)0{pWp_R@v33aWJbrjI-Kc$pj#~Oc(`7E76?Ej7 z8KiN2p{vcnHxmc9<S^95ud6Wy=9m7)EWJpimR@IJBP!>%DwIiW?q62mc;5JNkTnnT zCv?-10p(0K+h+RD8|kQY2e3HR^CaY{R8=;xUTwr#tq#9&38C7ucK=&?8!y)T_zmR= z;ov)_1w+kSc2DBdR+G>uoWgm5GuX&m$<IdyL<PvK=#vZ}MHp`|?MpQ#;*@PF3QuE7 zz(&Cdg@Ggf4#tBmIqYH;u;1VMiB;RvL;_8$TQ9J|%wQ58ZE8G^=o`wf5g1YskGofJ zM&y*m#ym6hLz3Dfki2Pe^fjlS+8*m&k)rWGf)Uq0;I{0({>i-&*_;vCP@$zVtbZT_ zhJyaSt^6+bJffmAS+fn}9{m~i#@ETSpz}F$ID$vz#KY<U{SzG*e^$5Y9Xs&zL>Pbm z@@$4h;~M@M#Lw9|N<nI+RvJ|;{Q|yMN2+mYvL9L(41B)!O5<Vq>CXv!XT2f?ju;d) z9;qaC>ltikk>)(Z0x}H*U45g*B~Yy576OCccXf!rtZ{85S-ng@8iqT{^0_r&FWZyf zwlitOIp%!m=OB04w?%^BCe~1Tj209l7$|x>wi~Y|WE<Re_HuA!`%{zUH(nF%F5tCN z<7Z}Dt<m&xBPFl!WRvbVua)lc>XAj~4~#8L0yVK%Y8TrP;L*Fg^xRT%yzqUuZIrZE z_Ig5duZ_E9NLnPgE4>PbkdjhOm4+`TgdItw3wjj=Km{;E@#?n~ldrDkTxdE~nQTUO zUZj_!M4#H(?JQjWS?)5hfx%Z7lFi0dg(P2eXmP+CMdziKs;9eL3)V-KMxw5Nn7I3- zR!ul#eyt)*tXQR_Ii++kqoz;B_THJabx)|ujWD2ALut9>@C<*4W^>H$Q~Z|yM1aK; z233mVJXa%|cE6sjYUbgF&6|(6>{Re46gW9O^-hqQcK_>02YwZU1Dh-9{rb9zT5zb@ z!mIt_&vr;`VjU~>sn>lM`Iu>?<<n`pnn|Xenk>#9fn`?{aGR3JeNVD`<>ka54B%nP z6(g>>!l&MqjBQ<7G$CJmbUg8gp(P2^pQpgmZJUq6tmh^4qVp6T%q$#=JY9?C#ZJcw zaBgeT8r$-|Jn^<jk$v@@_jE0*&&7PUr3Jn>mVaF6%0-KFEQ6RJ=wB~@m%5hwGI~Yh zSh~RP!Hh_cc{OjNte+WD&5}m0eP}wVX^9L9o+R~oL9coRpkbvaxf(wnhn{v4&=!~S zX?d03Bhklp<886gixva5(W1`bpz*P|G3}XWiYRIC`~!1`aT(h{a|Gq>)zr1s;^tTK z$!5dlZ3dq8zqV>li<y?zYbBLKyylVn4Hbs7=N()z+wvpm?MshG=r>FI@%W1ULB0eh z*SEzAGqzDIl~&1K*dn{-+D9skZ5Myq07puUJ)t^$QjF!#`~5+(-p9v6aIO(QIOE<? zP_^c?;zI8qA*OvN=+;{X_TEO{J2N7Lkp{^>L-RsEZc5YoyiG#(QYe74_!CX?<IlpE zAB0zrQ@YLfhs!rH46={0=jD~Gb5u`Wf@FIoB}Q9j82xQha~^nA1X(Pc`LLc^gc$>O zW~w<<IORsScB;CdRI|*Y@TZpr@80m?Er!sZA~pO;bH_u!(r07#G?A0zkNhn_AcjU8 zdRfzSm65^nNVsISgFow^(*C21_YF`J74qHdUeXFnFN22jJkPe&Z${p@*B=Onz4>Zz zLJ@|1!Bi>=j0|cay-)}}RN8fE2`w$rnh5LZ&f*nkkCNgGSub1%L53~5ueG$Ui9I5r zFxjlfl6|wL)BL=-4N7@TB+E3}ure;!l&#~bKO6Kc0kh<x-vmSgTxn~AZB_DfMHcyJ zs(F9e_}<HfkWcQ4aMN_7OKDqK@G$R;CvZxtTvF@P6+=?;ghFSRD2SnFC{k`euP`Bd z{kvziA}LIsegN4JL>E^kMP^sIx%_UUennYg<ixu~2Zo}33-???ckGBQOrfDNBxu-& zd{Xn$u8CTxyWR=sx4<!Xs?{yQm4G1j_s=_=Npr{CbFDb~UGFZxyGtFKQ(?MLyksLd zaJt^u0)IAsxX=0%lg70)F@5)Bce9M=1t+hZMDWg(3;It~JY{Klx<8hHz^oT3BE~RG zm)bIDse=sd8H&Q!F1)wNGw~H`yfuGxw0-Q$0AgP4n#gp5<_IZ}ev~A$0%7JtBJ^7T zs@Ux?TP+rHyxE15^eq#i4q2@WF&lYxkMBXJQKdn*y)OTIvk%IiI|a`R=0}(4f+cMk zHhJSQLa1hkcfIX$fzA|!yt6*+R>oYM{whzN@xPz^mM+YvD<$Y3MNwRSk(ba-Ku@r( z>eJ$ZGW1aW?|W1&3yi_`XU0G%maJYwT)Irxve9E$^}I^ILp*^uF0U~6M05cn-_0jh zBe>yLMubxdN?!cfLXFR@s~8du&<5U-AFWQj>NtIDKwR7&OX$W|^j@7pE(HV*KXIkD zO7OW=A{lotNMEHPXB{M(KeOP2sMtFqB5CEa*#3He&!AZ#Yl3+8CP&Y+VqQ17+o2~I zmir7JPs#Xze9~RItKC?B#J=6RBsKi{hp?A~z8<{*sgPJkcS~vWkuv_t=fl791*~J# zgj4kWjX6e)?_B4YnOMA)KYd&wLcLJhzl5(y^XhWycyerf@)RvXwW9Un&o<8Os_<nL z-d?!N`U`VH@9?@W;qG@@JOD0t|9H$i`~9}sm{H50cXOYq=5S#x*4}sa(~P?vrY7zH zYjv2}1WT#9CR)53l*1k<zR7G}Pe+ypR2?@GVS_Hb1X<x1*JnG?Shw%U2{V(01ryEL zJcSALna4{{vC6XY)5Y;ArlA%wratpaH5C!{28UZu>t)P(Too!U@K-%Iylp3xZ;3m_ zjhr1PFnp8BDt%E(Y4l*^WaEpKBBXI+T9og>^fbdxY5UTik_m7WP5$>O8Tp^@ew7AD ziR+YL_zi?5WV*2}UEVoAS~3Nfd}XP_e+lcHdIiyy#^_UX`3iC2%M9`B2v)qR+w;8j z#&ss_4OHqN^Oj=Kb#Vyddh-u$oUXhw@`}Sraiw2fwD-8r`pq9N)AB^q2_0EmACZwV z&7sZoW*A(9S|G1c@|0b%-_5vtPQq}@xq<1L?_AKX|J3@hJOC1mVsQx^WisC_S1Iy$ zDOanXMkhP2ihaEdRy%DQWVM2q3F19<VsgfSe9a$YDQO%a@f3S$4p(14>>=6bZ^VXB zHR-Zdf7g5Y3O}Ft5yShtH9{`@?~gdwKVv&r;|;nRZC{f&ZP{JR?yc7OfDw2AOzIuS z-=IMd_bK!7D(!rA*1%}SfT!datk+6XK(OOHLAXcn3dW5!raPeit1P@U2Ri3wZfjL` zP4h>F{%=2`K-TeREJg83(9LSuCQoSZiNZ;PiJ-GtT%CbsAwd!{A&)Il6N0hLyV#xh zyBmX6+)cLKCZ-VepKI(<9`*}`;daZ1#<csX6|bY!xK@7!+GtX(`NhY3X#e@nC7c<- zsBz7^#?u}wRB4N(DnVxq!^Ude?p=SAkK{KGE*d|2=Qx_0bmQGU!?Tq?y&4RYZK+Kp zs$P9@GI{WMUVQkpDX#N1G*W&i?SZ1+q)p)$Fbm%U&(CQy0U>9fq;~GgKu4XK$FAqo zqBPm_jX$NJCbScNJ(koc>kJ91usJk_QANFYXm=(rwh5rI<T1KEz8mxw#wTtspQp`n zm-B8Iop_uqDB{GXE0JKSvNc3A@)m{>?XwPA5nSyxnGh<KQiMq+s4qTf+^gu^lAd_1 z5cBCU52WtTKi)2q{?g8wP{Nh<H$JyS$8w{r<Svg{wNNb4Ox!xMyQMgaos<+~kD9bC zfQ>v(HGLcu?wzJ_IK(I>xyr1ls5JS!-L1zqw|aO+yo=^mX??*)V)dO4w`%THncVJb z<#EeouMsDQ$L8)K#=Ux>ZhfoJ&9|S^qHZ@-b{p}T@gkDDmST@fyYaTv#GEUZ9@<v4 z`(I9f&bq!+3w8?QfA5j|LBRLMjQP`zk%FGJH+5B`8;?#-kRWH!rQY>;Rf$B2?Zlw_ zD)6%l@1&>4a;$2fwXJz;Q7^_DdHEf^jEXLo9ZXonb|2tPBUe7W(~JkN{z7lxJvu%< z&Xb2e+qGW2KZSXo6D~)OP)+hBy>j~SX4`>tzY(W&N7*Y2`&1cDPL@tjXDhlLiCTR! z2PLy_>Q=f@tLN@h)PDA<OV!GF_Nh_MiXoq1tr64VnP1G(HELlFOOZ&nY~AWUHSJ|O z-+%AEht3!Q{W^-u$&}Fb^3sOy5fvsSPHj<}N-pS#Cja7LpBaZ*jsH@8r(4mnj+T3$ z$nT?M?o;f_Bai=bnfFctLC1>*(*DJ`bikPAh}e_RJMOYzQZ$C3o7P$D*b*bo9EN6= zyH6^{SbQSSzOMYJ>tILiquJ?Td*-=58Iy+W@{P*i(W8~&^M3UR0q#8P)cB<HcK=VC zdW}5?OzYgFjtXBw<$>cP^NsP^0_xM>ZhPQ%7d!}CROZ{$v8gE?KVo|xo9R2vd*ID` zeZf0KSENX(5PSt+wBik_lzur=m>~ZWpLpz^+?gJu#q+8uYtCSztv8lMAcg|uolnsh zy!Dfys<!8)kIVB%>f5|!TgI!4RR&5)8K=kd+5Y4clW|jt+BMgP;f$%kw*DDiK9>+Q zdZlwEfco=9ty}VUf2Lk_Vr-z>{@c<RKSr2YqCkeKzytE}+n#vRJ8Qy!|4IO9P3qwS zXDoO)FQ0}FuhHfqY^~pXoql_|<<ku%0UJe8ypcm~m^I~#LH$1)Zl{{4Z+!I}e1a;S zv~$Z@)U1pznqY6WIQ%++=q^)qZR?BcsIIW=!5yWTDy7MB2QKY))@`YgA+9bd-0<!( ziqoZ9HUs)Lq_pujL6atbD0jI(0>uXSgN4eia~4n8OEsDKD*{70H9wuLT#ejoNO|E@ zVPY0N0*&RGmzq`u{5ZO!B-1RJ4{9SykN&1tFbs)8d>vdP&!Z7}v1v^gEhxB!_sYwG zy!hUjNs?h*0W>L(atnEu&1&#DX}zKDe=+vnfmDC-|M-nU2`!_WQM^kLl9eqbEu-vB zX0DN)O;*WF_AD!|>sr_5l0tUIwJ$PmT$_8Z?R&23^ZR_ifBnuM+}C}rbDrlp9?x;k zJzfQFdiZbetLt3X&XnuQu3R6G6uRqLs<^eQ(09u7e&VEC%t_y-xTS=<yb*5Un-UaY zCiRcBFZq=`<*RPd?X{s-_XZ~2yx9e&G=C=Z&$z%@(iTf9$l0s5F)OSw_z&8J_vcRf z##aWS^^_(h9&>Q6-;apb`L&)hTHi2ls24j8QeF_%H($v55;VDI*Mn9EwU@m(0UD*8 zup!Q{Iobe22qT^^$KP5?O6}HjO*CCZWDWuoWB{z>Lzg1k?q3+-XMX%H)jlG*V!#yL z=WkzJhfk_qRkp*S-LkoJ#cSPOmTkKEKBXt<pOk8DT)xrkUTZ*KZgfhjIcORCzq}OC z1><kAs#|y-VD&0ArV7`;OcF{kf%O=lTD$=fg3Vt_0caY3W)9V9q4MH=gnO%$J?ahn zZP%O8wF2znm6}Y+;^z6BhUcFAw=~eB)YVX>J|<PKJExS!^16Ii#i(_DZ<@I}3+=0} zY#IiKa&fAeH)lEcxBR|?xgul-P3~hsrdF|R=>uyg`B!ov7Xr*VOPZt>iOrd3aZX&e z@$Cey*&#>wDn0Y!PyP#YPbt5FC<>4f+Z1O{Mx;_-p+_N?s%z=Dv#u4d7Zvq4uSLS6 zx5ZRwq?G84oWzY>fXGS(x0#<t><z4n#S2=u6m4Ao2N1}!z||F4`<-dCx;IouO(U6K z+rajXHZrc$wdQspnz!uhAZ|=E!P-pLWRr?6d_N3eB){H9<O^US$W13yk?Yda*@9B< z5~}=g3;S_|%mdq>J(w_aWQwiGF<aAezF6QQ1$UF?x9tXny2Z{N0Pgz8O^&@CHR|&b zIdl)Ff3{+ruONr@+&)gvYsTYlN0>|UPuJQE+O0X+Bni4!buxmhzaKgDf9?Z}dHx@Z zlD|>CX7w+!2jN@?As<SCrm}Y^@ze>YIwOzWLY!2v#E{Pofb^uj*PE-}i-!vy&Ykq{ z2I5t9WWSFdvc{e$i|CC9pFf_|l_UG;f0|t4(T)-11J#of0!H}BaCVdNy7)qkO)wl) z$p7?&=k7)^(acE2h}oV<Ghgc{&+nX?cQ(3?kt~Q8$Vrx?=2ud&bD-o2ZwXT(N4a){ z-`+P#ts3G%d*XHnTL${QVTAo;2^}8@WIZ<&1^NgY%jdLNNLyd#`@?0S?v>pTzQgTi z*~7tld>yK`Ge}L^!lvcRv&=(>*}B7h4xZVxV-S`b|N2Flq+pi!_9jy_Tfs@yG<Jhc zlnZA`L<R7jKJxw>=V_4;0{K0v`Tvv_m2k2wb1Bg4Kz}j*?RtY>-CVaq@%<0pM>F{G zDAY&3;w%UZrE->Z7ks~sAv=9?H~uND%0_F-x(_1c30DpM_iVc%i-YnHqDQ%h$7laO z+z()TXO2lO&gY7ZWJ>uxzfXqapxx?c+8B_)kSQUT_fMa(JRX%xXO0HFalCl6Pfx~2 z^);}60J)8wiF_dOzg%G{$OC!cd+~Ehvc+S;InmujWpFIOnarvp2I7*MSXH3O{-om} zkcL-!Pid_X6o$;e*(iDd0k$HzxZO$rEn>}T=AENK2k;Lx@5jAu)oppAr(mWf1$_zq zly?lGD)^5JCo?n}%Io~ZKqSWlLj$P=*6u3kXT@77+_{5Lce|S4-@q35XCH@L_Wef_ zeIVK4oFyvv7w(%;!;V9i0bJMb%lCK}dDRgH195Bl`?OX^ql4JP?wduvy$PaImz1ub z&TxFW`^$je4Lz1EvdJH5+U{^@fY@=-B#f;1)=j%0m<%t0aWK7#0Q(%BrZE2V2nL`~ z?EwhSf9s`oKMjOoLx2>DVraiSHS{;X8GWGwa)&+KhMyD!LIieGq&eXAHM)jT;X+tj z3Pg56F^gZ+Pjbp0w9DbIg+F^9^PONVz6$&oi#mvLl+fN%4`k@zKCpZFIHnc{pAiLc z3*?{fZ@tVOUI1R|RK{5LRv74ab6vKM>SL{%U{dVAc56hap<a~#2+Y2i=&*>0)q6T? ztL7)JqXG2tTvlvH*D9uPfR%eL&6%E!zokkVAh`9T_$ug3LwYRqAheZpocRv$TBBWi zAbYp{mvV$d@UUb+(9qYyzslW;6iD3zu5C`K-S1n80N7>iJ4%pady5nJ)0s<7ADm4k zMqcE?+?U3<669DQep3H<ZuQFl;~oT%-2-jejMb--M2~n{yy1Ar`+2^#vj-zfAVd-V zlE=U9t8V)afTthw&J6{kCB4gEU<AM07cDv>uJR8)($WAN?%2TIKqe#vBJ+}lHS&Sx z2=VyAW8nS6M($BwuVv$0hqaj6pIshUVrsT48j-1~owNDA*eo%D&>d14s>O1BL^Zom zl|d;a;Su|eHR%O<8bEpZ{tvM~44>B?y=yPX_h|yKO!vYd^jvA0+`+ueSPqX7ni+4y zT)<miSB**nu&c0qM6@L{`U>I$@b#5TsgVkBuk=+G<$z(va&K2LFjeCbx7-Tzs$I<A z=v!Wg?=m3Ey%E!PZtAQ^)Dj8*1k51*Icn^e726TZp7^8l<RBJ@Mu^*9KT`I?@}%^e zJSc)pC=BWRyCwOpf*KUmP8RSbifp+Aqk~IBE3PP^Y-9NL*u1)CD`)w;b;d>>)|{y6 ziV_`9Xac_ftVN^=H}VzOxGT_)9ODJe&#yx!v;8SK-e-|q=U<Uf_om{)s9}~|)s5`O zlfq<lHAd_kfDFSpOe$V&M=ft8`>!zd<WRWRv_FAQ|D@RkWhqgL{}iV9?SY0-*1M}( z9qf&}9WvRS<oF?q>Z{h{D@8BgjTw*JpdMEn{K5O1a1P^QkhtoWTcuLNU3N|)eGp)q ze^2>Te4>$8;eOL(caroQ!dh5fVV_)O-*FAdR|3~Yofhm8>bkt~`8_+wlL}2yNAN2Z zkstEo%t6TtsIWe96u1LpJ5vJ0ixDmP;+<LD+X7+FkNiThjqf`K;!2j~8v7HCs=si& zyBc}*19Y#jd;01ak4IlntsP@ii~*6U>v7Vm8|4&uS`c{)GjfaK{=YD!JfFq5e^0mw zV?&=lm7&<Vc3b&pmRmIgfuGqNGbOgFSour8%~r(;Bhto+lLqE<j1PlX-JIx2V3;NU zw6p5vKfuy>+<!H}sK|;)<BPV^EsG4C?ScW_%FU``Udp`^WeONdzcjtbAmruXq8GNL zoz;{9_J3nLP2|4kNw9y|b^d=eggj2-+cTJP<lwq^Pz_YksI5jNT#Dy)U4h6aB#L9j zBYx5auF0J2-4Y^*v=#L{r{~;pZ*H5uq8Pl*n+zHWuaZ`^0%m~vEt!~>*(5M_HC+4` z$0ZX)?gx+ms#|=!6TE}#%dB1O_h730i*P&CZ6FNQ;W2i|7YHg>O#xZ5;y(GYPeZg@ zWYEIi7^q{>q!WK^GcatAKdld{cUYV<)3Q7pSbd_637%ih)hS4<LYz4}Sl-1iT3J>Y zcM~2Dyn<u@vsdkP@$7!0I8d{<VoUiV;)Pl4ggx;)C;jxETI~j&^yEWa%dqVz&vpb# zbah)sdSc0AZu<do{RAY#Ic#BtH1Y<N2Y!8j^}~)YHa@iV9+^oi$U}lmUIT)BA^JPN zz*4v(m!vkRWm3%>q9n&FL6iF-ctzkYU<yA<zKp*>41AsO^nW@=zUcqMJmARh_W$g< z3yvV>Z^-ebf3594qy2vXq1+fX8dnwI)Vps+Z%;v?dxUXxr2brGOy2ka!tw}qf5riO zY{r-xE%*2KF*&kTyY)e{WT*9~4bz!FUswA7UvD`64?2<0emwclh>?%}Um*C;oRZIF zJXK$NKmpwQS{1%My+l<>agoUV7Q-kpmHKZr;Cphr3?pxR0lDCR&+_ojop(V(9MLah z=GMypoQ1SP$*-0>YXwuGPyAN!gVtT|?-{djau+jb^q1}8`<UtJmCY>f-M7wfUc>ym z6(keEt<hGn3E4Ym>3l_w|8aaEel|yx4m*RBLAOYJa70wVR$*w{4DNnqi*Dn;cmF|e zCq&&AsAtt^4>gzTU52A*VOygf#MnlpNdLeqv6y$L81s1pqsP)TfECEiuT4{99)NTZ zvw-f^uVBmrJ}qZ26HT=2@IwM_6V=YEc%2xo^|>GMUY)8<M&7>-zuKqSu$Sb5j*^>S z+mY6ZvV^u_#c<tT8XK<qGHD*dPZOedc9!Scy{H?Qcxf=!zr>V9+s)%MfFzNd9J#O+ zB-+o@nV>pLwe;r7iTlglZi^hJ{b2dc+4+8>BQa?){f~{j?;tZ7TXrrVZAA@k<e@$y zQS0p!=tK$~Z||uNMJjaKaM3MWNP(dT-bih*Z=+y!NdC+p<poivCr`a!l+|kfu>!4C zxJLDEWL=c?T1poRTc|z>k43*A9<vj_%}?->kT~cXL`&NsP2S7MmR{ksPqS7IYD{eY z3+q)qju=J$#ZnzUt8p=zJ6X+l$ECpZ&=_*_S}mc5xhS}1=N0W6RCZZ#KUCgQh=V*( z(6UX0SI&bW->K!X7D5HOW->Mq*DOSCc34LkYBao<b4NrjfZ9)T%U~rJ2}1M%`V-;2 z-7<?}0}4q1E}Eh_zHm@&XM)sVE6}K@VL1FYC{rte9k1Y5+BX<|g6C4({q5X{>}BdN z^Zm;*f3WH5=PN5rAi!5!&wmsscFjG8l&Q`4A>aXjkE+waO>C+!mm`h_k#lN@7t*C} zUNGo6ZB~k${5MtepHBdF@XDM5YtHG21-Z4az@2my<i#o7n~cZq4E8tKA`KAz2Df*+ zdm}!XAf;CaoW`tBE4?-KGtdL;)m@HV^m5I@KV9<j$bCwq@prO3(ReuV=}_dRA0iJL z@8E@?DCdxcIhqX#o;MhgKEL-@-eQkp(^(2MtP$lzvkW=S0R5UoI@&&V`x9Nq(SHah zXMV&_7td0JaF4d>k8^1^nZDPA)M(IKT8sa!;K;bGz9s{rUdh^=Is%+fKV9FrQjT}6 z(6f1{@k~Yv0inBsUOktGbjI<s+ARlH5a})glR)l;w@_5|f%Sjh10in~?zfoO;Fg{D zcA&*3PLPpe<xI4=!maocFt1N6+~_n9M3udbAO5wTU;zu60lk1F;#DHxEe*PcxH(gG zPwLI##mBQLw4cI$$8rhhhOW-#S?Ju^i0(%ye@VUBcdavX;V4rD@aZkGX)`<X<Uf(s zvEN@d$1QmblR-qVDy05~Mf!wA<Z3*z+dYR7eI917jPi}^H*BCKZ)I}SPLr*;A9ehs zRzR06XUSFeaMr>sm(n1#OGG@4FRc}6Dn0ASVFOoB29ecM2svzdyzWUSuc9ywz^bD> z4hR}xVUHRxBXe~WkVz^vLd_u4febI_`;)$8`}^nY1y#VkerG{XXS~O}@;vtn3(7RR zT?7A466B8vF$%;z#3aXcr;EVW5Wq_)>>d2BJ-<FS^_ZT#+akGTB#_g>JV_^gQEe{K zIw1m@)-{&gJVzUKkxy@u)gjL~{rQ7l%s;!Lx=xl)#`eYSnvbg$TS|b8>AG7Lz_$15 z9rEM~ux^TwvfaEN<tQbIZMoowwamzaKk%7Ik&UTRll={2#d{Eo_jV%pjpEzKm+nPi zJbOKzlH)JQIxSUt>5oVdbDOI%qq8tqiJS;qTnZ9fT4-86wtQoB_piuJPFP`1K~&!X z?{9f+x3Y@h5{S;mE$hW^CzVpg-=!G!>JuNnrz!$;i-^XwW3^*b;Kh<xb6h3sSj!o3 z*^Y!IW+sTgTVcI~V!PV@h!PM8<<YRXf%q~-+b8Y%#7X-;iJ34Sv{%))vik%N&VU97 zD+EkF)u@3sS0hZP`>EGUID;zx-k$LRI9=`=1K(nxVA)Z5e!=Z1&C=z2yPdz?^5pnf zc~`w}060+)c!^&Nx|{=}WXsxdJ1l0N>5LIDcZn#?cE}<2&r_(-Jw#n~?5VPrw50Pv zgzDD$?(0Unpwo7x3XF%U8TOra;g^C9+OZP4kv~02=P=%6o%tdgIt{Gl(QgER!_^0n zupV!bwHem)g<E*ZlX7USv~BBOkCYrRUP3$LO^j$x_X}huH!vga8|aja>0T-D8|1a& z!z>tCwwuz)AnLpkOh3Bz-|Y7mOBAxkGp-!s8->akH|J?rDhp%kdMgmpiPiNYVsz&F z%cWAiq`z`+4B^W-%L6zzewCT#KH8p`w8AxW_hxj#;J#01YxRmfH(r0IRv!Ced{>Lr zHcFD8gF`bl8Gle?X9_~f^NVAVB(grxs5DvWOkVjn*>aGuGl@Nq^@cIUg>uF_`+ZMo zQpE5b&=u2(iCzojIl?KArN$z5Uql7``tooU&Q7o8pnpvG3@Whru&~r|&^CP0zo6@G z_k5+J&1%&x(i~s^5!C>tVk4M(X!=CsS4melr1)%)xsBZR4$ri%@A8^BLlM%dv#-Y_ zrqM{Bx^K#Jvn*dL)$^F-y(wT{8HVAaY~uo29Lin$_5qHXRk|A(xiXWlVf_=SyDL<m z8uO_NG*2K8@}~9t;X-2ru=%wSDvuwFg;#7dnud}qQ~|}Vrz|1u5=;-IX(22ZL$oH) z@6xLPXf&bmI~$6;mZtxb*k87LAeK2{&~%FOqU|o2Ksqmu3bx9JXk`7x{bl+%0b!WU z0J_uMQH8OSeL;dm;i`FP?Kdw5=@Rpdg?DwHG81`?qV6_XM343jiev>jbtYW$bt`wn zNWb9&*yhtpr(P={@`bR2-Gz&Bmmm*1N;ylSXMxMET;}&cTT`Oh{oN|_YPT1<cIHmw zws+8&wgy^HyJbD&Q=#<7GI^tlg^3qaV@_I4D(|H)#7Zrq@n-giH?M7?hMJ5|n%HAs z{1dH=v1g!?<&NG!HPuay{dopLrH3XPW8p?cx~C1Y{hW<M*_)hH!-qheeTW@Q(Ho2V zdWK{9emDsprBYj?+QT8*^|?p571O|`i`CY<rno^(Ni(>D6aP{?yyZ0Ab0mRoF+j>j z7E7FolKzltn}PBWix;`E38wj!=|LIwV6D@Rxh5E3>zmOy*?VNa_tiZ}SkdX1hl@6P zus0L7{I;L{LpOh>AE?HB6hZHgnFe?gev>-2&Z~^Xo8CBd32a_?DEDOPcIK6-T{{C& zGl9t$hy$19D!69tA+j$mrv0D>`elUorN|_T$2OI*Zii6tBU!4Y&D<U<KOy!<zo^bz z9SfHqzPm+xy7=R*l8gd66P=CQW(@92Q}$5{6JDo!M}~$a#7CW$7N-#2vWDmsjanbZ zo%%nT+V8RAiCgQ-nX>y+&^`}F(eo{vt+fu!z5GA2>#fCyM1GJ;1T88}^S_^;p!I&5 ztUxBS)&bEe^6cZeXFvoi_9-5(eGK3f?&2|iBB*irnEqJ4CeC8iM+ff9+~sA~>V&X7 zOxO{!s?5JzSl&`z5lYOA0&L3Su4bRa%P?LS=SBgMFW(=ayLkhs7yz(?8f0?lp_+Ct z_X30?lsL5W4|iA3ZI1`dn+xTvOU})eE3Ch0={S4Isj0ww{YS9rr-=C%f*N`5mP^m- zL5$uxZp~X$c-OGudEfxLOWMuF=dkz?U)W;(8fG7zvUE`6l<V_Kdkc=!V{GV>a|I^k zb>V>T%f0qS*PnNZb9^)ZgqQ{3;xGt8op4?=R2-vHq|0N<gEp0s+D=$87U3}6Iq6%< zcAo32^<i!Ntbh^pv9<A+E1!EG4`c{Sxlny!qI+fp&}=FDk>>F1-OwJ-)#AX^WsUlZ zjq5Ktm1CN0WwEAgSSN8zv2W{G>3Fi3(LaUP0G7<&dehu7ax>Gqw#Jl{y2E|;N1<_X zL38bxZk*}o$%W1n45gd1wmAF*|H!V>a@8oNSaxY`r<yS^^rT_H@lVjb5x7<A?wa-G z<ihMyLp7s{uHq3z*i|G4m&?Q-zLC3nsk4S5(9~z#Y@4Vk8||?-u*<X!by6SbPcgLY z;AAO{TS7eX8=y!!WgJF>ORIreS!cr}pdBOkG%a5xM?@eRS0bdl>0zH1Z4PagXcrZl zCd5=kB%9x6Nw+-z{ZGx_0s))L|M?z%GQaJ;7uaw7KKE&iw57_AG^gA?dhB4iVb+MG z@#2byLFR11HElyvtp1*<E63UBVx91JXPXYtSD)T%1RAY%o~pKMQ2G@inilD8`~7(O zaMw5tIi`<;W_hE6TMa$etR=0GaXlv3zhVJ7r1A5Q(w;)jV)Ochs2cX`EEP7-ayGNR z6Z{`=1(9<AVSf1%(%8KEEb^+uOcc`pa4twP8?lmerJLYJc(kWx-&VG!MXAKkVR|sl z8@}GQCUH?sI{&|xJ$nx6|7dfKZYGg;Wc<_CfeV|RTc<Z;jeMwuY*iBBoX)>*m(RX7 zx;4U)bXB6}*)`3<tP$DtYR4PX;+~_|+Ljj*IfYnvFA)vnEqw>L4)^9Mb-KAYOxdM` zl+Wc_z7?jYi+y78^z3$e&3ntI;4K-?*<=PeTO{dQ6W=3x`@~kCq!Xs?W5w0tTG`a% z9ugA9h(3c32-r|d`ZKiLa>~I}N(*{y{0g=5;s+sS-Ptx&M8DHC3~KhEX?M2kB}ep0 z6y070-N#SUEnrn!Uv748F85|~vZ!rRM}pwJe7NF)CGdVTyv{%}g*OeE#T}o`v}XIG zC128v-FY-qev->oGTx)`2Qk3j%=g8B)gaE=dM7~T+KixpOXNkG(I+lXqd!A|^91=K zEbVQuUgPF--BO^OzGeedAe*oJOm82}^%3AmJWS}1MDyVXey)*N_uYB+TrL@L*ry+) zdaXui+|D$)n=vrqwCV1S+gu5eM&2!wK{BuzHQ7LB?@~_4?$4|AVzFrzyFZH=IAm^e zY&B4u^=3WViw77+e(J-yV+wOGB3t2>_vsB@G5E%6Qlc@1-U)S)N7Hs8CAbvr;{=Co z!E*2Bvk$t@-p8nUWutzG?4kNXCnq@eOq!?lTYM|P7cP?gty_@LK90k!mfB!+Tw!5h zKWbA2c&E1jc`9Efz^7Ke`!h+NhwaWxc}kcyaoLv4ZiLL_MW#nZcGSF@X6kZ&w<ylM z!1tXAD-bz`y)#p_?GmHbedM6_dM<4hs-Gz2fc9EvzY;AgA-%@o>$`g%8`5R(myA5# z&Aw7p9!jM;QpQ92_5J;cnh-43(0w`_k~#~>tKUNb{chVG9*T9ZaQ<<q?S4N;sao{T ztU@V&d%Evr3af;qCT9POLxzF9Vnyqx4bE_vPh%r{)xqkXmNoAN2J()65(9!2wj!vB z!*XLApp`qe*#(Hq(oa`P(@Kq-9gQs6?$q<*-Ly$3F(AhNc(B;C<&=yYEZu}i3Gj2( zX9||@@H)@S9gNZQE`w(6IK7ZSv}?E;vMo-4^|1y`?&~E+n_OgirBqQxQQoa1$Q_7# z9dg*FUo*`{?ZuWmPz7bNl=jI*uZc8t^;eI$c%^SptJa><*@uZe9|VE7S>WJ&$9IIs z>8nUP%U{!;Dx{|KM@c(}2G>~jmTmSnki@vnv5C_qTWx}gTe;Jm_O5fa7e=5v*c*Lj zFI?yj!HNLDiLdYKT`|JfEZ{47kF}6SKU6p29F%p<Q<Rclg3}P1^L!c4YWcBWi2Fs} z=@Y{2^|=N<W4FyG{b;2*E8JOkEkdLS#in`0pC5KUePh|~WteNvBRX)#z$p3NEuXB- zUt9KH^YEAv@L7v7L1Z4W*;JM0w=3}A3Bq&>V<TCPA?i?2ST4{P=e}0(q(1kHMneF9 z&PgN5YU(DV?1AqL0>7hdb90Z=`yp1vL=0U}_btWRfRG)B(n2PcNeeYjBZ^rb9YY0L z4|yHR*rs_`M1xAICE_J>Zbq+(46mHD?=<iJnI7_-Ez9#itdOaDM%BZ7x;gy%W0=}- z=LyKI^?Z2A;l!d%e<W!KF|oOKp!fM&16us%T^v=$9d!+jNA~vijkwQbs<$$d>5)%; zuu<DDeN8~Ec9DhDA2c>13InCB-(g^Rr(6QPVImi(Y+=8?$G8z-NXIQA*A*)gpK&Eu zgqbeNDXo20ZzjO4;FJ`zNan$QUXQ32cXe*??RZc7L+381V~`6WdUi>dtk{7nBe>`X zbWf*P2;W>4j~u1gUrCzSro3+0m!rhHHP#${i96<+(l0bvtQ92$2#74EJhs#*G#wm- zGW7B7Ax6$P$JSOTMXl`Zls7t%P)bn~bwW1?UaAu#hYQ9uwWP6^?o+?7986RAMG3R9 z3rMP*U|?KwMBKNQ5h=HtTVJSx4!e6ixbF0WKs|tT(`-j`q+e{)zt$gIS`YDy&ONr! z54ln_VKkJ_F2qlGqA}bymvR|h#Mms5a*Rc11J^CEMNs^e1T?19PqpLU@o^4$nw<;Z zDe3O%ih6F3H&$Olj(yDeOj`DEUqj*7e^qocB)}iM9~06s(_gheN#}La``Be!Ls=uf ziZON8_q)CGBcBu7r=EP@P^qF!9Z<MM3y~A-?V<-N3uaAwT(+$JfhhWP)-)b-%BN*; zRV=w}Ml#n|JHm}U3Mg1_Hl)8>lqyut;ivUj5G`}t!Tv7oZRABEi=&u<Nd^$vCzQsf zqbs>TK9$bHvwR#f?izY^?nTK3=#OqUSxwfw4sC6*e7hGvPwAT@c@$_k^H%d1*ug!s zzTBZ_()n)O=s7FK)q8G8f^@x|R@Bm#M?|{aMUM`}IoY@Ype^I6N*JV8{hp>tiQ7As zy|M5HydM~J3h+Li!zJ!_tkqE?)UU@Qq2@qau1~o$2P<vw3aG@`3XBphs^HiO+m~m& z&ZDW1q-Z;<5w6+1EWK09y5i+M6ziOBfS4iFh#_NwJJJoy42i7!Rje|Dza;84*Qsnf z3#MVMdn0QGd26Wy%}^Qq&~We|Bs4u34W)2%ami*k$<NP!(QO1+32erB-7egPb7?$J zvj<9XXe2q;x>*e?d5tkol$qDH_MNP=J^vg@SG}L33U@!RNdF^`H$GU(ZM|)_e}gQ| z5Z^MyMhNbZ!?CL79={Pjs+3t*jj?p6ma3qtgvUkX;c}(pa|vWhRFdHI^FbPz7s3qF z0xWpIbR^QYH9uR}uQw~UdIvn{`U%h%AJPQpx^7MDyY{@iGzlXvfi%+4gch%_Wk`)+ z=4gFAlm`83^8<eE=+*YnE#+2ItNgo&h}3RX(TQoYIg#V1@p}ecPQ2+jdOSLlnVRQ~ zCvqYI?8}A;HL_)vjyTLZqA2+Rs#Oo$RVA(s(o3mp0o;<_nzi5$sif&ZCg1cW)Cb)z zu6{sFk>oohHrI#6B)L6_AKP@y)lU(2`R$!jc{5zC@Obr&=9>rq3kCr-o&AW{`+dO( zX+^f|X%4V|JG;Mt4(=XS%e#Ch^&QH4T_Cdl+JxsU=8B?7*TM%4TICZ-)TT^_2}eUB z|JeqMUIM?J^5r8br=|%)H2a#3V(HqkbOc-Dj$a&PNO9CIbA)EP@vBl1CB9<6Mc=DM z{5t`;ew_y(K(8f+&U2~bcZ#T2ht(Vx+OoqaBh%I^!}1fCws#05pD4min{`J!bGzda zywXpt8{z?3jfP!vOdZ1Y7Q#aFBRdUNvOjrAhfcJ5Il2rPne;0C?IL_kaMafz&h&4P z6C{|x-iWu}6sGU`w<fHmov*}hzj-?rH*kDcc|RsBUrDW4_qk~VolD0-drc`+!07+E zk%FI~k<0I~@5Nd6UeA<h<Re13juGVZX|C-T6J#(|zO*KIEUX|63l}#+m)6u+VZRs6 z0cPXE3DO%?o@vuBB+MSL|DDs=P~b-O+~n*o>J?*MO!_Z*l<7xPOk}q7@^houy{$1e za}lyDl~b-@E|&A2tt#cT`iHr4(d`3&%Jr=`C;V5c5gP{XB>gAKaMAjFBiD3su8Ez# z^ch}`ExAbtWdo_J_USv`%1+Nb?<KYSpRaLDYoFS{%?`&K#aXg@-CAWy)smcTSQ`WD zLynp{4~6l}xV<b%dqdH8rz!rv*$udN(|a}{HHPMb0ztNeeX_@HFCzf?`2Keozk6M& zE~a)>e&Ou5#dme<gsZ9I$kvjVTIQrGs16Bkl+Dg19)E%$y*|zLp-(?2qK-c~-nlg} z{~%?~@$e%Id_8SG-7b*Je%Gq<AeDN=DUB9lJQId|83oMa6dOn;1g+5~10C%MV4JFD zXzPQsp#0vYK!Rt?{p|4iXt#8EaWC`NrWYHVQ=gMBJ_rkb4_=TXKiOWFS&|kUoI+AL znXBO_*g3loI+02(F*D#KBHnp5tih%08#ZO`vy-;OJ`c#jeyjxOx&&Y+>;nkRMRMMw zmFn27Q@_AypSGu95~)x9hQH&k^Z9VF2m&%!{q74s-v97W3VH?7d<J@JA(Q0-d3Z}P zzdH&!6CODLyM5HYsAswZxb~eBr2K@{hFg;Vv7j809BTY-mY7KE$#n!O!S!dzdAN-0 zAdBu%s!}=9_%90v`Fr(?@Zm$!(M$hEK_Qp@c$nxQw|buvRvrk2hu2;KPnli$?sjm` zXHEHy8&pnVcV_R4l+>YGY&}SJTs8yoZNC>qo$80nU~SpxYejH94`m~@-{TxK`G?S= z7|3O+VP8Obs{e{*Co5*v?r0q3&ar~d8GlPyB{?|l3xL#dT`frR|7ph+L7Gsm5u{SY zL2>JIrzL^jouiaSXj3;<;;P%Y)U)NJ+tF_SWmI$-d??>AD5-U@e$>SQ(uJY`8hra= z@0DqIUo?qW=u+TuWqis7VOd^#5N_GF9`}C2{k)IeqVLXp*W>Cn(696p_>Ro3g6|Sv zjkZu=!m9q^tHFZYm3-EfJC~8QqZisd@cPRMCHI>Lg^#DTr)A2<r_~px;BH&CovX5J zUYB!v)*@*Xuce#ZX2%clTkqe*=#}hj<EU4bs#Lt>G5q?!-I2*g?h570qudBwH-k*Y zK>)``)O)5MW7U@qNzQ}OTqU1x)cA65%I=pTr=96{eph;k5Kx9%NaRLqT$d9bfG3xt z-}}gFJim^Nr|TritI6IcCMk2aCmt<j=Dk<B5+eICt}nNby~=5TXV9HWhs#@qP>1T) zYr&u%k|yrgV~X@^y~+$+*(8!Zyr$AFu1_w-sJVga_K>kDq4wnu$t{Cf2M3vh5xHGY z6a#u5pNtie8ziWeE;OIb0`)v^xF8QcEf#6)9E(-<4P9sKw7G9)UWHTuH6S-RceE{F zqyod+Qv$Z>Q|*nsPG$t#c1nS`;AW_@tD*P};L#Z<zc*BOs`7eYQ17duY})a~*O#Yk z9Qbw|ik^}`r8P7sqIdPdUi5vRP7nYIKi^HKiuJKNljmQ^czs02BvXs!A`{(pEt?6M z|GbzsYOx_yQKPaO7bot*2lrtKd67ySyV@D5I+QM+EYOb|GULKwY&-A0?hdx{77gMM zEks2QHlhb0Ldv3zbaH%6vHYy3Jt9T`>*@IenLvfr^4NLq>!!IKfrJWekqi))<XC}R z<5>vT$^-A|OYJniA#mh!jDm|+FMHpx&;w#BM|Xm`a88q@A~^kiH{C~~AJSi@Wf(L2 z654~oy?%+F!0p~Qqt!sSKIofTb6oZa*fXGkYZ}CQ6N(Hr@`~4+V}B*I!*SMTq@atR zI<kHC5aOwa9+s%uei<PRY&!fTsxcq@3fAn>JEMc!j6K_*KCLXI?{|>>Q^?PJ=TtqT z^i$kIsiqE8iOLcYdPOgDub{e|NT!kIwQ1?AdPakuKObw#K6kRQZqr8LL$H=PsJ>S& zKgwPP7*QK=@s6n|229hrxa7ff*NcN^ExLbffLd=@UJcYp`T^4f)aSfdU2yBq4-EdO zHZ4kH#2Z(t2B;$*|3ddJK1p|=7szT52&KzwH}f!LH~#YV+2qqnxT3G_yB6ZUzQQep zbIiU?Ha3UDw-tR}IX~73pO@$LYbpf0-Bu=yc&3Yyh6=_ZU$zv^Ak&d?dUiY!*`D*x zwm&;&SF?X@=Z^VzEpR4)`Um}&L%EEpJ}*^m0ASZh?K-2XM}x;hcTlo~k2uB@#@u<` z(@%oMhnj5Yga|A1&3zgD*g0)nwG&~XKfUX*Wu2JpRJPWvttwxxGF@7p#(=It>Z2YJ z$KXoMs}({$7?Dz4Z=5Mz`%kQz7?#0yzu?NNGwD^ZohVgxxH(FxOyS-nwWR^iaGUn{ z=wSYVOQs1jxPj87qIG3-L=6Tsu<G^W4GlCs`Ojq=KkKUde%JaJF_hVro@lhr3)8tA zqA)XjQ@~|N%CT6CJzTv%tr<|S6`8@9Pjqe8b+ERdhx=Agzx4?)r~7Y7So^7Bfcbk( z+EHA_UCX{vdj_fq51VSpkWWDZOph-bv0J+Qh*G2O(D|4}HF4<faDYCV4-rrhZP;>< zHcVO?5ZsjVRJA{`XM!}TDxr9iy-NsIXqw4nt`1&2UvR}bkE%g;Ao*QkIx204n{1n| zgVIjp;~L{@_MDk@qtr)HNAa|Q;~Ro=2|CH<>fxk%ZTCwXW67T)-1o;A?sx6GerxHd z0HsQImzzH)T>xV_<45HIUDi2PbYQ@dII?A3X&K~AjBB#n3(SC0jZiAnarOnJNEq#| z!Ix{DTJacfox3P@<i@Hs@6zeK)W$3)4pTM(gV%Ym5BXjqq{69OLs_-=wyDTv=9>}L z2KXc<+uWl`Th>^tb=x1owvFo66b%-!ir?!jY8t*V9b7IaGbqwyts5}uJL)7naBa9= zw#aASW}{&j5!>p!G3D;K+$Q2)h48+mJ@8nMPIHA|rGfCIhY=717~Q8V-Yc8cCL~Mb zbIf4c-XvRI)x6VAZr9WXspH|&Jlsgnc@ZR6@1$GCjf>m~-e(yB6~lh=AaN~UvK6Oi zHp&(G(AySa<GCa<ytUpg&LEX<ZH;NPmT6|aWBFfm2S21s*y7AK3mLom`9g(tr@kDF zcgr-)=f6xH_~!HVF-}BC<FMS7-ZpI7mCn+yV8byu%5HjI;!d~ACEl2&^zElS4+mij z9^$+y<5I;=xXDtF!Zgbu3{l*A$U10K)5@OVy^{`?rSS^W>S&WKjE^kQ&Ft1pCAYOG zHFz@yjNR5YH<~C6Y%2=x76@fwHtH*IUz`aY4^PxEd45^Ux{H)4Q$T5H6dEdWOnA?Z zH{vV?!ec71HNs}8y+4aU0Gl-;ZRIFae*z??1I=36VsCr)X7w9)OKoKcSD>=l=QmLZ z<~$-j%WjP!bM$CQlCgVu;`p`X?AzDK!(Nmky;BJ+e?cs7`t^K!KFcJh&O<%2TU}#u zOluHPGPtc@UH5v)#O$6e0<TTX*Rrf!ctF{`6e*Lmb_c!aRECU4`BWbkE)T#E20(hL zO6_nj6KrI=+zqv1+IEGT*r7hnrmmuwudQ(fG+n@b5Mjm04Y5-lE+W)QwlLM|v4!<H zjkeX&9^cieBY~DTL%xuti(3+|?R4!@vpH6z#{#mBQ3A&s<Q^8R4wl$p3c`-P@?Ft6 z>mB%3@V)O*?1t;!JvmPiB$dy6eo!n`yldBEOh)a9G&MW2T(n=>dt9pG#rG(t9*p!> zUL1<(B(s?<uw75efXy(i?nnzvz_dFSV-e7>;763YmV`o$*&46qes!0E0g4fLYAIEb ziuY<nBabed+C6<i#;=+hNX-kQO-6`yl)Pb`qUW807VFs}sutxgh)$Ccn<B?Z(#R?2 zCEN7W=Ne5iL|TC2Xh8np%!l}q5wrOMoqzya$yW`74Za&+Q+qLDWpB#RaFv5mMTQ?= z=b0&$A_SY*HaLu4e$<K>{E@Km>{IwjFi#mpWvA3BA4<|W^#z4NZARcaC=U^}@2|xB zq#bq*h~EcX<^gzWEE+rY!=)32DnkWhWSUHZeqT3)b}cl$5B{PV1;3J~<!7C1o43UG z(S^f^7ous)OhsWs_l6I;IKt~i(1mV|1enrU)yZ3qM-JgdWEbyNYsz_QTmpzO5afZb zzLa-Es~fDuFE2cEL|Lmp8~fVECTZ3wP09i*H5^tmSe5(g+e<2JKQ9)h-MDS~8kT)n zRik*Y-FF~w*4#0XK;0b{^KJejXL!@76g3-J=;TbYzfLTThN!z)&)Vl)?j7cr=)<Ci zTXTB*u}MQu6x~Q~54C3XRp6bQGb>(}t5rD_*mX8Y&3I{gzHtTWdaOvnaboD0{vA@^ zz%4Df<5Fym9iqTe3A&S_1+z%C<R{l%Haz5nJoxbiU(H{UislzHs+TcqtIJdv;SP(- zjA;q8Vi_AA=hM^GEs-s@F2nbUi0n6VHzj-uchB<-YgJnI+?x>wA!SevY7&GdN?W2r z#ro>Mdeqh#lm#ayjwp;qqMT^iQ@h2x!4jz#5pJ|MTyE~ZuBNst?wQoU*(1;*-GI?N z(x%062Xz?t?CRiIIZ7i$Fu}Tl^?r}TUK%q-3b=_6D309<H5_n>uEKfD#=Rdj$jwLM zVLMi-w;w3?uQ522d*C<hhB<p+UGpmyuGypX@yowj0CWA+PT#%hC?wcg)g?H@&U2<* zqWZynZEv_`_$N}9Zv{tsr#4q-{v=)XgRbeay0Q(Q)D^cXgvkvWc$*j-j=gSMMxY1f z(WgarQfA(J=CP{Y=WOu|4n+6i3x62h6z7JqOYt#G^hNKC+$QO#kGbcF_5XnB;mphH zya!UMtN#RD{C<5r<(r&D5rp=zBilzG#HZ|u1tYu!@v+9P%va1-S6xsaO4M~(a*?%r z+eI)azWShR0rtZrTvMEQ*_AeMDYh0vc<fF``yKmym|dTVcf4j$nNqWk+H=-!bi2@` zw1Rl5{EptEkRLwYyFLwoB-@|{;&YDwav+S-)|DGWBuCn{57GtDH&kSt<=K5#%L;re z`3M9x4q3t1m!M3NqxW$yI^UdVqMUpb^ZZYsKQxl@V5F(B-={2nI}9mph9Z<o-|v@( z)phm3gb&)$t-x`)rzv~5H@QI!HDQBo@FGw9)J=(@FIICDFKK%#we)&BAygd)Qr+mQ z>X(&lg7Q7QcZWREH6P~hE-h&96mgvYIQUwE8rDTDANGh;*;|jlS7^cT0$>Ady7%eS z7?iR{ZJMQJDzh^k?~jiTVsBI{CWVbQb-P8;plJ3v*(l&NHt)bav<}AxJX~Axz}FHa z<d!FvXGKUlySB0jaM*I}={EhU$$8o_-&O6gBLxrb9wst(S@r;ja1yLqxPU0G+jkt@ z_V<;8ZPm=uhGaP`tV;X$gIt9ELV}XO>EkFUD_ZQz#){Z)k><^J`h{#&bpc25i}{xc z_=27?s|Kr}Fx_$ZREE$V<9VsVgW>LAko%b+L-@Usi}&-L2hbh`jQ?4)3_Ige^8`hN z%R|DTPbHcj3C8ANwuqN|PYJon6190M$2N;2>9DyGd7nxzN!z`$bzNrNtBJ@SEDp(l zj(8MDP8@FbrA^;3&?-Jr-_<kt8TNv~9?+_HKY3}Rk2H$+(2RBH5h?hO$n?EyVZ^KV zGD-UU$7OMMLnakj0TNciOT~uHUTo28+~pedm+sx=^(r;BX>HR3U~=+8E=h~F8lo!( z!!NNKH5tJSiI~Bi9nW&emMeK3jvoa`n<(JpXvOkh4|;8tS#H6$XWm4pKe5sn9ZfGk zrA?xXNckPT8?o71*WxjAZ^ba?CA;ToOVim}_dHAw0fpKNIRR0~&lTH0OxyZ7JZ>N? z#*ESDcXOMOYM!EHmQQR))sIbZLF8t8&kWeg>L8xFcpBc*^L+opl7JKv?riQFfQOWc zyY?EZ!9VQxxSO52Mj*&*73PeX?hbM2;ATY+FT=80EUjmkT<cyKG=aj5%<`x!ulUPK zh_s{*7S_9z<LGJ<F^sXIYEf-(vfxKyH!Q(cgK~6G1t(7~i6Fzu3y5mC7{zc1^VaUC z%_dsAvbDsX@fG*6F{irq?Pk~QZ6l5-BiTBm`qG7{G0%EQjkB!%ago0IKGlxdUMo`} zv#TShzy?qk|2Ik{PB((tF0Az|yqYW6tVL+Y3R%wR`R=GGPp4GBevFkN?4~rUnsm-K zyfYB*o?YGESYK=xzzILV4JeDhk|I@s_(Z&PEuB2?b3Uky#i`Rv8aYtbk*0gz2f&X` zfi|&o;x~3uG)W^(Ds^cQ+~uJfIF#^~Gu20^&4M<jDh{Vvz_M54M1S{nc<!LB??PU` zQ`apmT#i$@md>bo%>yRHf0&IFQb9K!Ra+Rp1l2r8r@RzfVPB_}0MUlOLcCH(u4wM_ z=AcT2iUyE}b4?q;L2#&rZ0Ta5dMn;bsl|Og!0kA_?{{@p-=Al1<3$J_nhM3<`;N9k zWOTx(E0<{%zH~8RxK^*)Odhdo$fNw;!hqe&;<B8p{dDH;aalsoyG93s6oTES&LxR8 zHN_jxL5OAWnrueFU}~`qdb*CZAeKV;S*Uu3&}FT&@s&1D@k}W<v28Hkd9L<zdyYZu zIPgiwkv_2=VKe$n{iN2&$cM^Ki4w$W8^hi!=kwnjp8Hts+a|KT7QI%oHXE-Nd0ANh zu#0j@9IUZZ^|`I#DWSvnKA=Zc@Dg;yLPGJL0=n^YaN4}QCEXo0+mF%|%93>AyM5}V z7B$MiU0W4R-gQ3ZSjc$Ja<oJ|S)@R?I<l}_MYCF~kSZw-tl_DG>iWZwUps>tF*~0& zio0)2dyd~3aO;6L7I_~|KJ5(}7}*)tRV0{1hMEA|<#h$};3w3{dol!l-a8mQyncyi z*QLHjl5tNrG*9}v>J(G*sI2}x?Xxyv{ju6CAw~+L<xZaoS32>P^mARf{~yskNCQnT z#5s33MoaG^j3!0tdgw9YsutWgbqNLZ*gAkP3V6q*>v{Nv_&VEz(HT|=&rE~<S?CHq z4%ZU?;gF=FHq$Np%5HLKS#Z53AZBJSaM9No?D2><YL5$He;m|s=(CzZ_9j5OD)ioh zRtZ?Oa_rT+KEG!i-!l^CZoAl|-?wxH`NU8dKd?<S7T?G6){i1LC}OFC>j?kYmRNCl zB>;rig@Fw6(Y?Y~QyoM$3(yO<a(gdQ?)`#^`S5B`nh7Apw0_9$TLjl`>E6r#x;2^T zuudF;ip%nEl@CF;&h1cq2g|$)h0l+)=pBU>6JLHuE*rs@GV%`S9+0ThMCNUHXuxtG zP}P49<Q>YCCxmtFBxTP)>^<F+yv(pcWwyzv9a0OQ+H>C(HokT2@s(RzO;ggP`PnG^ zwY;T;_zgA1T)MDh9}CPaetEjnk_|xv2i+~jk<MvY@3N%+;@+|}FfCCGjqPmyQhjom zQw}Pr$Y_^C&%%^?)oG8P-nQq>KpKe}E%Qw58Y4xnY0x*1n^OX+K7SU`2#S>lRQyk+ z>B%pU2hTilaXg7b7%o)Zex7Kj(U3=ll$T1#%`}%sIV#oHsJkO#>J+(ih%2by2la~F zktdhRiD}ZjAp-g=>-v^%ZVT=Z1>64}JH0NCe$5^20g=nznc2I(A`NDQ4S=j9&G~DV z>OXdsiEV+f{k*(|`nsK0nT&N%Xvj+-ULrPSb(UR~G7K4a5*8-HEpA^rT5b^9-LxSa z>jB6BHuO;dpu-JiZH&f_j_#U`e8=Zm8|N<P`{x^ti?KkQ@vqeOYe4Cfjp^N^>%pJc zH)W@<-lN27S!%VXB@V1NZ}Nzb+<Ne#LgUBsFi7?*O6(bUwe$7vZFje0TR7sw8DxIr zQ^=(QO1YA=hn6eY%&dYHuL<9(+`CqG6oybn^^|C)sKDXSi-OVr^~Jm|B{qcN3&Oh0 zu3d~bRg|9lZD?V?$yyp;uoUrBsF20-YU2!pn{n64s>QAoB4%$Su3V9Wo?nxHSP}o= zuGIzIWlL}NG@~`Vk*o$m-9^L2WndSj$@e=SY*o9mEuDRhFuy{wY*8V4PZ92kdah4> zo@-1PkiFIhN7dc)U&;LyGuGjF#ED?63nv*HSRCoYFEU9J!{LRANc0p{jq%s{y0^Gg z?{eG4g;4gY6p^{WeLT18keFzCAMVSrQeFAt`trZ0a?|_ThpMbr*z$FbYX6H(%SnSJ zfRDcgp}Rih<kTK3ddjhzHeNbIx>`pUrn7JQxlDIdl0R%z#^@5mUPYM?kg}uJ&qZOJ zao-0sU_K}+Vos&EvA1!PPt^jk#CE=Ok+}6q+ShZ_?d!x9^9ts%e<Pp*S*GjJmoUhR zWLy{OooVyXPP|e1xU{r8HM<Pq+9lDQHwDP_F_Myyq;Ah~7_7s4K-Qw0p_5pz+LOSN zfFVX~kGSdu5e;iBw{=(#dWr5<I_Jj}GgJ>dLdlW@nk6W>zUnyHdR7l*{^V`|o&8>E z3X<Ux$w$buJfdaKfe^WkweKvbrkJc`TkpKe>iB}SQuEDRnzVyT`FMxsGlHZr-(f?* zrNM*swD-R}87@3czoPlKKKD)lgoWikclBW|-KCh!>dgj*>B92)0Zc*@%(3H?YE=2> zk!u?AJV>orq<lI-eUIL|U3PVHxsnmAN;qo9exO$C?yJe6x4*M;>GyAY%*63)v+<Zp zylj?wW%DZ|V%W(hP$bSIjWOf$(!sg(oac<L)HKe2hX%RMe(V;He|}*DF|C-G$j3aQ z#5{wI)I4T0+TI7Ve)>pq&azxz_=~B}7S3t0UCTMvx#Rd%2FX#~BtrL?cQ*UqI(<-+ zAxmNWaXhbPSyyQBQ^+#!3#0BNVrN(0&&-c3rDdi(5G@-02cs(EE`vLcY2==NVP>$= zH`%3M2`?n(Ck_s+SBX9FU0IkfQxrp%H?`1@w&1+lWTbYvG)g&D>ekQiHg>I8_|%*K zv~`{DZ>MrmCO;&&K7X|GoCuyO$Y9Ly^0cKzc_6u>2hs)`kKq2i3VzX<=S*Q1GpYW} ziMk_&Aa_;uSXk&Cmq7z-CrRI-dkmdorTL?`P;vXSC+zox=hulGY=kW}`=<tKD|n%Y z^xqDTq848qx?QAAN3mNdrHhiN{QRQ=sD6G5WAzK4v}VVD`oMmPcXN=i%iM>N)M6Oo z0GU0%xV6t=ts?FBb^F<M`7)BBmYU8A>f|*pK*{`D4rm=mF(JTT<*UlCvXo=6dsId9 z<pPB<`67twfVu)+_lD#~cU5npwXRLPa@|c_|KRfLuW9(P3;PDP2~D@|ytF}CV}>NK z+ii0LiPl(2<_TLQ(RoCzM)ZE{cgKMa*ymHz#hJ|yJ|T(h#Fl=C!h10h1~R1P&vE)r zLzp@dC#BCK39_blh3y`CGT?W{q++a;oDruATnc1eThnWr`_~Q*njeuAoG?38RoJpg zp`Sh-%ThZ!D^Iv;*%71=3%;d6!y0v`KIwt(WqlHVmF!O6&m`~d#Ms32aoy179@eq? zzTvqA8D=}Ly6#l97HfJiG`TBBD~iB}f#-g>ueZ{_YDiy*V63UID=*HBDt3z5pZ+|0 zPVa$iwYv+t&5#YLsy+2;rMSua>%{XPqDDap{48W%NW=~7NGwTxy)49$sxlpdpIm+~ z|0_#QccpKqO11yjq)2!c{^xdPLpeV2X{AwH)%=}`Ij9P0_^{S?1v`S1(BDdi6?#O< z==nq~8ZvbI9t7s}lgLZ*Uj>(*BToS&19~HBgHq*$#VN0S>z`#)Cf8Z@?jq5OMPKg( zy?&%$#Ik&&U{d*0y1X1%?BCfb?cvjw@&*TY*x$aE+JwHw>?%<xFP??!*Us1O5-G2t z(ty^W9Pm-jM(XaVhy`u@3}#eA2{(<w{H)p|<(CZB?rOGGZLfF}jJ43a9}@e*PW((i zwcymLfqQsreH?aRnceHD3D_$`l)T`C-10x@-jqCbRl@);FO2Hd$hIv$mMB|3fzcjF zEgUbEmp|cd;`zdtU*Z5uXViK;;uMWbE&QB|ZRVw4rth;)X&vqrj%b+f*cK9UG0hA- z`=VcyHb(9&4oD5GYdewP%KI=+<LS_++6z3N8DCZ7>A)`{zZeKgPI4;m(ZTV3gJbuc zl}QJ$lw9_+(~>DXnSU?%SbHHNF&*{_(km&vnS*IWKwebw!Cr4OW8&jqS*wzJDP;Nh z{%@ZM4aF;ov?_dstDE<V{nZ}?o9gMK693D4u6`v|Hh$xhrA0ICD1E$qukO}nDXm{j zAzv*~e)AgZN`*8=cMDd5bTgV;@%h5qRiR3U^}wfH|EBrfRy$iiqUy$w#;XF96CR#1 z1WNESy93|6@C_%p`O?#^vHxTW8JXH^>J|q*QT?~jU)AO7WbwyO+IPxnRbsY2O&OoO z_xly!*L0WKd`*MZ-#o6l!cXV>JcgD8;3VF+&i*+>3e7Xyzv@%Hb#Lr06|+?wzWOy{ z{<2j6^ohd!0+&X_a$=4BflSYALNa{W1?QxJ^(G#Mk9vfpBWw_9w5en=sL~K2e=K0D z{HJ-<EV)4xd-<JPbR;R_DEIEtTgImg+OkpxOckyC_wz_d4cJUpd1n%=d_Sr5hO?cW zuhGVcT+J<sG44Bvjo}HhLN*7^BhOsG#5RV`!nHI}$!vhva&J{uS!(d7TBiNMq+2~I zOB7kXz;>%tME3B#3KB^Qf~ZOZqpW-)#=QWMz3nu{3288XNt3VpWLQ@R;qN`Nfl7cN zpMTvBhMhfFjL@>0C*F3wplKaB`D#V~#Alyac&5uUk)nxw?dcl9{rw=`ySTo4gW29* z<Jj6AwJR=Fb2)f7Q{F9aiJ^NE`kuHaPY$X1Qh^mxbvWMe<t>8`P7mI(xKZFbTj%5` zU+!dhM)uYn8A9WV7e3whfH}QBl|bE=3lPjihXF^5v4P%`jdgjIkrAvzMWQr|R2>|V z?Jinz2JE*&J9>_HQLSh0t1z?8&XnGj3pUlOswRdk5MCOMAd9?w?HFRO67NgCJ&2a9 z<g#|q*Zk0d^lB=N?zzvRKl%4Mncu?49W3}$lRx_nF~}GM+2q}G85eN#=8tkA_52dy z$BhZc!9NqbCA;DDnA&EK-MxiU#^4@Z*kLJI96y2;ux-m^+IxMSIOu{pbnx5VN!Unm zQwb}H_bjEV3===za@xxf&APUM-r8J#K@Cy;XbvFGU<FE8Hj&r~KE`z1Bvs^4_K#qT zdl=xr)@otemcpBya6ii9=J*06xgZUyYg0N;giO-DVg+pV&uSp888n$2ZdlR6b^3bl z*qzpJ#@0;H{&bpK8qN1pZhWadpmVx&gEv`Aad6}NRT6hZ6~YsigD6rlF|TC$KYYDs zKvP@S?;CNW?x5mUnpD{~iXaxc5XFLxP5^;WL|Q^M6d{lx3aALE2+~6@p@bHCh=72F zUJ?i$q!WrEp@hI)@!9)1@45G!yFT!RBx|m@W*Or@eq&5vAAUcWLvimfKy=k9M)F89 zHq@!^v@6-c0D4*rf*}^9RE}E6$bRX&cGaDzomMuJhIEpzIe6r>$mLG;Ebw#h2sd2= z&^3Eqtj04%{L@aI*4oZcksRrXPk(sv4ts)8ioPLVsCv|pr36&HK8J*p5&+DOi329p z7rDdp9rnW7(bmfz2D^*PAr<rEZxc=$^+Z;eB2w5+ds~W%4qR+{32s1nzf?lK>jN=R z;-F)@i(&jH3#7TgUf`!)hT#kydP~%W71Ils)d6z;?%uwE1?mlFOLx&XN(lRwuH<jX zVNn@{BWt(FB~40wA%-@&V12<aHK``E1~INuE~KSSMN6JaJ^V%Rn<<51?&y2ZOB2Hr zqqK~;Kcb<CyR(KtxK;CgWixwoz#fY*>N+W7ACiv|+Z`4&wYTV~mbPKamdNGqdVBHi z6q_P>SDLOvIEl~Kfz15Rr}UxD2{zr6cD;Y(-?ZnLRITSo32Gc8?VOFCi;agRAXZfo zh;}B``4~If`~`D^e1ILzJr?2&9_7;n&JeMFZ+?Lr3#S*9uvZnSyuK~L=`!Jg35kt& zLvrLn#zAp>!r5tCbL@$LCb(6&1z#<4VN3dmQ95Zue1&%66>dR=%2IYaEe7pYlIy6e zAIZOOGFN~~r8`F~!=7TU@<Lwupbqn{kG>q9y-r_y0f!~dEbje%U3GSb31xO-Z;>oh zWu{k=`N+ks#}*tk9OMj`#4ntF-nLd2Nnux_^_JP$gDIcD2{t+resh8^G-qCA$0)gY zF$+J0pFDBB|E>jhfG_ZLQ!;~3O@(-4LlpgCpdhfJQ!E~amobW#dewVc#8f(QQK%Z& z({B^Ai`P5yKAo-4)-UUNr`jGcvP%*;STj)q4_m6NHi;?ak?x06dCx0C2(3Q-<>+bL zXyS};`2pU_YldCk=RC15G8g9ct7inbJEWV2u3{~uo2fvfL7ISB_0@LZYuO|5RG;ZW zuE=~0#Ns)B?zGG!PK_m@Tf686ffdH0X%|iyN_!(l__C}v5R)gwv@nx>C|@z{BM-)w z5pX_yHL;~x90Oec2Vi_3ug>%=C0MQPIu#e9HU=n|N{yAz=WCXgL}D~-uJyAlA}oJ9 z9@2`c=Ynt_@ZhRkawjm$-5}PaZRo6DDX?_edn9qqJZd;r##w{?AP_RSXQz5RkcX)8 zA{o`@!ddQ$F3`;dNUfN$@8zr`IU4w2#%5gR>P|lJOV$i@iddbytyVuHdTlc*EB-tP z#L&IrT+a@cD_VvY<0$;#MZF)Tf+Yw?*ikShdS=$>tQ;q94SEMu_}2e>j}4J4Ice8= z`$aoeZKR^UUyQq<I!SFeHeUSf7mo87bb|mnBv59u&k;~9#w6;s(`HS}M3I33ni17? zK>NevHO#&~{<6=dXk(6W&|*kEHk85_R&?+A(#RGrDO_cxQA;LgN??F@CRe}*Q3-4@ ze$G_SeV|-Nx6Wa~4ce06oXmQ^RmG>4!aVQc<nWcq$ler!{2?WGz47PEVVs3E^(m*X zJty#G<4Y&~_S<YV@?IoZ6O{`)kyBCij=Yw&y+v_rx(3m9Z3_}7KBo>I#}4ocmqGW1 z^^;grQ;iFhyP`{I#d$(d@bnR&(^f7%`OENSv1Y`IDOoe_{JVC3xM0BO$JT9h%rBLY z&(@6mGyq@mapR>1utY5Op=M&6Y?3*<Yc8~@y6n2M3s2)H6H@oVci0u?IEcTK?5<Q> z(m9n3NpOqW#Z?8y2$gNO{-H3}=+jDREeyL-YP?tU_U1Txaw=M@C&m-?b2TY?GH46A zwrKlfhP_5#{)=#3S7?lwvTn|2(@Kf$`|b~mtv)MeI_Ebsa8E9g!cD1wOjMnJK?%f0 zQ2rsku5-x*UGfrzI5Vk|Wy+}bQB|Mq+0ge6Q`+%52nBWD;Z&>dn60P?^3w(vbwuA> zE*rTq;oD2}eDZ6>_N{oJ%$i?I!TU@54hs{c++0_lUDo6G5Q<yw86`H15(GpgOuFkK zZgf#+*A+8C;~E*8lwopD9ptDpTOUaxnHDRzJoUBQ^hcmtL&p<hoA)6Nn}2CESbdoo zzHEFOAhxE!BQa~<Avd<8C#>p$K1Uy_Z+5pHp^m004j+44a)DOg40I@PT_*zEUf1fj zWSQX6q@#g>#8y2BADHyCYw6cFhv?SB-_H_JOSy%CTfPCQ3UeIw;A&aogKJR{{53`U zInslSmwaDk%nhgbK^_%thP%A&*X=loUF!U}*8{E9fWTN8>Mh`7)saV9Q~0bOs8pgS zo?ff`kU}9~b^TzhvO>=Qy+-1v-v=mg+EaQ8bcZpt#+(NYAlJ&R)DdleE^4Y!YfyKv z=o>dy@uOE0)vGi6KYzNaTj3iiMl<Tpml;F0q}X3%)U_Wx)PHy1>YL-8`F&INF|se; zFmk7SMepO!E8MyC%Xr^;=-xTP<;X9R2s1Wo@R{Ct!2Od?&Q;{-##!{BTc=gr^E%&q zV;^&x0bGFikWnMO$!Hu)#E;rxsy*-#BFMk#!znK^Xx1s36eZ%diS-lUx2;i{Bf>R* znB$+3Tt{kK>vwBu@eT6MNl!2v+VrIg?A}Y>W4La&E48GT^aLjdx~x|+7=Q6A@?l0i zOax+5Ug0|@(E$be2qAM-yD##K%=pVUg8}^{e*B$?rs;d0Sx<}T*4S0ch3~`rk}3z* zV9ier`IY|D#vtG@KLcXl@*`KQ-Nw$NPl4;dc5mP5Jugbwn++YQ_@%AG%n<YR?BZdy zYbrz}hS&6wdkR3C_2xt-M}P4=Mf}p{rcmbRz>FX>j}nOW$!}~jW3s@{T=kt3%C?o2 z-hl^#ah_8kX2U*{CV^{X$CH&Qn`M)0(M;KYv?F~G;EUraN9~zA(0+Hr&Ba=l9gIA3 z<$Hy9vVFzgt3mbFr>6TzJ$B6PiQdAD9L2bHw+oN@6@q@f-fyKr1|C0GZ3~c?-i${8 z<FwM~$Xl)e-M!nZM|t;m0KE{KmF{B?EW#RDb$<c>=RH@R)8Y7_agiIkEZ{e))j|nC z-wt>DPj94N<@5&MWD6fCCv7SnWHx%uMXCPM77V{W(7du#k_f43l}}+>8LQSg&{Z8U z{*i-UCvIQ-7M$0c0kK{fbYBry{~pF8RaOz}K=`u?|68_8Q2E0|vG^~p(-D9P2m_iB zW$&z<l)Y_gx8&}+qTf~1g))yRILi|Rti1x~UKS?|X{eEs^Lp6uHxmNcD%qm5?dJ+E zjPgg3IucuDUv$GoKnms8iakSU>H*t(>Q;($VGBSLm|KBqBr^dc$7gfEmbICrHyGxK z$%Gdz=9!`&Lk6}++Bz#Q)U?Yd`wyme<Rt(W)k_UZwRFP7#}Xr2_=Ee^bRD1VrMWAa zojp6qqVhz6fb38c{#<bc#;-GEjjRs}YA8W%9TXpKr&108Z|ov;CSmYxONK$>?A00N z<iU$7I8et7?+SH4W+SYvN*P9Mt>KNVkRU2GECsLKmb<seFHvk?rne`-xY-&xXuZ3+ zclwV5GH2XS#4|^O-T(gM&T|uoKZ78qpA{B^ZM;o@m1zVR(}6Oth#GFwmju(ZyWB61 z0bS^UzPE3Fw+cLf9nxyQIZ>&McPac7uHi1(h`c87l2n#^^Z@Aaml`p>Tl-R^T%ez+ zeJW*-5!;iag6ZS>IO%{p{(39achzAWNhleT_8Rr)$FK??^9Cx{=hSLaY^6YfGT_%( zc?PMUw%?SUYDrR|H<d&W@<wl-j`)`axP~sZ&J|5|)QjBsIng-gB%X2S(GTu2SK1HK z)cym;`oMT=2cwC{o{6BiPGc`XKkEVR7MH+ENtGd)S4QIP3#g!j{9$HQf9H=WQrL~v zf-1(Z%*}3m3=(*3^OY@oRT)&1hq=-hii>AZB45yXnen=Nl(Se@*OfRvEYh!W(YJL^ z)FOapkANHjT|aw`!g$ChjC&l@bqpBE*U$2eEec3g-m^<TQMco8bKwL{Rb{)4cS_q4 zQf!;)x*|-O&6Ci8Nc-2D;kFq><i`bT8wII9l&(;;qrf(q-g>K2ncI}f`=gl(NZaAb z&4yDuG4`I``SyeP8_OzZ+D(#c+eFk&53$S|HJi)oHf8|BL~FHtw!g;Z-l69s32kpI zw8LiOen#kR0{QsG_DJ`)jiv@XbN5a5%q{o5O{3i`i*+zZ=5t@Yp{Xza=^<&`Ayxo% zpmTcGN>4CU81R8{pBe|)+Djv+Pp23Aq>PQKhU;9^Q=w}$y;?fh5$|MeiAf7|Sw?eK z_aU-kM~z<O6?I=r=El#pPSRFZ;O-mVTm7UV=5mRIPkmz;kI=PkNCccm1DKIh4(2yb zV^u!GRNsXdHhTd5ZRiS%Nw+Tv?(VEsYJ>BOnesUD7(+x3R#!Jtr#;oDHCw-+_!bFA zRA;7fA6YNk!5+X&HJSPI@rlmGEz7!d_XJvI>or@4Q{FahSx?6SM)o7=)xtij5=p`l zA6m{OuLv<kB`OvOJc5K|I15a+VjK~zwhp5&d7(D(jgwjRN5xLsB2wbfGu6(jGGRH2 z1GQ6~l^9fD&%8;m8Z+t*FXs01i)k12#i-^9yuga*M0yi86(|e**k7JQbKj_Y%10HO z*slE9%W#A<`a+T(FaTLo8ya&OwBUJf&-?{B&#oE;A$rLs19tC*i|EgK2)dmYNolsj zBV1RiH1nucfOH`4J{;U3Lc+jA-;RkDwANJhGwp!&YVr6?#aVHPdH!acOMe$ANH|Bv zoN|BA;Oq=kC;UoG{9wU9Yl%NJ=CiF(($xx?Yl;>5qOo`vtK_^HB64kn3D?WfARu1Q z)a#V}mjTWA7JmzvhkqNsVvBhw=Bv#rjJNyLNi4}t%vN<-98IV`*Dc(JEjcBuyxu1Z zd0o`me&sd!76td&ymi|yY^NIWPz;a!S#vR=jNIAI$mYhrX4?78c6a)ZU5`PyUM<qp z-bI>UBwAB!t-Px>Pb?$Tk-T?+1Ji-I0eZWTrSG$oE0sDz_Kq#wF^C>vmlS=Om)Rk* zhsx676R%|a=maEru}owO1X9ES_AXSE%eo8DD{cb4>c8yGc1Ac`nST#=LpbkRCNR5j zb8^|~Dr2lkg>vg>OT?lsFSA&RkDqH%v=!!ZD=J(Quk1tCh@rR3X`ah#Rsy9S-IPq! zo4|>K2i~}TOLSe55?UI5vR5@%@nv<nyFH%;WiC7mX#|I%qQsU@?8e@&*pl(^n#i%v z+ukJOvr@tu$1XymcQN&I0m2Z=gTB^$$Ipip`D4j?v&df|o6aARu07BEDWPb@UogZ@ z{3<3Mblu-E3Tsb+#peHY9F!`Az{E3Th57*X>W+7!db7*V`Kb9QpNFL)dyLDhHG1@A z6ubTxnYFaXW*D;;TjkZuOpAj@ew=%1w=d3g3$;HVP=6HGrLNO&YCtJ6tBm~H;YWCz zO8D2e`xC%)zT@XSZ&;g+<mnrwr8jE+pS9I5|7xp?bzn+n$%tZZ0=Y24A}o`Y{$|i6 zhG2faa<mBUf9g9?$+?QqWwxs}=LbE>abRO^0n0<8Ob|q&ed&{Xf*8bkL?eUNAfaTB zEo~gzGP;uHDLu@jW7kFO7e_T-cka(s!)>$c>T4%B^~w%wz;hO*UKyRu;^Bc@MK~Kf zTezTL7#C7u3GOwl){#373~pk6*|qfAA&S($`x9iXF~Bdjg8Kkd9}nFec)TT<KK9-G zAI<d+-NWlGkBXurrNfMF%(8DE!GC4oY0o2MFW)H2e`P`_tQ{>bWNw{ExO^jjCP~h$ z-|s<I62j<EVd9>jmn3ri<Xy9aK%-JEftk$a<FZy9acLcLU`0K_F1M{Y2<k~WZ}QkU zArQ`^1Ayg?h-)nb1a2X7K82c9<8pj~wY1v1Kxk8moSS6QnY=epNgy}lAJG-`ujs1! zU(uCBL?N(*Rf?PSN`2cHTVFNFU9Ldq>)u0|L%#bwR5gFIf`IHHBy2pGe}8;*$^oc3 z!$?s;0g=O>mvXFo(G52hHi^&7@evqi5b?^yQav5Re%GF2KD>A13CDHgr`S1gj4;6p z!qpXrEnt*{hAKQ0bxO3c24vYo(VNd_{+BFEeOPNlhA!zk$MxhuOSSHApa~CrCUOB; z)?=F^%TllXmStPrII`?M*!^iMj^|_}^*7*dq!(`luR&F(9|)hfSma-c+AR|3w%!|I z)~%=lI|7TMw^Z!zqM6f4FH7`y9h@Gy-TvZIKIWnEu+o)Ua+~~BAc+?EExua~<A7*u zT3E<twrYk{qaVNtH_+udSHL&<KWy9PUI@2%BKY_elsauZ_gjUydF21*a&P^=;-ml> z5BgdtnLB*JUIa#vV>;t09@sJX@eXCn@Ks0Oot=|Bmr*Cxaj*I{t872#bs<MpO_@A5 z3G%oDCQb`cD=q6AU1Eo0%zi&|?!O_~;4;TdFd%mT7dyoDHFnYe9FFQG7YKWnGy5jZ zrkB>ey<T*L&1J)#Mjfg&h8EmI&1c7y3!v}jVa0q4f;(F)(Q?~H6pz`-T4ah&;XBx7 z;>Ba8JkxEKYRb3wl}LP9P)x2op5}j+%rVY|;2ghwu)<f*cx$nIZz85{e^i|3r@_@F zmRa)fMtksiWhp!6PFLH}kLb3WwP0c7W?!Pqz#I<_{gBhf`G9BSo`=Ob#TySqOmFcg z;Ki4|zpMnWy~!KsQ*nD+l%iYf+a#Di`-K28vB~vND7Y*aI<pnio}aO}HTi*cqIDRE zaV0#sdjtMorE~0sDJ9j<x0#kS!r;X2um=1uabPm{oVk(qM6S3dbPFz?;M=EJy%_H# zt`;_vj_Oh<m891hy*^eojM$&*PaCamwi?>2BW`ubtNTn6ol;J;rq~JU!kh$kU``o# zt{!$;7N#UON$l0V{xp<zMS%C&&P{FR5FHP3b{8ME4~trkN)b`_|B$RaA4Th#rwmkG zir!q`r#MHTSe0p@m;*q8fct3A-W<J3dWU-Foe1G(?VJvvF4);$*1L8Y1WSdX4q-(# z_}*~f=1ARsAQ-*Nho2pL@T{vfV5O4#;OF_43ko2&oifQw=YT#8^5Xj<{mkomfmW@D zJN2=w7o&a}>0VAyPx-3mGZ0#%4~9TtOO1B~?<`!yl^zM9ePUOKBHowlx%2V0+CDR~ zBqs4m)mB$+NzElG+ub;KOfMZNJq&$TcnnI%c+nTy2zkLOSABwj<4LM12d*<zebNEP zbX^X$n7ljoO;lwk)OB&^IdOpf7KZ$m<2pHj<Vhj5j8V5<NbTqdTSp0QxRl-&lq;j3 zgIV=$yU=#(iRH8L=uV(`BHiC9AY>2(f5A0oy|+zaGKbth(fqG6fz$hF-(~UTf1WtE z`Yq26V9sCH{UZ@@AMr_NVW`EIRB;b@b4x3V_uiXZ*wy3DwQ>S`?^3kXp~*4<>-nne zH+_$#hm8^)BWPjxZgkZZfy2)(nzifP$ZNbSs3cR+H_+S_u)gb2e~&*Oj2uyA?0gKB z?jA!$Z7}~tK)pq2Y>~?Qkum{^0*+Q=%h0p3X8jsnTjh5+G0=oCiHe#)uY>;XU}zBm zn0vUW#zAcTsu^G7O!_HkE6jJ$k>}`h<rQ;Byx68|hn?|XJ8eJ4WMnc&c39r8C!Y3r zY8^V<7izsTDah<lU-`&3_eY^JkT7JsBDqVUSeIL<h7<W;U4Gq56Vw&kwqO6+ES9LZ z(Ou#*_vNmL>9pN_>Lu&tWRqW)#xy+1sgb|gbPw<eI^np9J^VOyYvFxF{(*Myx5K4# z73o$+AivqZAIGhYoE|xSO>(Gri?RscKeB2@fHQ|I^Y0IaEW&e^!cr2jRJ+>y)+8D8 z6&>Ue^A}+j;?i?!(H|$R1ZtE7!oJ+Q;ZcORI5Wz1*Rd6$H**9d7E+Gm+uf{NM+N4W zDqC+Z8lA<PE9JNzq*3qZWF6aFS}Supc;v7r?t9^_%|%fNdKkS?J9azfbFLoXLA`AB z-%ok|33Yw|GeYe89ZGr3kJ}v@4L6j#yU~51Hjo1KX@9wl6E`}5czAN@(upPUuZf(+ z?UW!!&oX>tn_;10t!5udTO9ec^+>Ly_Nb3N?lD_{41O5yTAdu;IO{@-6XPz<a+6MW za0M9)a?}}}4&eS^%U+XioVS-G-{nP(PgvhToUg_nHJTfr$NbYI>rznKV!x?%;pXs& zX4BF^ODwSY{)uQ?(!7FrLg*au^0>1ub(Z^wzk&lJ^5op5GR8Cq9R~$%XQW;oOQ{kt z&66?fUj%D1a_k4g2MA^I2SZ5r==40UI=+1#X}}^=Q&#~Av@cpAusd_WLD1y<&sF1V zyw|WYAd{fva(B<swGD{-9nj&!&M^hMjQP6g^LjH)MqxlRd^j;ZiA^BP=Y3Pu>o2bT zInq0@bd07MFVFx`)(le@?K#$geqI!;LkmYa4=0$nj#O_h&#BPT0H>MG{G%w#rzND| zNYKL5xw{h+1)>^jR=BC7f~sh0Y#+-=T+lG4q;aa;HG3ZjkjZZE>|E3&u5lt>A^%1j zXNUj77u{8Rw2~K!r9o8f?INsv2u5?Yp{pDL^}1>`F`7<uci~=|wK)31b5x6b;5u8y zKfMx;hfZvKDf#0wuwnrZa>;Xm@P;2>07Rp74hOZnOf|_>j+y3D{=?1$Q7^-PvcCIk z0Bf&BAL~xUU1fZ?bkqaGrD2e9*!$Dk)U~NrSxv!YL58!+h8XABflHs39f5`R9X=na zalYR(+E83j&An$@de*ZjLQErXe66=b;yNQiGtj?zmfY24bK=~?aU+AAe^>?J`%t}o z3xl^`e*UCOI@j+>wcBXS<KYn}z1y%f{<7&j%bV&Cd;0AxKX%9_=|ukvsyit65@5@? zk!V^=krMk$3JbI110#NKzSjpY#BF)9=6Rw9OHQn0sWk(RtNT<-CcdVB6HmivGB&{& zp1g<kUM-JNw9j;(@l}z$NYioHL#ZRFHMznYZ)A&#$986v`Qs^mv&n)Q`Xr#0sZ1$Q zN5uy65uw8O%#pDS4>Oi-;@~!*c(?}4{O*A3myEgVY-Y~8AZ9n{q2*xRi;$J=;Er^e z@kM!-3+~;csf#sEj~b>HH4-r-dG|vF<W7p^uleAXgZf0iuQG?w^I4ykXq98~Kdvd( z%K!y1Ikk=n+A(z-g3q9I#-8kfs^b&~zxqpPohW|b(TCbypn%JhU~U=k`~Lb?U@Pd! z+Cn;uNqs)XRR6>rgr0S$68&z1;~|<WZbQ_q{X<0G2a}t)pK=w7Wi6&(>!t|jGuE0? z{rX;Q+_n=Gw%VVI28MeDWGfm{GCDdsXK??tcI1;z>nA{1>Usp=S($(WtO=G-z%SoX zv9WsWpd2@N?F#D-0u@Fz9@D+eiG19j04!{mu?b@LUDNiume@|>rEQcc;9=JI5yUio z1~fHijhGXI5_t&>^g;{}OYlJ})9G^IZe<U0tdw$*ji3MVSidC*J5qIcH0_L9bnS0H zziePJ+x%%KLQJi6?5Nm?ySvyhKeTPZkGo+1w2U|ZnH9)RsF=!5O@w&&vE&Tnsr(O* zqLjx5V@_h0;_h)1J|0lGnrCRr%dzJ7f$aGY*7+9z^1FV_8g1<+a6%EF8o1>Mb7;)z zQn%I<2Ai^A3;tr6r2LN@$|<DFP-o)GefJ>|Qe>lbIA-lSRypJ|==+1`D^-_6v%zph zAJv<KPosE2xsaynSy0e@ptCf)$UOnpmVfP(RcVyxAK(~m@D3!b^VW^jUCxdfbRQ^o z!q36F0Gn4U1<cZO)VqIeqW*M7Y=Qq=8qWEIrQ^}K!EGbo5dx67cFN6&m<foMF(l<? z$zp>)f#6M$p@q`M9aO*~C7sy?-v|4)U>z<Cptv(wWERoCSQbtz?2OlR2k!ORhO?v` zM$Jiblg4ZavMZ3$gg9CfrG@u!Br8;7y^EH!T$5k4zY`eIiTpeMlB-HgPNC@Q($cS3 zfVp?jUZ?-S00Da^P=D^hDo}?ar~ybjDGis!n3nWhmw*S>!2#$i@A&3*jf*;>T#L&5 z>vG=`sx&y!ymx6b<^+ARczz^K4i7gMrOhY)po-}|VcI8O_JNZ)q!q0{zr?$a4p^60 z`s;k<>xZmp^W`}{uCHXmr#XT|!`Og<T}GEFikD@#Pz9`8?V><}TEy)Un|51^4RV{} zYqHHQK=f2eLNgZrPpFleb`dLG6~P|1BwTds6HwQTLX%lNhw$2q?6gM@STuZ+kDI_j z#)S8IvBZ^O|6Puk*osJQM1AmrtXFq$?Q|wa_6k>17~zMv>#93bXB36_X~44y33K)* z<uA5^*DzO*_z|y$`lJU>#|I9v+G4}gA-y($=XIq^XpeqlXsVYs(J$bi!rY(zn=%xI z9HL8G_TQ8=6WYy+0fdIk#eal`Alm;$XyEf|SOsRvk85}`#d$XE*!qvof`=ML{}5Ua z3^(UTa~Qo_Ndc1e(O!U1J!Cf+!U}1V8}bfo&DQW$0tYCDVn!lcx^8aBJIkev64J&9 zw-$vkqdViAk*@$K$9Ku%Ul?$!DO(n`(QAlQVO7_<yE2xXxKWjMIXhE~j^M$#?`=Wk zi}Eg=uryl|LEHltq31w&fp(8wOtm}l22cS$Prm!Xdkxl{#eC##Ye`*I;EOCw^&Nf7 zT>&_`+1_PbwV5`ZA)a9D$eKXd>x54@RR%Sj<>MfuG%_q#bW8qY3u89_l5yGswh0#9 zLF0O;Eja^Nh-|JWrheO1g2Cq^Xhk<-THIWR)y|9vLai1@&%pA@-wG>H7)>`<wjUOf zCVe6jUcWrbcUhS@M$+6fV_yT1DI=`<CxsoI8VR*?(p}z^^o>m*0zb>I+51$OuvF;l zGf1@_ZPGXZO1;j(3*uB3Zh7@gM94XuF5QzDi9U#q^MC5xdd+*z)WOHAtHrD5t*WQ- z^1@J8v8P0_t(|=C_NDin2<-o+NW}tWp;GHLrbCe6X1>VkV*MM*jm3{G#<%TQt`Sh3 zC8|a~yqCL1^Iwkar5BhN;K=U#?1SG7a4F$i-$G0TJ4eh{R+F*vU%UWC<4;9LF?Y{* zdCVUPwGz79l<e4+B3KC^Xq+wO2pSc^27+)0p7SGqJZm^*NOCU`Vrc}!NFwQY3rOvE z8w`5LC`DZ)@W2jzlmDwZ4@GI)Lv;CEL_TT~Lxvp^4XppYDIWtMviozP;TJ1-L_}QK zKQ0a}r=$QL5q4WyT6fpw#)&rNnQxMcGf_Ok$S-gAkayp{PBPwNZB;2MaRT7i#f*ez zOtHA{J$OE`ucJ8=0|J$%x*y7Yi?ps|<Y$#T+TIFQEXajq5?1FO1wrRw7SCuQb2=(k z(9Yf8?Ab=!#jocG>beOS;eX*X#iwTbtmcNjBu2{gn)!*gphV{IVD1MhFgwWu2^m^8 zf^+cQd;5y_{D7KIroT@&mgIoXCV_J|nOm}YdnTKKrq-@>(pGz&<m$H+32Je7b^ZgM zW=<sjsky|#&-6!tR~NJ`a3IQ=`bQ3bB(1Uc4BAP>tnru{M;Q>q%zspkU+sl1h02BT zpQ+i9ZS!g<VSe$JOJ$pUmw&l_Q~NilcJ}3Lv*BG_><{^>ehuVC``E#nuIfB<^TJOf zNH>U8VOUGQVh%7Jch#<*35aY8`Yk?7ahhtmDH~zea;yJyeuc|7)y;3js2ml)nm}&^ zvTY5(97_Kcn<%p-949{a09YsNZ|*qURffe)7N5&@LsoE`_7pJ+c5K0d1Gas+jw_GO zJyP1Z<l(mcNDj~AEK8fo_As5Oz+u?MW|+NSqk@+UKRxi{5ay}F97SPX_30TfI(ff# zWTx<@^2iizk>tEUAFiGnE!#t^6{VkV`Q2TH^8t2%84v<QfodPgaC(i;<bG^ve<5{w zn{PCPwPO<PQ9oh+5>h+WpFKdcUy@of?njsraPR)3ro7>(Da;`;M1XQOiR5v1F2H}T zraTId2q}Q@8wy@gh9%Z&hSce`7N*L%eOqdr44Ca`Az|*x5!kbhs3U!~B^l=jZyO1c zS(kyMBsBK6qc6ZCfGY6!e=@PVeI_tp7#|m8cZXi#&>C5{-*@9}#U69Xo(x2tH9Org zvvI_YUR&l^5h`o^+a(7^)a$y6_(6h$Pg?x%v!na+iseeUl%eG{KCSWt>l;RLFG(vn zE|LPs<QR?^_yF3Rz_*jd5pRO>IpPi1LxK_+TNJD)$c_CE>qhkYmvxh8By?CT=)*RC zz_8+KIkjN|c+WIs@0fRzg&sSvVr)0%yK`r9#8~7|a%Z3$<0P{+9?$~rQ4R|&v_!-M z=fC@EZ2Sef{}xom{0n4v_oVO7k2<PeJuPAy_NVnyN>85#&iu3s9UPhp9YUQBJF<`^ zwW@Psdz%yAOZgVTwibeXA6*uYo=SeJ`td)WdPkU}T>DEu@b~(1&)ddCTx_lURio5c zcV6-t;ns*WB5Y-3HDpdTd}!NTG+RbR?lv_0|D*hrbr$?@kQ<Bxxz$ekbS!T#JCO*T zao|f($)(`Cg?Sm{1GMnP+z%%7uDT3z4`Bb$yHu|Vj=Ttce<Xf3*)ZgD%^l?&sh7!@ z&*M70ui_uiWM5LOSgtNA*?8uTm6^-_Qzx%8*>%rKP`H*=?$dgL>|LBcmeN+^-n^^D z(VWLmgIeCDj{B19r^o{+nYd-?L}uh*0rC7&`&yGLrSH8@fXW6R@Ies#xz?4Cr}Afv zQU#YA%w0l?Mk@g;!a(Sg>r(L%?=(JzZQ4s1D3^YQc2cCmnmH?6bh}5BXrM0|HlgFm zcxsrsG&4Dq(Pa>mgFXxYhhDpp^$)#<<S(i(*>4HK{^r*x3)Szc=NYC%&uC2xbCErE zbw_fzCIb9^#QWt2wY~Nu0<f-vwt+MnoH9E(+NXPTO6k{=<#=7xY^IK;SD#vkn0;8w zVK+sNO$|!D%IAcuF`USdsN3StYc{OPQR)<~)$7k;HYJy&=6-*SoypeMYe?tW<@+fx zG-FEdW;Jbv_SXqiUhtXiqvMqLp;g<@vvH9bM9h>@j{(1H?_}HJ5E1tzq@(7b8kRga zdKTar4&|FcL#}n9qP=LsdjEr1lSCq0w{8$E_LJnis7S|*jr@dbaDtfe-=8Lb!<n0a z5!7$Ih5DA*dc`PdY`us*-AGg-&A$VfibkfWsOwNo%V2_Ijy8$_#FWwOIQBwt_u2eE zMmJ3{_9C@4OZAS}_G^`ydEb_6x8WAQXzuiV9FaEYvXM$GKBgEz*>ZmwM!8sKxfI#` zjJ;jS&q!$OQO~i8-Ao8>*19=!mF~^jGZ(!U+KLk^9h)(q$l;-IP__@hQMQR(YyQHG z?CJxB4NY=Ud|t`-hG$RZ`Kx{OadVD(fOISLu3vnJ>O_i}w#{;^bOul?4oZuv?R-g+ zNUR-O-ZeAD&g)`5`ZWEw3~Fa4U-+;p9S487E8UV@Eg-hinw<mce!HHG_OXitlSDLI z#)Rfr%i*UTF&OhdW$pfzL<(_YAwA{VoSXDWO5W@@T%5hss<*P0AEbO36No!t#W1a1 zS|Rz}Gyb!{rz<&HZxD65tTNbbNh4mhwcfLd*1mRn0P;I$OyQ@rRC}d$adS*2*o0A| zWlM=walZJN(orMIw|lO=GiSkq%LY`vGncjJ3PI;3D{|>mH2v>|2QGbp;5Y1ZQGopp zSK8`|*TJ}34JZ3%gP*(C`$uVPHf7H_689J_f4y$i1=bnO;=NZRb<d)bfpjHT|GaMW z@Su}L;vIhC-}D@vGDQs2(P!f2pB3;Qv6^xjzk4C~Or<*wu;-XOUO*7BbNs;+xz7z_ zE+)9FC$b#I1L}V}zW=&L@5M$C0LkIVU!!yKG5lQ}nk=GmZ{O(Wjz`+M_8M;F(G$$i zm{C{y<P^kz3ys<sDqCXso};F$HOK7xC!gx&+=^^bJ+*?km0gJ0ve&c$`V|zUU2$#* z(5Zf(5pZLIS=e4lD&a2{bW<(Pkpup(Z+^Azc0YVcLu}mYTA?z7k8r+timH9S8$qut z9++Hx)>g8#@~t(56u*|OGu8A@fivKD-vC7v`qi#(ukR8^4r=G5Os1W7G}n~)R<eg@ zZjYRJTU&@o64P52O8(wi)3IbQjQshk&~MjI6F6G)_Z3vbBqonkAXjP`^@sPTGf=-` zDnnQKQ+t47={Uw{uC3DYob=-INwE+D+S^?z(Mr=Ogk=>8GDGdhc(S>>QySoxh=q$6 zSj{3+wD#=D6XX9QJ?mB>)^}rlb%HZ(fD1QJldSH#wL!whkDEe%{l!}1H+_=4`n^4o zRze$c{j@PMHWDr{=s4S6_9!AEel}&NNy25m#+w_q3FI2x_fDEgZQb3_bx+KpFYF{} zr(NxAMbi_V#6)3xrK-rKZ60~4?UoVx%AR<8x8JnHZd&Jd=Gv}%;E#%>!D#x|BR^u# zc9g{__Gt7I8MB2Y1OXt>8#z<6gBtr0ptLR?n6fZZmh7(GkR^`M*tk~fKl9V+Hh`aP z7qq=Oi*)%u(0kir57CO~W<9M&GY6F%zdurPTzI5NY6N$|Hi!BK^aUwzp96Kj`u$PE z9*Ixqo?Im=cIsBvLdY?`xV;K{_{<8c#r~qlO47AP^k&Dip<h!a-JLjr<!kP@j89q? z0OrjAPR?TU`tK170^JM>*5r<HmKrunUF5or<q;_hd7qVT<2g?y1U5Q`V=3NJUtp|n zdf7+K%U~ofTMhA@UWlBGu}SLk!SBsr{FQH+8$^6(S#yy=#b>L|+E%Jwz~774)@zE? z=jjG3N=q_&{WzW&!K7X%Os&n#J8OIH(XgoGSGz?XL&`os;~NR*eTl$kV9Xf{Ss)5` zDTI3I8+vCaGsy_Hm2nQW)gC&xqH&~YsVi=Y|8uG1j>n>kukrdbPwLks{-*!DbP&9C z7X2%_ZvwBS0ri>T+2A`>Gww<L@|xZF&GMI6KJq+wqNeHdggXhVL)_WU&XG8(9CS0$ zoyf0$F-cQ{jx0g^Y-C${=?sz|*!opiAI<f(7@I2z4Ab*vimJn3wnK7?Wmd0xMY_At zM1RQ^%2;cp%r97P)qS>5CItH+z&|-~NNnTSr|gJw$bzQ0&KeN;y<M2lUoq%@kVr&W z8cP;XE}+MXqyx(T>G<`WVqN}3XX$Y|kc@p<>9AqHmKi?3ah-<Q&M9y_B&$m&2z4kP z3>owvnN%>sbSkC<-zT+~%+%O!{h9-cNj{=v3w+&rl3yoBj$K}EQ-?we7Zw8Ez%mpD zykmw9QtRAc*+&TE3oZ=UU4B0eDmicloy#cG8h;${wBxNNv;-FmO?1+hT<zCcIXd`# zpeSYZA;bMRp~d7-!6IMC7xNRR1Z6n88+XC60fV!v))1fgz{iYfpH^TC@aBct0wjnJ zcGa|XHh)*{3k|}~1Lpje=E?wbCb66T&wB|yV47xrcN5{s$jNwPM3Q?t@V6>$0DLA8 zEPym9UdlBefZ&65Nx=gUr8R%6fD%0dP68fE$+@m*eH+hZScu4LwC15ga$KEZZNl@{ zb~Wf5n&dTq>k1^F;cY9trHwQdUun#Du9o;xEF|}449=gvM(MORJtgw}i~*w$x3#(Y z-Ury6U4PEYJ*NTO&gC>b(rLXoHwG!)WF6i#`i{xc@#iEEfD}~32dWyGVxuC-tpES? zL1b8p|MYq0i{!EPoq!+dLrXn*pN=dffl_0oyNs%4Wz-nH8oxrGf$zd>7Ai$`KV%;% z=7K`TjnBf1-WkyuQPw{5S%Fr*l<8n|F}&XsgsfO-pKXYHRa8mK4=8tm;%i*k6vA{B zN3VS|<Z{)TmWa4PC{oYK@S$$;)!wnK60@pBlTjmq42mwk8qvpC6dq=zVsalXEDYxz z$zbi&RRYxu^|>3Y$EYU>_m~?8$(<YS*8)k<*E=E2f<vQC+O)x<$}7)tGOo}^wWl8B z!)dAo3l=2qvfw%HE5a-o);g<z;s*0FxT>s?15pekC7`UzbMO*Yh$R58Yzr{C5FdTA z337**c=QQy#)jmLn9mx5Z!4t3bg4gYo_GEE%_!bk;-u;Ye^^w5PZMy<kcbG5J0f+a zW47SZ`L<D2xRT$)vC~o5@(k^8p3;*Xuo-v-`l^dQ*ZvA2r58i@A&jQl-X!le6EEJ9 zEH^gVv|RjNvJ76z>cOVLQ>}{zm@W8>_&LD~Es??&rj#gZ`n!&hjBQl?yPjX=j?5SL zADlD^oozE^*Dij3UN?Ja|C4sv!&jnPdevU8=m^VV3D}({e3^?$=J?`9)o-&(E?=+Z zZ!84LmosN`yZS@c<;!_x@!`N^D%JyUvOR{Zc|s<wHJ+YHur`x^ThCt|<I-Mmy`Q@r z>@(XrH!nDc8z~JQP{<^+%CSIFA${9eh?VyA?hU*++#tD7uB;=Y^>iWz>sORl(%`d< zQudxMZM4!D2C5MF{~7fD#6E@4!vtS|#}w~(>JQU=f+hX>?&Pom3naAf%_zJ2rc|64 z)LSIP&f^DXOod&)<X*9z%o{yXG1+M?y&&`7?t`QNp?7dc_S@w9Aj=zBR=y$Mip)`4 zxh39$AcWiqqZ2ZFpUdX3pEdjL{BEFVg++%zjT)GzNv0<N+H8xM&ip>QT5U;-V;@8I z#9d-rQOwZ&2%(~L26t<iC$L{pmgc*nY{t{Y9HKA56mL=cm?Cw!GI}&eVGyFbg0wBw zLTvDGWw|_u@f?+al;spQb{HBxTi}rmrUR6Hqb+wMT4)C_1eErYT5|83;-#zF3EKGP z{suek$hk7p61|2}y$RPeWXb~f=X<tS0q^E_%6E^7!$adEb%32!_X1;UFn{w_OTm8% z92>WkRx4AdEJy-S1su0m)(drLdit;X#AOCr0sv&7++`qKl-3PWg6V{95!}|mW1dI$ zQFu(@2(o)B;$$=~nQ=Y9d%j0gE_FmPGf#y)99v}Jh~Ht4<<v8QXOljojYiw&2X`A9 zUKcT0sgW65bW9e5w$=!A4N_HQgV;H@1?_Q8irHG0;j%AbP`u0=_NpngUjApl;`T&w zBy_qscuHUBl<ZEwihr&mfyawo(V3PDS7}B!1OeW5Rxk4BUA`SPXHM}M;Npntf}e&V zQuzfq0}5LBCTe6+15~&H61|%a*W-Q%uprf1ceoSLiupKGI`lB*GC^N61}NZ9p6-MB z+BZHG{D5fhH>Vb+4LMdBOR531;v<bxgI5c|mLZvgT*g?cAxrKfAqvkEl(jfM53;yX zoMA)3ul85-ZEiP|a8X^-%9y7+nC8OhcSYbim;RRDtwgf)F!21MT6yqu3C!-6lf-yH zXhe0F%QI%hy&Qjx#p=!h`?k}VuiNJ2OWG-}N-``=D%|fkY7t_v`O|z`4So{^?VWUj zkS)poWEzX5`TU2;Ge3ZE5nBncr!PD_<OA>@wEh%b6r2*8TRJcqXaKb>AXkAU2ph$a z?8w>-Ho2|j$Ly$CU(WS^5{(5`?x|y1f}MunF$?<{)qdx?6XwkMlNQV{OYb1Q5qVQ1 zqgAof^-dk;5M>Gg51)gdU+T!fGU~53E_VB4oX9<MDf~6d!i&v;>a3TE!rD{S0<FS7 z#<Z!Eogc+#3X>r-y|qeDA}JS7Ice;mrto1!7PGznRep2GOh2dP?YGt5zwnClNP~sW zl3H=f_Mjh-**fQbZ|~YZ#@}EJrHE!Eng4w(;Kq{yd9|@oQixQhImLY?seM;Q%I!}| zFCji<=i=T6Kev&N<h=dknFw7Ye#;|>=Sw?phMynW=!M4R<19%}mGfe}dtcUf+9TQv z{EnX4;RfFZ9sc-=YwT(o-u=rK?@R#u=cxO_o}0;D9BWU9!~-3O(~(7ne(#QR->v!w zQ?N1w*?TJFgz@}%^Bxf0pZrVr#db%zS&iTujay|O8s(BvOCH!$MaHG=rq5G&Lfs#E zS<Ltm>UGt5LrB(W2m6Kig@5_J@^joh|K<C1dl+*&264lThh8-2BGXwP*M^(sb`fc; z++)W3JQLuLBeE{B7oX0)5kFXa{N~<VJvY*4V}SPq8$r_;6$xBUei|4lH~Qe@b!+(@ z#s&(??_M7m;$1f;Z*J>Q@6)|oQlEM1N`QQT-X=A6b2HP!$Zl)OnRghT_SuB)ySOs* zXi4~N{l#bU!~0b!)bz`In>b-5i`wbOeCoQ?jTm^!b@Qf2(l)C}Y6-Re>wRmL;FO`% zw~ub|yVU#j{fgsEza9gXnS&PKpL_vZ{prq4P5LSoT$eFXHr#gL^$%5D7lw_@ZeSa) zLGLUmV%*%8yXi*1D$gEvw#3xmn_b0!<1UHJUpnk8r%0};N>>~jSQa*RULv;?-s}l9 z2yv;v*%d}xxRa<?1uH8eJEln#XifGbUk%D4H+GwwYwy#ctL~MNHKQIQ!_^F@SDpAp zM$?$bL+<>0G5u~wybDNZHIfyQ@)Q3)7`9RW6djr2*KSU|_?2SG5HD2KcTW#=e6eau zd!u~8BG&h;$?l|JAX+|iTlug}H1jKC_UBBD!!?+Zij}0@5hc?GizVR@{?F*}<;)Ez z-MsHIv=cz%9L0+kDnF*dtF+y#$4vXGBWH{590&kTXMHhui!vgui*~zlqM-0nE9K`u z-GwmMz7d!IosZB6ef7zBFfJ6x5f?U_h($!_pVGf!Hjpxa4UZ%NEY)S(1m>ImHTfMR z&4-gCK5hDVyU<rL8_+8-aMv9T1kA?Kb90_5h)98x3aVKXSr}LN#$vFg>Ai)6?`%cJ z>F2N7bKPrKwU{fQ3rs@Y(P}v;OjWisc?5uImq=s)rn<60^W-mUe4?@Q4tnG1K+mB2 zX<B6naGcyo8ToXc4AuR4p|`i)ym%EV&D(d%tWG?^v>MVXjC@0VfST|gFcHobG}x?l zgBeWVM{Adx1+PG4y&hVy7dxg*iJ_8NExa279sN`@{vYt<r8y$H_++HDPFfE6R6%{k zzJm8m$@<x`Jq>z*km#ZYdfG!{WzbTJlvOHWX(CG-Sv2~LL+F29(i#PfY;>6~id)@Q zcHZz;=gP{#!)MaCgoOSWLbXuc{eSI+B0Ed|VvYbSgPC+|9Arp+w0=-EE7R_N!lmgo zNT#}*R7Cvv^@bJBfL#cZc=<?FZ43Gi{N+vI?vd7tDqN37z&&UIn6y)!v=Y+gOy%bF zs<)la+C%mbLhSg{l_xf7BNkUMlz-FQ3B_VhE4FgF#|tZ$Uu!K{QsSdD)om4)#(K5L z_gvG(3d0&rD#dq&pIGqj)uD@V2p@dN^L(;RZeZl|w6+iuT1AMa&2bNbgQyCz>|+Kf zvI7d+afxNU*AGNj-^uOmZd~bP@iz%0rf1sYvHUj7!KeXs6TI^UTH+#Cm;EOz>g*0R zaezBVjRdJEGLp<|X3^jmG<NLX#JFB-Z)hKMPb@_24C`(0vf6o{gg-hB!$Lx5ev<FC zvL-y99sQ|9n0R<BfiEdGyu*91C7DbewH+Hs*cr1@J}<bm(0SgMLHk1$aHG4i@GG=i zt;Am@*h?w20Cjp<<D{xlr*KycLtOnm0rw1FN%ByA;m~&g@Ol97#)Vrpu;sbkX_tv! zj3vYFJ5aWSPeZ88h5U)du~k3o^ZgqvN$yLatnF`aI3DWD(ft>nK~rjub^XJTet`DZ zEVIG4U~##`ApV|h)>w^<F;8Pd@wQ@;c3!S96g63MtlvG)a!Iob42RAOhh~NRqBOZn zz?KzH!m)O#2~ur3aE2^c2=+C1!7Aj1E#OV9Rsnj#;znI#4*|P*Yi3sA)kn*Ik{UUr z1bmtT^LM_Qtz`$vg({p3jTSJis99qxP(tEK+v_<Qs~Zgvc5j<E{9#DPJugcKSEZzR zwbT+XamZa0r^E=zE+B$@S4(k%wetitby2z#HYZ#!A<j@qgIMgcZv{PswFeK3?y&V- zUEy*m%ow%S+YxBC^>$U2{yHLfFpJ|gZ(Z?sX;5WvxSBjeb%u_e>$oLZ#Pbx7_4c_M zDMCl7*JfxR7qfV1u@E0|Bz}#5x5ls9gd)Ipf0Yq$H;f9h1j<1TCf6($jX3xmls&Re zuUvyjyyp-*)^|9ZPU_!$2}f^(z1TiY;Db%X$Ly}YF-LMp9J;vnf}5P>tH(otPV3Wr zPcBQ5;=&p}XJC{6&SK@H)279t!WA2Wt~d_pRAH%GI#fNA2CE)A*p&@D0mEG=LEv%I zuW2^dU2L!p^lVO=-{yqdapE!#BYPGem7M<FgnmB(a|w|-MJN2~@X>rCxNKnY?bx$Z z#*bJOWap2!sn<7F1lrmxJQu?VAvHD5Pbby+9BSb<81_}bk$%t1|5+*q3&dL7IQS89 zVj@=ia!dpOA0YaR!^Ei$4wZ=~B~7`LAxt77x`VmA_7_IQ!>ez(A;C1+XlNG7`J`R( z;RnH3jL8ZQAkGDC_a8GR#Fn0Q6>8i<6`N%I8+MxQG<!F=pKNd_Pb0YL&7%+ky`#F+ zn%}vc*QIw-lUAWvFVZ_^U3J_`Q^N~JH8O?P37FDlGIfoli#}J$4j7qHa^W`0R+2j& z(8b);n&Y9=Ss@|Z&T54a?yfhV<_ynY(6cpJwd&ya{A%0#3WC3z?oLRg<BT+hhu7=0 zdW##4XM2%qWGFjyw&xN!kFD{X|0tr)V`U644@+=<P+0QjNGUxc$Itnw0e7Kk_u@>p z;<pMx_cX*$r)xyLS-NZmqfY%iIAh#6rV^JDlgt_w^FaN)Y8)~&*ee44v9NQmpCnM} zLl$Mnc7Q#ianJZ2@Mf3Kt1;t?Dp|&p@Fc*AJ?Q1?zcMBtcM>X4TjJf(tP_0&*}c8h zx_=8ue>C=C?eh>_XF9uzgu!gbLoRbnOQS~}#WTQ5S+-;6f2TD(IWz|dHTso}6<@$C z<L(76O`!S%v?xShf2L8BAaL}>6@X?wLHHju^M3+jTDH)th0d#KnKHH<jQOrHYW_FI zJdq~>7!JvmeYTm)pK3KVhS9Z=WR=4~CpHwAqf^%TMQ3$Dq6d}@RK!h9WzEP!yM#p~ zZuX5cz&K<<S_P~jj4wh9zo4j4%O8`ErHn7U)S?8e7`%$FNG=ZUw@fSJ>X3TKpqe;l z99uVzJXPN1{arDoaa^nDig6o?|M;v0-Y_XA#YqANc!GFK=r=VWeEG;!i@yrZ?<Q$! zmKZuS)hUgYI;Hz)I^SjhI4~V+X-m+ut&A*HdC;r?xMFwmq?U-^L>8&Q;DvsEc18B^ z&m4?Zuywiu^B|z=UnjCw3$o%<4J4_bl!{*AOxgE!LJXS!Kycz}UCThBm{%!fRa$+M z3eW~;X(|(*Vm(-=R+9o$DuQ^nxsF({jI-6ij7GvUz<_SkB%<>jU@vA0JuUU~NMjtL z`Vzl6PHW&dQQhD<VE71HpP+3lr%q3h@*-dJI@*4FBNZrAJ>!R2&PqjiA>VL~OCw!S z03q`=!L%n~#=<uwJHfqv!MZTdLXW6DYf@ap34m2C94tw2T;G0~t+|l{MBTpSXUVRq z9?f5)(4PHmeg*cRgcJlMmGgqHD}O=#!o`$mjcaKcB+Z18aJxr_5c}@|@t@=HjQ}83 zXu)yPz00Flj8=)uqRFuL%uH$)EQQ7-4i{~CPP-3O&N!k)ygBO^fVUcb{TY0L+hbR= zLMbTFA#rlmjTU*nG*aw<b%>!<ZgCfPnEatWKVv^(@X$pT@(87o*1H%UJgIWn{Y}1R zG?%@ypt3~BGrGftuP1{REWy6~=`#9#I}#&xYDiZOT<_eP6#F|E2Qh1}T&}TFwvJeA zA^TVBtN$cv<0T@;a*kQ87_pp*l!z?CVT#c{zdYz9QWPCKjMbx2j}eYsoDMty>PyKg z>!{cxOcCa4hS3#L4=D|!ZEJ9YBbhfqZw+fy-PV>ir1f(d3i*~XZeU!6frkHa>J5%7 z>wWKewu~UZ=5`vEQ)(i_A2-=IfZi0Qg{j*$1X(cQZeUTih9mz^_|ju1O@EBaSaAYn z64aAy)L9z{hlVVK5pZge%-x8gyR~eOWSSMUluLJHf3hCJYvltg!*BC>#*p2!)QxjL zH4i34NfazlEe|F7jKIv6@Gnw&Ro5+rQfK_5YVVlZix7H_;!-nMN<b}<z>g2|hOu_x z7WN3(FtxVxPoP5dDGBJ#9oC+%YWTv~-_Drv>_6Ra-%w!f{at9Aqia7T&L=etywMK5 zL(lhR=B)aD1Hx#1uKfW30MJq;#`Fee(f(28y1pr3tr#yaOdcCz_oO(oyh>G3I~Qt~ zOFK)oUOa@R!ns{M^>c7Ati;orR5EuW?%a`~ZTJOK{`_}kA6ef3w3&8sW!`s~18f3e zZ+5ZyqsHgEzSG(l*(-CMQLtaL)A6T3#?@N88fLtEusmO5P(~)7d9$QP4>}w4loc;C zFX86*M0t^8nWXaV0A(6R7b*BusQp6yXka|H|9;h?jcNAd0r#we)GE;lJnqf!vJ>}> zTmec4lnID<AHtjR&w3sUxLMaaf6K(b>j}@~o{hsF5ieG**J(4i{fo9a@gRLQ@O?T> z(8Uw+m^<GemR5|gNGb=aK;&EgrwT-3r&SrqaC7Yet$ROcp<nx=^Tg<BEr6GM-E@Jg z@P-dCPX@Q^@P1X(?^z2DlE5#5QX{K0kk-SMW!9<r0Oxj~R>Rpl$y|N0%45&Gl7f(C zzUK~lYWTy53fT|x0BYfIz5}{`#IV0WoJvua05ZLPioH$sE$-l)5!HvA7=HBo6TkoD z9s$VT|6cm1{}*)&-1q+>?7hR9TH1c$fT&m~7C?}qV%dVBs5EIdKtV*McNCEldMHu@ zHWUQhDn+V_bV3o55K2N3qO>S2Kp+t?L<kUifI#>rK6}6K^PTHl*IEAoA#2vmtb68H z?tApP$DaRtU5x*?b`<wFQ4(Aa>i=9S_l~Rmr*_xg!2hW+H}?M^iF5z2HRcXUfI@5c zVZmB=oeknqfRT7c<Zf!#fg$qG?RrZBHM5>KIo=*9x>)_%VVHgS;L;S&!KMiBCSr*W zaW`UwDnngY=@$W?j`+7;*R7NPM=`nEBL~-Orsilltv06PH)gqCeFv~<f9{|H8yr5I zv->(K#sZ|i?sP8#EZZ8^&ntTw8-&<-E7TK6g@@Yy>8XpIcYd-#eIKDV+UeuIGx^b% z>wvqG{sYvHI~xiqsPl#KY%fXLpdH(M^c*H&;<^iRQT3lLe_u4&?#)feTnz-|PhFDn zko+>X%lHSi@0rHl$8TEu#ik@|!4W-R88A%>`7i26r|)hNpQ&EnBcAPioYV`m2`jee z2sMVEFS`qpYcLN=uUG9@bUpLDRiIGf28llL?kemf%>4a(=go>MoMDx`1Qtu}=07=@ z<{-_&csOJUe)Mi0C4aF7auvn_uE%qio=+^(TrD2(N@SXv`*PSL(lxV@HFGB=$)Cfe zW3fT?rLh5-&E~(|XV-_T!}5tQWfZJ8#Df+CS#q{6AKwH}1Eo6~@d>_>7xc4XTiN0) z9Y|j^61*VXGB%K@maDVC{@L*T0J<_@iH4Eh=8k^{7#FR7ZH`3>r1hTsagp8fH>S0N zs!djH<pw8;g^AmnBfl4lHUfiVgXsr%n+w^kLZrqKvF)#~M^^!V<Knjd%R_HY+P|52 zA2>*<SE+H`t#^>W78QG$1Nt>QpoI4(!Dr8G%!Upt<kl@DRy1rT)R;6A^I5{#OLBDz zz5(*rwiQW`2GY{;xP<;IiJs8AD!TURh)A`p79M2?S`;KA3N&L)!2HK3<LcIi-N38x zLC?{j9i3mCy!5!>9!qsEp<is3Beu4?(QZz}pT~N&1%Fx1GAWm|fyH7Ch$in$=fYJ= zb*Z1=tE68|*9hi+#n|cnzEE~d)!j2#py+%MY`p*IB<`=?4vWB&K!3(eQC`n2;lmcu zY$mCCc3mWIoz?mjx7&ZDZevOVq|wNY(m&kowbI1<O+=O16KlgpEyp}45~hs9lvBZ( zq33^D7jvDBOoeL0j~c&mF?h52DzUU}%Uxd3Ip20!k+KFC7!Ty44d5}rz&srW^$?>z zw3PLlS>;XHh^-VhnI@rIEF9LH+0cMx7hEx)`L(<T<&y9v`p0pu8>mBUVW`%eP<yN4 zX{^9}Ma!Lb6HwnS3Dvqpwquwe<MA;i34TZ4PfQQ(f@KwX^bK!*|BhG1_mu-*qSaKX znrCqYC;@nbzgWX{Pi7$H^6&6S{z=QhDI&MbmQ)TS_(OTolAU>FX`_#(mmkC3=ny$O zyZ>S~k3FVU@;8dTXz_i@(jMl0Av=rJ9J$$a@s6I~SE|@~t(4O1tZw_V($kZRzb$*! zUV47*XnuOry*c##PzCBDRcavU*}q<Zwf@C^-qGbJ<lXAIY3Z|tc!7p`qgm!6v%g$6 z#@5KFV*8_UZZSm!gJ%nI08-!uUg0R4{M|oAxV;A13tj(AF8kUmR>Becw9OqWp5Qev z)^Pnb?q|PP1;@@ze5zI6z{TQEH9ht{jme>=irqibed}zXnl^h7Gb_up?Hk&K0)E{a zJ^Z!@43HW1i>hCEUi@|SM+#t2f5&+TXCUevk4h#W6?-BgpDTTbv6^MX<Z9t;rsA_9 z15F8%kavKCeaxQ304c7^k!Ze3v{K|z^5C=G^DEn@-V^!?X3Mi3sW7Za8xF{@g|p&} zIP}gf=F8IN&0yJ1QT|bU&T{C($j#6Dqt?Mm;*f$s@)#qXG(=IZ014)hU`enXtUqmZ zKK(e~ciJxL`ZfWY;nBSxno<0S{`n$_<;NxwyR>re8fGi5kEAq&;>l!-rKk0mZ4kOP zQsWpxklnRc$1MY`J~V|TAGBH}G5`AdLu`TrFTK}x`d6jJ6pZzl@u|FCn4|H=MvqNQ zTA)C#T<`AZErmVWLo&po8tTONeDv)y{~`ZnkNh*}fK7vx4+Z>Lq>fWR&8Z*Xs_odK zy{>wV7WLhl4W|2&esSz2yrIIJ;Fdb%c4<}<^-~3u2!=S~HVq~7e0{i|*T%<a4KF@C zw7%Gn5bN7_dC?bNVwQki!@n92o-SX--Jdv!KjprM4^is9=gB8I-}(uJg<QR>N>n2_ zN(NHkzB?S`1)$|2s+A`mptCeVfz7C@CECiZPl_LxX?0YIA$pOsR0MX*P4ZTC&^Mfm zUX`d+iQ+pVtE(8ctNEtoiA=P%oAT--se+rHP+$FeAL!g4Pp;1<)iv{iT2i?8`U$Am z?;3@JHZsU})YwpvX)21^{zws2ax9SH&cD!dWx*()KdbT~iKgAHchDAs@&UUC<$aZ& zEDDg0Z4644wH*~xS07y2^Rnm-7vkQ^sKS3}4R*HhP;B%Sz*Q|FKCPc6Kiz*c;%*tN z`_QPXF)10DRtoB!T5gJ(Hi~sY-G}`%_8f{GusOmGXZXRQ%jF+&!ai(yKNI;0DlBrs zinj#aXEq!S7f9BG-{(HOul^1dZdyFR;az?KIRv>S)So&?7lHKbkbpp(-1y1+i$Cip zDa;z(5c51agH3rxjl7+tau-sfh+EzsUMQ!rvzwyEEfh#98}lcuL*)Ynia6g|W=z~q z^ZJ=9xJ-0oPp|tA3LUgpF+F`HP^`a35gSNsnlmT;MChMa!<!eC8ks*7MGP`m>_Hq3 zU3YxXP`A&{It=23;~3lACE3}rwQ4k$x<WR8j78|!^?ew(`I~q7337X#Mmg%@64QMX z^JP1x#&s6A#=e;1>|I(z$|RbHfbylmZ5h9b_b?YB5MC$9#ZIo@7Eo#PJI~b~Ddlx& zwg(B}1(7mYsPl_@#kgLx^k!eGc7(F+jXgKw$6G<6eh<v#3IXm|I<?1Udwy;~a<7*C zo?EEI8xrtz3^Pa3V^h53sg2vonfwBnuh;RBl>T)#*jTTKn>uzBcYoXdBobz_oe;XZ z<Wfy0DSH61^2T|g%q#F8+HQviUxiRkyYQF5;4J;o$ECKH@|q5^PSoJENZLJh8;akS zDdkW!(9?e<&aCWRVa--mKb^c-X3v=FA1eFVEx9q?TyDGgUGezw8RqY+JSeg1f;1%9 z4&$TroyFL32Ov8VklSw-KSOR`Vg_#3s%NA}_T!6zVc7on@DkMt^X!MBP^V4W8Z(}J zs`?haauWg(0^88{4kc$RV>+jUK!1TH<&vW+W6yn7i|3)KK?rWIcWm={(lK@S>2ej{ z4|ain?^&=@%3nMlQJ8_ecLN~0W0UOxh{UgX)u9@;Muzy<>yE$Wr<dffUb&FMd-Ex& zG;IZBLYxCdyQZpop{D}9A_t0Ld&-C-=SVg^W4?XJxJLnq%)l+KJhN0IlNaM$yHb){ zy)ySuEzgAYrEEf5l4$S&QA(`S>Dm2mGZy^`{zLHK@^j?&E+<&@xd7a6JWrV8bB-pR zV_N`h$0;!Hnn*P?Cv!8PJf_NYT9hC1Cr*m(j$oQ%DuL>M0zjR^Sgx<5&%_Zu)ov1T znqgV94m_FNVkJe%KL$8ry+2a=&xsy1x1R19KFIsm%Yf(%+#D3WSqih1>{2V4K&{5X zf^TXw<+?(-39m;$!fV7O8O+}x;kABq_vUV^i0jDzEh3m$USoEt;Ud#mb+>w-=(!Co zV3c+sNkqJ0A``b<>L-5foSe0)H@W27yPI76E08gY5Z&QFa{+_TyI?_lN~qOfv*aeL zUpWMec-__WKh1f^^Xx2IRQ)j+>z+-25}nt2E9FB~D=j0vb)nWoowIfGuLpbhxTzq3 z%=nJOgG{p`UWa{_+lcfD?jk6#en*8WR$O$$_+x{TCE4yzb-~-}Rvn;-&&tiRwr}*J zgx!BXz|9(k#%*f^X|D1h&6Ux9pG8B<-QS$MvS=FS$!e)|yp;dnhD_`)w$?9A$5M^_ z`cv*@+6U3sI`tgqT#L`QuY@QrUGPVm7cvju5*V=gc^))gYPd!Nt4-Pbw<;z(Q@exB ztSfs36^1l`lwe5j8*{%sZst5x3Mi`<TMP0tqiiM+g+B9Q3z12G<L3Isz9!&(N?MZi zBjss#n0UAOl(|70b4@c<p1-z(8=NDBQf(UWf{57!_Vx__F5@lx<^L3-+&#$41Ciu* z&Io@|6cf~EvC5&Z{=u8czm0x}J5JedJpGLOL}IMJrkKl|*uJAQGf?BV(e$UawS$+z zw)oHY=VW0-eY3Z95`>BZy+$J$p!dm^gSv><=WUNbqI?DlP4lgU-#_E#(4!GwnFuaU ztY#Icg25O{XW5*qEwy7Wq0zw`Thk+mm$`i*r&hOZyP5VvfKSVNzl2u&y-H_~TJpnJ zXC!|l)Iz;Z+nnoG-H&+rQf>d2%fpA-MXy;kUDM|s+<oI{`=M`#7scdlhE7-nh+rEh z{}Mia_ES36jo^gc8GKHe^1VIr_=v^alRo%n7NaMhVjJkwhb*$i=*SdaB_UZ^tU7wc zhZ#1Ku3<2qB4=udz$)otNLPT52q#Oxv)U3PS4b%-KH*zo!FeVQA(ed@`{$#BsuoJN zjjX;>*YV}t`jK{_C~d5|CKJ#M)o(-_8~u6a%2)Dw6m&i%iXyG6_H2EBmHe~(En#b- zOHX(6tIv#)%-T$ZYiApvdtE|XsQZ3&Ur<3P_Imwp-%6k>osVhSXV*V^AB(zJ1$Bs< z-QUoSZlcQDX6|-^pg*RMZQ1I7AD&#n)hOxGQ;tF)sTv_=!?YE(o5ce?LHkvw>KKhW zH4P;dC`iKuSazM-ty8l#hbC9NO-^eI&%D<hp~&x9gj1J~b75r0w|-todLrad6x980 z<ZR<j3`R3|Y4GixjWsvE=BynMr^=~-uphKvkD)z?rmZd>h=nZkon~7<ub*925TyWs zB`_z-pF%r`BfXO=Is?-h;nh7eGs~lYLCRmWY$b#!<px9s?sA;N!y!?9pSg|lLx*i| z5DktnoP0X*xLekkwinWn*TYvAW@_kT4%fx6xnM?SK}JTyv?<TthGevoF6)8Wmrrl+ z3H>B~ddoSkBWa(S&2F-AOrN+iw#O#&VAx6gXC6~tNb<g;zKeJ-LCd5DI^!WP1X8Y2 z!0muI;fHr473892y!yuy@0t9}(_XS*T{WCkEGo;9dk%35E#zhj4h(_q%J=8m(WZvk zFr70aNq5$LGQF9_ncii{-9Zy;bB7?RWyn?5DoKzEeoq<N3f*WS>?q5A$aq-8_@2Tp z(_J2C`uvuJDQ9cZS3}p9Wp4Iuq&g6#5j9&KUn*y?JdpQ!+s{J|icZjR<jEC5HRy*j zqthdqcWO>Q`nfu2VJq)-oF{chr=l|rxod;B`yq$8N<Diz*HNB=%H>Gwu8uiR_G;#@ zBRG{QobwUC$K-nw78PwViw5dqM*~)SMY0_*i=WqMj#dTPgAcP76*azO%V;lT1~55g zwc{Z60XE=$_q0zfre~%lCfCvUv^`~7V8iLaUft@Xl?D;sZRM1-2G)Asqd=d<VC6S~ zk(GUqp^E(jm8Y_<gF~h<lOGoqL?P!sujWRtK7Hy75=D^=MZhzZuYn_7ou227v1-kQ zHw-$Z8x_yXq)9t~iKoSY{l&M#NjspXo{{d+N36<F;LJu;uGK#O;pI~ZxoHgh&A>EW zkglF;jeH6mXJz@+tvT0z?Q1<*DM?mSSPkazVz(=6<I)zk3$X(d^&0Hgl5g`h(qg)6 z)5>Z!M;wMO%NY8sslJBXa9D1)7))MwDMo#tUJQG9ZMD{gLrG|0$%ioqU%?GTT)lM# z#vd-v959luXTMHd!AGGEgtZeCg`OrluDl3nHdhnmkU4X3q2(>MG~VjG@rcyN!0=gV zVI4%L*QV-1Rb0?|MSke>n^KHryx7>_3)jE0a#ww@j=y;NAAxr1S1IX=$z0Y|{sg6! zK6uMO{|@z#-PJH)^N5N;j|J_4ec(qB%bro+j{2BgnXqWH4tH9gmm(>!8&~{gX3_Cd zG82RWzwi|#U0TA-C31d9v%A<w%EUxUGeBQm_|iqQ`>i``D_Fi74<v&DCEi$}an0(R zjby~k*Pm&3Dh;M*XTsLU`;YB?&S+osJOJBIl90JdsGtp?{AZOPNM^H&jIYcZb!hY} z5><45Cqx~~K82Gx)$x+m60%5XtC+xJ;9EzYya?HxKgSYkVyU}6IYMJEO4k%(v$1Ex zu@&Tg)=q+;K$p3UV>Tmt%_nP~a<<?_cFQ@_S=-DsSM|idnSJF>MRlzYZ?+kZsVii? zxyw2^dr7N#-Y#XU>kF*u!Kz4Dd!@}hOCJ|APu(=4Vw&suPTmAS#n~n`JFIfe_X2J~ z=jr@W7>9m_yZ~MXtNNQ5R^tTo$3~o~?u#SUlQoTUoi?ksG50~=NjMf4;v`gqbkA#Z z0@j;h-muMEx|WeiW2^j6Wp8M0b`_p$qFxtQrSfm{SF+oY`QzBb-jFXlf9y+3kn0i~ zCox_zjrd-BMF-R=T57wDo8_bIO*@YE)1HzNmYCL0lJ_-Dpr&Fr2-&m5Qwi}==j6$c z63+(l)fMh~C##Npyu7fQWEM~#zL0Bf881}J-1KFy_FUP@e8Ku+lSEHs#LeG1AiV7` zk+J|z@&(UW+{@R5RiPcItjQX>#;df;xR3c*Pd&uMbe^5J-J#yPWCOa5XlE}z;|Fg* zb@wMP5A5Te9m3_y4Ac5M_l2WSk2`p*`P|o5d!H02m)Ttxzw1!i&;d6wHm6nJ8}`R3 z>zfTF)4!4q(z`BsijLCt$O<+Gj}YvfOAO+`F)Y*J0=F-vk@8AIp-dyQlGb|n+J3A2 zI?CE+&T~jzDQ{v?p<VRh@z!O%Rml(6LVS)b#j8AroR2}fJUrVqu(sYdhtbh#b@&#M zu#9AyN^5%BK0uB|&;q|`uYT8)(aG7ZmGA<K+Fql~vg@?62qFaTiW*Ish7vtmsPE=k zhQsZvKE+35toDGdhm&>X%H6Y&!#O=OdQX|I>2C<qcoJ+`OQUj?6=+>39&K($nkZM& z(TX=DCq>RVB-o?B#|zzs*V0#gb$8a}`YZTt*vH_s_^-(FL3KMiWqN&J3HF8jb8V=v zjR7yM(bxpUgpz8U^RZ9Yj0e)lyXX-+;SKMSNET>`E|DMm_D(R6WDkQ|@0#0F;W|F< zC)iT0Ymv8xD?c}>b3&M-wQRz#-K12+lk?ajjnWUEnwe?+J@Vr0zKJXBl9GaWMC*FV zk^^fSIj&4g7LowLAk%8R;@cR-*^C7T(6M_0+F^r1UFb%w1x3A=68+6*DluBcB3n?X zW)P%gI{+Q!$AM;1+~=7hJnD1v5vQkVV_59WbebFa^=MM(p(?`8Vb^KLn(?7?P5FIh zc74wIdAwD|WD0g)XfhnTw9&p}9NDsS(F=AvmI<FD1$ix7jjNCNhnw|3s1T(MWokwE z&(Y7CmC`j!YgGL3NpL@kS0|<YDDRM6OWL+Uvyt(K+PYW96Qq)U42D1(Ir`@QeWV{N z8E?HR$XQPpsKx8liXL942hZzi#0;hd)iyE}Ws`mgGc2Q1W{K^)QmT;XdQA6}-)wxr zg`KM0gN~Kn&WT0!c{EX1Ywug0>!nXG*Q!34VbU%<%(y>imRR4rv&ZE<_V$#}YX+(S zpE#c5QMFfx?e(I#zX^-<t<%*p>ylA2==1dEu}6n=$*89^-lZU_180&~A>nq*+A#7S z>`Wb2Drn7SFhLXPG`+B%0{d2%WwDUaU~%7PjYh9cT1l3903|&*7-AHyM;g*PAV2s3 zGGNmcgy)G;ZE}R1{Pp7GMm%13g&#5KdF=ei%duwW!s7-0{ZrbB?NPFp?{Yud`-@LY zTU~M))Hnaj-X=q>G*|FKO7UyyKu@Pdce1Sxhiz#Qchlcz?X%4}W;P{n*cP|p<4UpB zX~L~qYhbik9EMoL!|65j4Ae0@r!Eg&Pm4jVB~}QEij;ae=ew*Vmobg%S)r$y&}@=3 z3V$Bm4?7oIC#r0L72FKkYC#J_n!$zz^6Uj<wJ|wc`{>4Yr-PkYc+wi}sKv+9l8pN> z+IlnTIx5yqemR`mkwgL^W-3H+{EQ{Ozt3yFajn!y2b2J*K`uXdnN2vu5_2G`R0nU7 z4A!IYo)y-yLNnuO_g?xD6l|Rg%qdmV@#K{ZJF^H!nXRc;sv}Cp)6gw>+X$bvc$;*; zFEvR-XTf)DV#9@vkv*Q?;KhBPv>OVs0IzL}G(Oww+3KUY6u&;N7vs$Xplkx-R<`an zAJ|Tf*wrJdh*uI`q70$&@hc+*D;Z`YFtS5Uj)!gB!j-Ls$5Y{+*2W?vVVPr!Cords zW%<T#yQ`+Q&*zKHz}~S^GVd2;H4jM&f6*?!5>@?dLHq@l7SamyvkxJD<><Tt@wjZf z+Bszg#ZI#7RHs#7+lo1Q&+KwVZ*Gk(T_fpCDeCr;_7U~gHj;_gbwtto!`g+inHIxf z7RTGA+pOKt7tY!WZnx1o&@lZcSyt(Grz)?|d1uOaN~~3($;`0ss*{S25}q|T^4Kta z;mY?Uvx_b2Aum@iY7`+CaOK$UzjR(^_v(Zx6YY3JldgI>w?;nllJREA<BL$wcNf)} z_^ge>?XGlawtkZlCS?0CDWR>Y`yl#HeFeX_Pv!C_FjRA~BCZ{plmmC~QH0bc_OqPG z8sr^iDe&yK)#z}aW0KDq6jX$XuH;vlR)goltTPklXy!}S1bSd?U^N7n=hvFx*LG2d zBE}Gt>7r{Nc9vSG$aQ-mF`i8HO~3Fe0d8<4pm{&C8Xm}ce`j{J=kexy2796Kp3waP zxoN0lM<Zq73UYY}QX&?{rG}N<HRd+kpRQrcZ0s%MbhH%YmEi@JJ6z?F14Fl;x`#|J zG!NB;!tM4cB+DF3iN2c-9&xj8%NJ`ChmHts7yY1_T<DO%O7c1*`_|4dL*9}&;W4x@ zG`5YYMe^(x$@BAaX$j^d`*odl`^Gxsph$i(5m@+`IGhI0sJNn~>GC|A6?cXxPC_{J zeN;)THCs(jTdA=2&Xs_RTWngC-WIQ+Ys<B>yU{|Y$|J!fHA;5}Fa66}RS4q}_dHC< zfu6~gV{;>Y)9kSNBp1}!wjTbTkB=%gepZ)UvoBmNS1poro<94V!HlVmAQtJC#AEet zNyzZhe=6u4cTn(@I*E}lrQ2FA=AC@iL4Qet{}lF$Y41<F9XL#7V}L)kYz{hPkGo}d zg0OSdPiQQ>LO*z>-t|Y!Fm`t!iuE9s-vO=%lZqrT{E+jZSREH%X?QGiF=MeJ1m8t# zRUo|BO<i9n&+26;7Ui^$uSYK?z}V(~UP!IQjP@{*viQ$=^BpbcEF29wPEVZNa4G(b z*(e*ZjjUd_Ivln9hdgyUc436Fy@Kj<&SIL)&P#IHKh``()47(2Zu2_UYg^>yUHaC3 zDs^rR=570fIJRw8QE=Dr*tStW-GkCDxR5PsZ@7}ZjP0|(=SKso4s~6+YxXsH)TKjl z$eAuw*A6*hiBSj^sMsOYfq<7V?ArW^&Hi*-kFFdo*kAz(->bnK*;@X<d;z&{#ea4> zgs5MiklXLk%@R;etEVAaC=1O<0+>!a!CC-;yxBj>T)TbVjp~>xNQ-PN9AscTbtPqL zQrNfkjeZ^Q$v$MZm#*z)df;T49=mh(RRp%b)#ci@@;fWZTPMQW6}^xo02%&hmsY5n zby93o>kFZrc2z<Mv&DwOQjL`UpvQ@-_a?oI4eEy-WyaOM4b^ptO8Uw!q;F09+N2s4 zkJ#!kp%m4X<15LE2<3bbs%P*&ytcH7a3tyD3^SG+n>U+ocAOxd;&{KXSTdRkrchls zznt5gyTF8Q0T3Wiiu8=mMv|!8VD;R22DWgJhU3F#W?RzekL48$lyA3@W;-Fv4&}5+ zbYQMI<-h>vX+uf*KO={-0SAVcJ9LGzMuMTLo|j!C#t+w;8VV_>EgBKoYk^*6TjPqH zJ`>6Y9qwp7F=Ig8>`pQBDKEV+;t=j6Nt`(q@o+CB-5{SFx8)TQVmJvO()AHANI)=? zWHzVE6crU$Hkl*ubV6vIwh``-le6=9Ed0kSnKfj@q%6LkSz>MNg($mGR?rro++VmW zfD!Rk_E*OTFF_CZoVfXqz~9!hP#Jtwl_+^nNs1ro0kX!uq55B<VW3XI?egan^`TRw zn9bFN382Ya<N{dl&B4%Y!D1RU=mJ8VzBQPfe-5s9LV0^oww@&MK~kY$9rhkZ@mMMH zI-Q(YnMK;5N^`aX2_a(P%r86pm!51*khVfn*fkZ>saq2iWcVgP|9@|(#Q^~2v||v= zdB6T0PWAjz?>@PZ_np&VYOo#q!&Rv875vNI2NIAdWHDHOwjK=kor!Xk1~<HYTjj80 zMH$oo<5|^5KjQgA)yC?^O9UE1)yZ-ow3Y9!O~>HM0f~_J6wq8z@h89v3vp8MXVY^m z_JPT&ng#9*xQXibAx!!I-*3J`-<xxzW5Yppg0a&hPWQc1aOO}-Wlr}!l1<iJ_7-h= zpn2x$>DmAYB=5~8f(Lx>ZqV@5ofCL0$)hy85;q@j#l%~+AK>715yU;S^5A~p`zE*? zAGo5LxLm@`tkC+cCW0dSYRzcTVKzc%zJGoROu$@IW`-etYn1rO#D0FV&>Ec|xv{zA zs<=7%lTCDl+pd3avGo3(VU<a63_qhCwlP^XzR~^%E7$z4i$ngUw4X=G)4`|o3fYTY z4caCfw%AL}#jlRaitdei7dY2KSReIyUarF1&rk1fZ!g;_m$@9{zB~I}U5@T1ITFNR zN3G{{=w+v<+x$^?--NP^9AkYg!XAL9^r&0Zjm+Y3WD>APA?5m6+VeMb54|+J1>XMV z3@;b%qxpdv{)wF7k360k_%H@u$778|jV|_<tQw6M{m!u7Oi$bGgnl-X5*{GDK!A%9 z4>uJ2Q7IwL?3nDWO_+s%(|Fyy$=0SwJDzjwIlGM#ruu96#}0K&_5;}S@0N3WN}g~B z4%`YVTjU0pr=2N+>f*+SI9WKO5H2&r{;Yq(S84|)UdlW}IjB@pkQzGs;gSkdtgK$P zejW62Z^f0#Uxg%gS;WR?lcmS_#V+kKne|pmGcDC`82GDq5-7fX@$xkh$}u@*QsQ=| z&s7HMBTNv(L#Dc%$gTASE%KMNFDQK{DMGR{sSQg=^$X8%E@bbACoH$a<0Jf>5yRnG zt2z|5*!9qR^#~t2M{fpYkZJ4j2$Z)VC)m#p&#!|SpslXcUx+*9#gffRR|nasEq)dH zg#~trbg1rQ<+At!x1Ie7e;(E9MKkD@D{IWT-ES{hoo?z|jTQFH4Pyu%u9fMQLR{D! zRl%TkcnayVzJF|^sOwxF<&QDJ!>3-(1tUqvE;mZ<MR3x<HbXb`m!>RH_VRb#$O+Eh z^!@a>c}Cz@RxWg-gBiCRx9HOTbk&-?{AG=Ocj1NWj!}*}{BY37az##7SSo+G^UH;r z%0sfaF$xOVB9tIy69C-|^vuGXRo|fs<XkW!O6bF!&4`$%LJ-fB`}~ulT}!LO0qycw z$-8&1+#*rx60>wBta}gW(<<+ThEnK2`(3*yL@u&@p<Grl@iLo>sxP%X$O`k2`<oy# zp1c^Z{P8kM%K(?B9xSL-$*-(96!haGM8h&m$L7g<FK0UJx#4)7YKYX(tdW@m;eWAh zJ2>IKi`~tdIrJn)nHuiX`p&ivUx!;5SdAo|kday&HY#kUqS^ZhRoiRUY{s-{ieg_F z`*dI$0+s(*hZ;J<iumcr4#xSOiFvxOSMLzITeO-s;9@&oaI$MAE63y9e<RY#V_GlA z;pYB=w=gP%QZv2?n$0h#3$16!b_8Ac^LH)E8pmI15atVaoz2<w@2KB<svQ=W+={jL zD}A0|_$$0V&~}DjA6}qwCZmHcMJR6B7|U4OTuy6UPCSQMxFhFu|6eaa%{bdm+^&oH zbRSXshSoM(NZamTR&m3s>t+W4lXRH%DZC%fKa9ZfH7Febye9YRsN!#Ko9Zd}d`4c+ zvXbSl9po`2k8vk!s$FjIS4hc13_8`-m@|)8A@xq<h&;YzR3Awvp$AGZ=!0Yb2Uenk z2wsaaE$Dmo<5^dqOZ9yX+`d{3k7K7gMidqPMs6Fp4H{&2$JGz_StY1L`SMT6->n;D z-k%F0iAQQncy~Mi2b*$R6ZOtwXJSs(E@^Y^AVCxI+Yh7qg;#!uLZ_JHt3vimqnB3S z$p<l#oA(``U>T&odptgHKn)Y6V0)S_{CTg`BBvP%Bkj*BGkfyshrh;7j303!LY@^Z z9qfG@Duqm0goWr*tP&5Ym4@`fg-lDE(aH2`!PIEvq~|{sANw7i<fY%{OLfV0=SyDB zBDna9UwR<;8ZK<}EPrR3=-{}OaZ*sa+vDN>I~OL>t_<I%VfCun+})K~=V6lcrH6tM zr$W4=RJjL4fh*NLF!$GS+Yx>8$erm)8|I>>@zh#B>^34hF;TUJ3(+o93PO>^7P7)4 zf!_?o%&!n?uB!NoziM3#>F`I4E(_D+%Bo8T2x^$i2?+gb^{=rlC>kTqV^Zck^1W%# zYmJze_RO%<1r7?;tKeA7R4EVSVnuK{<<ZbztoghH!>GA7YKr-L!)51+TLzj}%I#mE zfBKjKnm`U9#a0_V7mp_&_BrV&ZFO=;^=v$4=(GAGVqMn0=k)P$Vql<WRf=>6ZM7$E zNR&|jZS?o?mQ<{q2F6XHMIuoXW0mip{nIMlzNPZ-Z0zkW?Hd~Thswgeog-=CL0;5z z^MTt`cZxJLJo_CG7X0b$Y;jja3!pWWgSpyL)OB`m*XHBz&_|!cgs3BB4iVgN@cj%g zinik9bzuCL^0D9be>n8qJfx3DQ?J{m=8K|^R5~UrtN@|yI2dNaNHuWO?3TD-U}ay{ z!VQ`O`54bWNs{nlf}j6GaRjbDj3Mr<|6E+832Pis;x5|gH`1@pOH4K3!mJPQ4%x1K z@E2j_GZ|iwN$psZ%XZFLruciTk3y_scx5Wda6%NE5$s1CmoNb^Qk-Wd0R)Y;;pP=) zr%3CXjy4C7?_bELL}$K9vXGu+0Z%Belhd)Zi@~mjlM~7Fvo}uHSAb2%^FHpFILZDp zY?pkk_ug{H19uU2M=RT#OK=}j^PH{`Sgt<ibOw-85T&jINhs7^kxpe&D0D%mJ{NFM zPe$jnRwXQ2B;nr{Uwl`VGf62Liihh(NsI>aB`I&kWQV!=dbx;r1ySTkWo8Zr8mu#x zzY@-2R@aJKs=bI7CB|!<+^+h!5BrZ@?IPW#GPIc2OU28vpfZ;EWI)*MmN3Fu=Oy`w zbZ2Hp>yheR<&~$zCg@qz0dej$R&w9xrXT3?B++Hg!s1h@*^@937OWA|=ZbWkb%$rd zEX=I!VzGJ!VvY9%Imf=*yQfoAP3rJjKK7mI;GCzmjQLQr^k)UW&~2Rs7iO88<f^}C zEq}~b2hA;t#TNbI&m5QjvUV?ib|}mQAsr|JGdo(gLaDM3dnvYf`tejXI@M<_4l>>W zm9gBh93rr=DMKG_{=&{ltD}0<7G2HyQn}YN(zTvFTk9>WguaOh4h%TtUKB|X;hC#& zcjp<gYey(J)aaoWTEU~nm>QCD-|7H8FZdxS3<>cR<;?DYoE-f+&#Yg_$=+P1(QYvj z%&w(x^5nG6imYQ_Uvf9f(m5WOgGcWR>ci(!uZ$L$A<4o7D-FqbVR)`Nsi94qqZX_X z$~1_CIj(>8VQRL2?%Dxn{eTT`kDoDF2hYxP;+|p)QR-{kd}LZl^097_U=L<-8Mz3o zu2+G)GqAkG7meLT7FF`+q6~ICcn1!8Hp(a0mKSb#!If}891@(!4y>u)b~<+>DJ`1{ z>XlO5EW@}4Ux-r$zhMelQC$TYFKZQ_ZSYqHc|T@GFN17d_LLt1>L$e+y6`9|wS)41 z)w74YSFk8A{{uT@JRkkc+{d{&8e9A)VniKXz@Zeg!`*McKm5UGT3j-0E$<#;NWGMj zjiv~RMRBWA>-Pgdz3N4NNb91lbU=$ArF5I^P^?w+%_kSDDIx9yu`qdzzBA1UljY;- zJ$K)5vMEmvI}?f<0n()Q^hTz)kK?%@`<7vuF!0f}sevnAi=L&+2@e!1^j9qZJd2!O zpJ#Xr4%hx-YKT8X?bz>;f<@jNAc<ZnVH=cyQ}!~i2RhsQQMfU5bU}Sw{}y|O);b#y z#!~DcLMeJ%DP#4R^E_~I9ehQ1$e$n#x$kPb%W1Dy7)`-?t(KBjG<26|CRSyX`C%Uc z2WTsSJ!y)b6IPbeGKc-OxNU$md<C1%ako8D+1Z~(O2}soT)awe;cEDO;ZMD7Z5faI z0_%Ugv~}EC?5rph$83Z=X=rYmNBce;>gPfSAR0aaU9GO*sS)I1Bc>L1kOZ&G9Y$0a z{;Jo&AiY<>die8HyLNoKAH!+wCkTfEEi4wMDhr1l^m%yjpQR(p`~YNI<?O}Vx#?i= z+hTv-Mxi3S$>XfQrv@U7_!|7CGdurNA{TNJ2njF8<CAxj(M3N6K)eYq>6wv&4P9{E z3D|*J<Dcu{)`ObQGNCaXpu$4cE|b}JOtr(~PW`Fy3`wo31hC*4I>LjzvYm3R`B9%6 zVPl5>F;LM)x<WLX9}OpcrYin<u=11Kj(Ld7m0E~CI`c~H3uycsFsO)1S0?T#yt=Gs z#@>ErwDxTh+Fd$u%aQv}d0+p9GrAxCRn%6t!pD%~lcRKL!+eTHQsh>1_Vw(Vu^!WN zlmB-(0~t630;{A~^h8%d0T6l*2Rn|a960LRfdcr`lXq$xG^y=}M5xt8JI(%uA)kcL z2<9O=_wG(@QsMIzk*kM~dB#Tt64p|X<WG)~n=zZh7jBrYYBBonjmVY@F*f%aKVGH9 zav=`q#+cZdE=^V)G;p(Ax+-diK38krcqP1wqdn^4e_{C@xO#r*G*_JR<?8{Oxs1{2 z86S=Ny(@iQ&~%0&aMeN}R;I+Phj}tu1YK+0Hx4ZRH_mmdp{QNSnAiM>#pP`8$Pc`! zXTX#$y*ra71m5ZaXV%MGs9li=$)kP;4pK24YePjIME(>Y%YUC!DT+*oXZhU#$>WLI z9xytZMfqWNh(yO@XEwMu^NieCTBB?qKxx@zJO?Ps9xI+yP=dc+#<svGmf<4q?S8;h zX}rhH>CElzz#=f~$vZOCIo~(Ak}Pqy=|}D((p`~OG1a5fxDzWY0*UlC%1w+|Qti%k z5({OvA7j3fHzA?mSxSF4k;W`5)o7y1sFl$f*c>fDLa+z+FLGCMr#CPD5mc`m^!+~F z_nP4i?T;wl`QBC=62oPxT1CB*(q9E*Jt(S#v|DJ@Wz`|o;F@}Lwjx=l#$DOo;)rAY z)pYt}V<Sc{U$>ZG2o+;$C<80SLc<+A9Mr^kfaMwjF+I|h??y{!9TBKiTytAr1#}s^ zLV-3fCS%0a(-BwAcu9AC$paOxo-Z@yW17J}!A<y41dvSEy`r)&1Qp=bJUmwP;&+b^ z99C%}41`rno=d0&TZEqjhf8bx^!6NvtFI6J-KdiLz+`BI%vvHKTW~19h>$F=d&Xln zvg+~9?G-TEuycpH4l`bJ8uul`d2_)|x0WsxIhcjjFbS7o9@dM{uAl(b6tR^RUpuSZ z-+s#Rg6!~1zk79c1h1Fov$8-HmBZbs2%@Fxst39GhHvm*E-?u4X<L5INLXwM{T1>B zesJ+QmT)eaR9M%Krr+x(`r)!tZ6{$d%vl6!g?XUdAG{2DX&0B)PVz|yDvlU@e7XeQ z#KY}oyQtkSu>~#u<7*!!ssntV>>lkk6Q|zE1Ob!aAl2w!nKH)#;_2#h_7=tZNh`Ng zZ$zUZaw?5>;k0tk6VKvDgv1kdGdXi<WE*gt`o{2;IJq0+tNcC3%;L1~v>)-l^Q=>i zxBmaYj7`)(n9)_@AIx~-Q9t_P1;9fGe;hCf#tQ4gYO~Z46oy)9#9Kx@oM7ek;bDp2 z%Y7{6%isB*8x)>QsJPd0ppVlqAF;)lIe`3t*ut5^yI9qGU$?`wH{*IX>9~wV8!bZN zppm$h3^)PX;>=1Phy!t|1a^9TG}%T|cW`4m7I4+J$2RO|!~Hrye~3WY0=iVbVi_1Y zPQ55b_7il%H0+c6WF0<(0RG%Kp&iJce5gGUj_{inxV=y7{suh`Cbfz9Q*Eq#;+UlT zV<i8tW2<t-dIkbQFd)6YN($pMP!f%HNS93O3)^k*UF@!dnSLv=4NJqa9Pz)Kor!9# zP&zp%VIj?5IGxtkWmDqvGO)bRO-eNg_pIQ27wiq`!wl}~)9Lb}ajwwnf&!`HLl68) z7wWOyfo}s7NjJqBT{n0ytr_ttGwTxk>X&P1Z~_TEvEf(mvTB<s-soZL66nyZj<&<A zBR0-Bnqu|$O;50pH282fscSRt(MBq)?o_{IswCKf6zK^MKgpMk$uhoJ^K0Hns;A0F z2lka{aW?x@%(Sl7^e{2;Y~(p_#-Gy$taN{*sm2{SW9jnD?djp84z@1if3;P#_c!eG zrm150@#za&U`{E}_Y<grzuO-xL04kq$Kk6f<QZ?S(E53QrDy$N=VY(a@$3p!S{6#9 z+{k$K9a)T^^&eEL2vBVhUgK+L(kB;)HHHVb6rs5z`hG`<)o;oFhP4TwXV*6UI%!07 zW~G-BODs)pg8$8U@m_1$Yo)dqQoKI3qrdxkdb1=MKP*J-(G3ZKoz5-VUs=ccwG-c@ zEk6%IF2g0A9S+Xq#?94u%M09i_CMHi$KAqRnQd}klXl<>U8Z}@%+c<}_u}V@Gum_M zj;e=z-Uc-mXZqNOh*RlNr87fQ6|H_Xv{f+&&9kfU5<P6tDU)o;4Xk&JmM14?z@j90 z_zizW&V}Gyk)Ij^&?HtsMqsS!59<;_xoU57e~y-qcuA`YJ-aU&R?_$&EFn4<7-G1u z9Ds#$>W1k*Z}&N4P!pYP7vVX*qxSWp%PhZev#bdvCCh1ts+o`H<g9aS)bP4Z-z7OM z4h{RdliAb>xn8rUj{}!s+KJa+c=Q7J8&lw7L`$08CUwcntVVE;v4MH1!Jtkkl61dP zo6ykx56mwY<f@y;zQ?cByTE?md4hFulQ=rn>?6gDdFOR>B03K>r*2`IJ92VJ#K6jy z2*o8H3GPLA`^9r<qwlf9sQpJn%|>pX<&*Av5Rq_K{*OckHncrxP@3$G=XG0550vGU zssFD6X%P3TZl|Z{(fiZ;>?}L<t!f#s6BTyHve^x@)hjQ9zPUWNo>i=q9t)orA&G=d zO$4>i6Zs1b3J)eWtX@Us``S4_`Pw|BrkK0e(pgHjz(FW|Mq@{E5PJDf2RbEl!R?a> zU<}Q*p(y0<ZTpDwg|=qhf9m#+q<Cj7LPxcK>W3_Kawlq^;eVl91r0gaVyOPB)Wk$x zQW#A?Y_icVLASo(qsnZj;iF#KmsIRXKu4iq7P-GVP-y&~w_gMoX(Ei<7&eAd)hUbv z#2XPa6*|RU=d?RQbqU`%4doC1LsCMN7Ijd-E;AP=JVR*?W))ku8+P*NSbW}sy?jG> z9yMKh#c>v&oVNQ%?~}sYAVt@v^lHbVEm6A{pT#dpZq)*dPk*_>Wn3r}7qmLts8dgq zuJaR6W*#usq=!dff_=1|JNThFm(_=^##r^7c{IK%r#B!0QbgMIVUq`lOZ0v8=h!dW z16-Q{gEoBXXsI&s^n~=?87`~#QgYG5wujcQeYq!<>EDO1$P3XP*Y=w=BI3`C07`Q+ zO1tzNUUy<}YmFV0;fLS~r(cS5N#h!&#q&bARVzg2n9aiCwvsI1Ipkgs9PDZ0Ja$iP zTy9~yBOU~wAGOyG!s0!p!sF#HH-0|hC&<gt_N*-E?|}b>Kjv9XI>zj=eTLtBU%jh& zd_CDF{ULQ+QAf34eFPOjd~GR4k3FKI5`E9CE18tcnn03`O$^0f5{4P7U9_Pym{}J$ zapzyIa{aJ@jCR(S%Kc3FVwlkROTMDxeXLWw3)gKE>D7_R3yNY|fzz)%oKla7H2i6% z=Pm$WY4^;MlkeJC|6Oxu-;|z+>q~p|o7q3QU#wi5kurwgu)X~3qhVT8|J`-3SVf%w zk8p+urI+s&7rj#QRf}%52YvZR_>;|KHFrAvRrFeRI6e$8G%7VPruO6S7uv)20^r)a z02f|7jo>*_3Z1as@wOcqCK%Tq_?$E*sqwW`Aj|~UYUe`s$+b7XL|^F+l%Kh7&7cG5 z_PN~=_m%kV_?5_ksXy`%W?ceeS_HPYMyH_^&wCYWcMMqsT>#6a{dCnZ0OqRa2G|=; zz5!d%7|ePoq@ijtSPi1I>%YXHn9zR>s>>rzx0A$?QKkoa^%&!K#Qi7UtL{v{ZES;C zj<4{~b$yZ{kF42Y@gKP;On1SS-E9yVMzu~3R0Vv}gT|+)bJ^XBx>0qqxdH9mO@B|2 zJ%C|TZ@Y0Do8afo!<w?(&OT(1b@cUE0of03IcJxDO}=@|%z-Ywz?kfndxp4GwHE*W zA+(8FAm>eHS0DUP<zecSyelf&y7FAnGqBec0MD{Be|qRxhR*kmH7irppEONV`A6Mu zCK<)yi;;~eHv!2;j}5KMqr>QGPuUC_x(z6O%|PjMbd0hFS&*vfYDGWK^HR|c7pVXh znkaODlRETB7@sH3-1a#Y{Q~)@I&0k@FRERp4xCeGUO!CGgV6!X#j7%xFT9Aj&vOWP z&pcIqdXaBHlVm#`8pT8v9S8WDO>eu9s}MNfCs(*J$Z6{8{|%_VsT>h-s<Z{hwa9DV zYvHj9#>@XerwI@vD#zB68Eyhm;ESb<kJ!e14$ga<<;hF?&>Dh(Pj^D$gM*VR6e#Ww zk`^`j)1{Dd39#F<s6tulSVRIrTks2|!KmsUu1sV04|ZG@vRvh`weE5s57H0{0(0fq zR5IfbUjrDRiIa6wEzw}IxZREP-ugrl>Uajsyk&#%a8#)kFk((r{Q0+&#^8}djgP<$ z+5;tT;5XK~j*iYWehgfaGIwF(+^BT`Q*L=svhUR7hSYm++tf$-R2<>|^RHGaK+qht z8{jLpHseUUVV`NnP1T@%)gyKIopQY3hLgIMM`xu#Q~vI&!xt`u<?JdX@<+9^fPx0D z8^9qs;He;a*Kx$4$QLE}Jh5*S_M`=ToZ~UAPQvY~+j^hB_ksS#y>FRU6!K>9#?1*4 z&9YzsZafB06=CQe+-{Zt23fnp+^73rpt(i=e*w+IT0M>-Qv|9BVx>D<5Vy6Vg2@%K z52v-7yewo*&*%4mz?94dflGthh@aSKae!eSe5=Si8!TL{I+LzgQab<bC<zpZgzdCg z;}maiP|{56;zjnc0T{jwDe0C0Bmkda{##tyogs4*08%5o0pU^WJys_9KXCND=N~w_ z_P=nnV=2y2n1A`)VIuqqevOzYy>_z(_;f~Y5B%y1+7>PDf7i%-q$|1outf+7EyV0A z4o65yb35`zJlOfFnHmDKv|?4qqzQoi#<TrP4_AP4{ZoUpD<{@b;yL{!&cQ1(8j|WI z7Zu%ka!Aqf@5nXV0_x4vBX%9SP5lHgD+#ecu*|zzskn+u)^5#lS>lG5#|gZh6)~~S zA3HapU}P>XayH`Rh-&u2SvT-gQNHgzj3Y|C-{8NjdNC8>!;V2Vphc>9{%G)hlst** zQoaOX^+G;Q?l#MjfwEUGSHAz?4b?72m;xjBn{aP`GW}ucVs><=37CTqf>n78tpUX2 z$9-7CLHWIlcT2CVFG9-_7bDr>yxTIp6*-5OXOin%DkBFZ!eRmGBS6+&y?E}Xwmx5D z%vg$3+Lp97Wr6Z=6UUzjf~Ah?{f%_cki||dn57!t4W7ROj^tFbebSKgFJ%3{dVmK3 z+og)+_Uf_Y?z>J4o*!*(EZ_qX#m5YpN*=l(6t?Mf;B48_rWc!co9(RwL((>5_@lX+ zX+oAmmw%$?FiSK0y8HsCt?RCS9Tw#zAG@lPw;xCx585quMdwJIwfReCbCN3P5I4sd z*DRf3Cf2+ikY64gH(@1K1D#gvX``1j!J%F`NHRNufsNT={?4&(B_Yz5lAj<oWholN zo#2sA{mky`|2`Zhl;Yg#2X+Til3~EET>222fD5|sYg{-e8^l`C-t>c2fFk3LS+40; zZ>szGOU4KMr)@M?ht4Gs!}<hk6_x2$cr8+a)eNS^yXyco@xX&t_E=qr56x<kO2#6} z3H}|7#B3}=7)Q|11*T`$I$h?6^fdN6`DR8%&nx=f6C`Qf#MmWu13N@kn3mca<$v72 zL^W!0nG}xw(zPryYiKqs<J8102Lo-q`pGQD0`=X7j*}ON|HfY6<@h^KU<x;NVHVaz z?%k;L6sfQ5nHjl_x;Qe}9jo$a{M4zr$S5-utSd{AV;lH>9guE`XDa;H>cuR!Hct~C zeqI~0-V8pYLKWHrqD$UUrs9_79;G*2d(8Zxx#8)p0}ynquE}XHlhYCJYbeGtyaun5 znm^y+bD0+zH525VR0-16()`CV>?OVlq;_c0bo{vN!33rGCC&UUe#9x4fpFO`?Tx<T z0s3)2Z`1chyFSUwiCt`2UB2*(y+8WC?GY)Ul*(`Gr(NE-Lsn^#yl3z5aOT=pmY$n< zw68;P<X6PTBqw}qfM31xGxVYOLdwFT@TI_xz+BLQaSVkkgNMfFPtL{DS7~n)kwqR_ ztqIsnw?Q>^=4nadHF6qZV{E8xk^aX*3^Rc2?Rdnt<^6f~Q$2o{MVlO@z@fIL;Cp?} zdWgpgw!^$tJ`%A=uMr98VB#jU#Xyi8c@_0e<yXp8L5r<fDs^&2x~wS7M|vUdxN99| zGQig{@W%9sIxseU>^!wCDVQk{>Ud?1I<(3h=%YopK+^3GtU6@h86t<<&*t$q923fW ztLg%gylW=@aKe!2mY9B}!LO+~w>3f7mjtGrurkIw;b$>2B0%u#F|7_l{>iKHAvD7_ z{zd=ysr0P0qBg&lY8nuZ3sj-RzspW{Wj233!}~1`ZC~}*#V(N#iK3%E<bgGbkKO8J z#tt!P_WlnKhSSlo_`o(sCRI0<{~kkb4%o$IH-8R%;Mm<8uEy~@$=-l6ji2BucI^8# z0a2YuMuZ$`RVYJ6N~1Hw9BP0`)*@oYZ#G=9ZTCoOaGf;6mYN@)d6#?^W*&q0VreJ5 za5QsEcLb0{yA)sIouDELX&%}S*_KY>ZhDN9hCfbK-NdAjFH#5l<w9Sm7MV=!ruO0R z^Wp6kkCpzyl&qX@>hNIu=-DpM$o5sRpYb&W{vHx->Sw|<AJAXbw~-SfKG9OVR@?)H zIvxR{?E};JbS|;Vu4~WfT(xwIR7knGrw_+_12q*&^@zOgVJauDB3lysT@J|1HF~*T zwohldm|V1GAOD2mcYeD6dt14G5&1=>M-A#aJL5FWhWjOJ@9YyzhW-6`5>z#VOKo*T z-xnoZ{VOA_;VkArLWsUOOwgoqVW`cb8GG!)qsISe%yRI7L+~y-l(v{4+r@f3mX&0V zo+om(Io*?`x|p$qp!WarJ_7{pA6c<ue(#q+LTYjSia%vvRkArr8Kdr4=dc4UQ}eqS zDbj*^*x$ys%91ZVJ?ny_ROg}T6(t4K|MEd^8|M<;ACZP?Dj#MzdFD%pJ6X%hD7_?~ z0}r=0jf<!5_66;;(6u((yRFj2wY_hny0FdOkj&OsX+xMONX}QE|5Z)ngz+o&aXnJy zn|(#yYP{4_$L0V%bYPvgoCcCiMmiOBP|xsSEi+IXPrEu`W^rF%&qG`Xd4ARFu%?R0 zd#|CDuK1s28AfK$Cgv@AaKXK6tu}AR*pi-Tdt2>(^_v(;8S@J3|K$LX0)FHTgWH&s zvlxGcu3F?^n8sE4S-TdAyAO0qwR9Ya#9P`yrM+Ekju5LEREjx9!>o(0K*jIBU6I*R z?cyd$k7s-}Z}XG#;_+Q$nr|`(+<BBrP6JN(K$_f$?MHdTKy5Y%UY+}Xs*0d@=BNai zqAV;wj|`g4qAe<oe{RaaD7I+#h@4$zLc0-n^N=UMW{MKDb4TC(>jkjk`iWF?lYg?1 zc}cX#;MvQniy@xodaGfPD8BRy8^+Ma@#By4L#IE>RiTG&dGDVRu5pN4XRGTJ>9_wp zce%Aj#MfJ1l1U6BKPxcoguZXLAZQ4mY3{Du@?{L6p3vpZsg>yZSLCjA^4*lOq?ziT zRN~O5viiNH<fawBw{%aKh&@jATi7-(1Cwg=V@M-6pub=d#yjMasJOD-0qh77C^}eX zlQ@qIY}xeqW7FGJ|KxU@{9Rv)P0qe53^tya(=27asOxF8x!|;`ZZ+b1@6%az#?Yg| zr3szK{)(t}UrZ;TND({_{Y<Dxlbh+Qu2T20Gm;9Lkefse_XOpXN)6O;Nf1~WGIT}F zpm2j35Eh7uj_<Z;DS`8pyPr453yI2jP<zZaaFYtW<$YdH=P;#CTwC>L0UwW*NA~SX zzNmj?dun|I(dj?d>KTM=`7l?t-`-N8a9cn!+Fv75x^md@p*HC!Wz$inP)>^(Y!?@$ zS$ev)ARASUUJs{foeY_A>0_3|6N<tSwkq?-iQ8{b2Kx^}oH|jcXS(IzlIy*M7W<P~ zke<9hc@Wv>WjsJ4#8wbkA&Y^>Zs0-^9t-tbnSS9ailW*V1upuxHE=U<pcgK*N~04Q zh9!CRK4hB=WzrZs+_R)F#{kzOBriK0;lxSbEaSgPUWtrX{Sl%qD-3Mn+3oQEuf6Y# zYbxv3KY+gIs31D1NK=^skq*+NsUxT;FwzleB1J-xZU~T!Wl(84qo4voML_A&TS5>4 zsX@AwfV4;r5Fn6x_X&FM-1pA!{y+Th`|aIdlAP?Ez0cZf@4fa~&$ANcsidbx11M{& z{svqVs?F3`08vzmO0aiG3~W(&K8{PRnJTR%UTxn9n|-%G*H5M0D<6k-+KBLN!gZq( z%-a=67HozPRi0deU|=6LZ0U^$?g2~*?V5#xed#4Qz*dj{;$g|(h@WipZ+zanChFp$ zp1IDR@{;hoXcz5;F@*PMlNRz7<E2!X1m~O%IX{}UcSO1Mt~GFAguti*Z_Zy30?Kl? z@=8wzYO9z^NZle;2}B?Zl)Qb>VlPJlh|Bdz&mSs8KRw#7oG^SL4cn^{j}LjR9u!vq zlpB~Lr~)&;3PB%$!)Bc6YS(re0gx`@0kzY_H@o9BJ{|5o9zCjsH@-A|ka`bEv%ipf zGs7TW>ul@K3$>+zrMn!J$ojJWJ{zPn{i1#1r`+edlIz-mf3UO0LnXg3Hn_UXH(K0) z*k>7+LfaYl&gtmF`IxE!M0{`?B8BE@YGUY%WFqTH1fh^d-B%^6yDk)u#m&mm0^(-K z003)SObd)jq39^<aTQknvL1+$^m7>av5P`k>~f@DnK?df=Y7~t*Z4{r8oGnm9>t}( z367pMy6&>8;L`I&&8%l3>K5zCxJVx7ce%yj*lQ=GJGGc4u-bWS?eg%aJJ%}=L4YI} zG3sylV*eKhf#m?@{p9=20|NyQrk)~j`+OKHYq!UwcgE8`^c5VNdU^qCcIP*t5Jjts zgX9MowfD2zcDu4+pWx^~v$C3Kx*=5y*dzs-dAWFeIPoeT=_`~s6@32??h3h_b4f(Z zK&fseZ0>+mp2wa(M@hgwsMl+1tVf!v0~`bTt%p8#dfPMV(5%O?R75B3AGUe`DMmN} zPNr2gpNVCpE?V5r?GjdHqE=gnH2UPT5-3g_S)Q0lK-x%oyY>Vk%$!l)|HU346Vee} z*G{3Km0OI%KipWX8)X!`OK$$MQ~O-(?>y3e7=0)-eLmDxe~BH24_5c{%Ce<ukFUPr z-Ia;<r^i65S#b;$N5dzcA&l3_6K7WEU}8J87fvNB^?uF6(N@TpY!Z#s=e;Ox%0f4c zvd8Jjd(?V>>kdXO2BeanT8O+RyN*W)ZK2t_?0-^?)NA%|QSXx=EA}0ai|v~khXLI^ zAy*V4C7v{|2EX3U(&5WVDI!JC99nh|x&b)m(%ZoA&YWQpjc9O4|BAK*{Mi(%8W3}r zko4z_=tOsvlVaX*imtYny7~hCF6y<G^!o|FzQ*G&3uA3@zekVL`f{^>%S9aIEcmW5 zSvlbUb2Z}sLRj7#x#<tGqZrkNML+oDc|GO%N#(4N3qk@@qpJM3v^`@mCBA}Uu9IGU z+xFXB4#o)^62x+AincwQ)qCRdV?3uVB{~iu95%_y(fTb{1I>AMLIrVP-ui;4u+i)( zp;>uE;@__8mDlnh*k~Tj{R|#S#DIP_b8E(B5HUQxm;JlaHh_wi&Kv@e1r#eG7r^B- z299}5;@`dfj4t&~uLg$So!51jtvrN`5%xP<Rbi#rQf$Q#C<2k#@V#q_q8Y%Nt=F%< z5T`e$a%mUy94ibYs0?AU26Xw7Ofm-tQ_RC&JX_OSV{V0Pao^Ap3hCd`5nKNr9RZH5 ztq;W3*^|K5vl+I6Fijs(GBp5nX!x5iFeyE5_!=hDVq?c=B3uX82wR<(xxRJpFmNd4 z9dT&G*Ys7T0hqh6Rnd|#gRUr(g^-#UzV{+Dt-VU($Tc)rfYp#bglj22dcc3t-wH2# z0J$Hy{T+pp<a-pfZvO<1RAAZ^-;YqiNxq*3{{I-0Yr4Y|pjo}a2GI1l(+<nyT$GiK z9zF-^m!9CdIKAC9g?nnEhR<^^aj}+3c6s!O4hJ|kyZPCYE0jvz^pyl03`rhMoC5;~ z5!{0<)F?7Try%D)V3%{ya`!At$RP5wOy@3eTIW#jm&IiQc+t_6FtR0`C5V=en0a7k z)>a9#nllYh(`Ni5FnY8zN)aFM3;Dy;;@>$>xcSd8ZC-wAexNr6iUPoyY{1+lRBCjn z8tVv0<6mgvoy9gP-ogxJDP|iwa^+)aj$A9W`FtmU*WuRV&OCQg)G+9&9PHPa{%Xe2 zfP>x^RuQd1(H)vLQ6o1Nkk^4vrNUKtoa>M;5SjO#V!j8%nY3^SDv%Jk66|Uaz6-b? zaJP%!K);{Y*Q}TiWO+CT0#^hqjK_lplEE|xv%2Ruip?6S=<qB+30JU=$Bg%snaLwp z7B1)yaCqILHizl!E%)~Pauh_+dUa5>%)I>w6Anpt!J=q-bTz-*Bi>+`6ZkDA{V7Yk zq5VnS7vSwb{-&8ZRucN!X5<7Gdm`j$itcI{r{sS-(SH@Wr@hJOJ)Kj#N$9;Q__-Xf zOVoHL?Vl@T`(K1!rv<;E5T~o{?;??Tm);$mkEJ5V82;~DZ#pGwQes6BY?Ka7@UnMf zHGBOTgZ~REnM&;&3TgO%P<n@^v^nzFX8|KK-MV$inDBg9S=6vNI`RRvA<*1<Pow`* z^3Ezvz=9EpBUds*r5*Qb)C~a39$@W7Ciis!R14-&&tbcLr|iNFwMsg1!BHU8Z1T^c zW)uiD{}WAjiA&Q3zOeR>)O!TA(_NS9H?A_n#Fr!PpDa{(7)Pt8Ph!;7dFI~?<jGF$ zo?U*AI7_F=pKjUaLcP5D3mdpp$a@=&0MpZ__N<5wFRA-Zt59-pZ5Wbid|3^i-v1j@ z7tts|0F%hueT}mfGTH;5b&b}oZKUG%N+is@liDI*N7z;yuxQo7V~5MUap$?vtI4dU z0AJ(+t51o(*iVi1Z`mkK0kl7{5AGGGEA}BoT*c+HEC(Cf`*sVzM*1{o_0jQX>Sw-% zgDbqkeiXv=S&dFIT!+G0LN^j<(ouLJ%oMUdc<NA4^1H#jd_cHWl>2yA7(Tn|hJ^b7 z%I(!Sm~tCKdlL9IUbbE@me$R)B>131%vSU}5Ebc`?!LwLl0y<->6^tE<H6D&hA%yK zO;iYyT5q1mN{vRp$jJ+r|9+BGKECD)V!N0G`$cYS*Ym;^tU*~}oJxyE-xAR_DM0YE zmUPqu74nd&)|7}<mI|%#NLh7hVb2YKSS~p3<Tq^1g;#G$S0TH+q?Y%*^T(^+k(Y}Z zPo+uVtI!woZp3a#0`TK0E5L~R9CAWEH`7Kn#4;=~_eslxfpw1@qA?}-PX3bB?`=yv z_<VZ0eGrz8POK}5G}Q$YdqY2@!eIMnji+Zx#IWuHi36$MBfR@ux<nX>aENj7dU~y& zm&oSfF3VPGMV=fmy^*-9!QO{Kx-=#F&n($u&GxGb%_TZW`ot*F?adWp=#^l^Sfm_z zta|V{F7cNw#X_$d)c)Y|WD8H<9D0{#5*Xrmp`hmZ3$*&otS8E}xwPMhc>2E`=78ov zkXo*Qgp7!8k87gUpCzgtLq~(RIpiC%BEX3<&23S{Wdv}tPoxzd2ev#zO1Z7p-?Gif z)^_2nXyfDgcSYR8)~@S3xINzqua`a@v>KX3_$yrcIVDyn1j%YCx#nmlhcv}Zy9hdS zo3!N@dhTl^^fkffw$wx(4KVktT3Cp{stMJ8y^i8N5{+J2#Wv%eW7Yl&!5tM>o~)QF z4!=O~x~G1R>|J)S({Ac*{#082BdWG^KI(+R-yDE^9!TZ<6}G&kd2$oBTw<AD3y{S6 z=2kaJl=6K%p;s(oR2KT(cFetzz$W1Q2eE%fXHjOyoy0pcL~YUEb@cjw9&98W|M_4O zHE&!zpRSWtTB7BeS5MpMx6M8qAD$`MZB))6Ff|!YLcXQ*mqdMDfza+DEC}r;k_A3F zR$j@he6O)!QtW_zE!OMqLz6G7R3s<JMf~+x(<ok5&Ayo%DKOq&ExoFw`k2@~?UXEW z{jL#fGKzj8A<T5f^|#o}%^aSXXSBB|41ONREncuDJK^XvgEIf%alPXTuxSBTlXZ>m z1cZvymz|yZhmL9U7AiTS8ecUxKe>mD1a4e<AN2{2Rvd?1DUr&38F;5>^>X+;;FAKj zWJm)X=sh6AAGJgttSZB*xNpH+I-ERsrt!JEkXWOQY*x6dgbL-R8OX(8F!c1o&}|>G zw`jFvdxZJez%uUsL-jlq>~)KH9=J`kr^26j)zPhG_NJe2bV__|Dj9LmW9~rakeW73 z4n-Y1dvi$eu9>cyR%sB-_~8;n%cC~f^-uj5JPjf?Nur_nII;G#&JH7qX2PgLd|jKQ zN}$k6?~4j?Hw0FjN4?V-tqX777wd+I9PI5$8h>!(T~47qU!4Xrl|;{$9J4}vDmC*n zIO_X;u^gY?D^1!z|0u9r<mH6<*cBn?Oli-U=F#PWBgfkU+oT;_4)$3uAjE1zl8bT( zZGaI<<nh{4jdYk9RV%wE;W4+HXeu(+sAiX{mS=!(cKY?>xT4KrhxVTvVra4EPbA34 zexa2US0nC|-w0&<*MKP;=FR2OK6mQ0Jm`M%;Gx1_S)bpdzfzc%T8AxuEq8P4K7^04 z0E_{S{{8`?zjVXF$O=*KV)3|wkQ+mYvyl}vzb=V#r!Q6G1GPjaI1GFy=D&r3t=?qg zH0#bRK9{>ZyQt$BkH{Uoomh)(1^kJ?_QnQ=kw}%8%(3v<S--0N{`fa>it)4j?K*iT zXl5%bR{{IC<j=d)LA_NJ{A@3ztPTvvFONHeWz*s4rg(@4<Xq{~Ju=MJ<bzrh{$lR$ zUuDx4E~Zv5yN8C|HhghFA=hHBrBTbYd0wxHNx4Yl#0vnwQmx*pVl5ymwQ}Wpk9t7> z*Tg3=9*qnn>Msv6+6!}vz7KmrPC(6Q_uQ&|sbpMpZ$DWhI^m-XNnhp7fp*kDhV(@c z%h1fSOhovIy<B;1Z_EdScDbuj$FW<Tg>C*MrSb$Cj*CyG-B%ct@u)~yz5J0erkGAL z6LIeSmXsFr5^yLtVaWEBt@aBZqKt;ALt4Tp-uw`QYfyqT#HBYt2|xZ%Gkb@!NqdMU zw@naf`9>)Lp<1JF_XZcgvBUmPFMiPW{fXOX*HoJYI*~mV6<@9dDNBEQd<$|4XNkH( z<J@SC<-w?2=YewqLxkVM=5r-k6*^FXKYJmULw_@wD$eW7y^lt>0h38_3gm}0+C@1l zBTny_MR4XuZc&!vTJGQuMmlo>koQrJI2QaN__rVK;;`{`@A;vpI~864GaoMhl4t(E zlVkF@5icYk(yNL0hr_u`w>4qTtAtpoB}|Up|N1fhR~++0l@q=5)6b+L3G%&hrK64~ z=nIMXl@EIw8^iPR9U~Wql_I9wTqxWp&VbGH7Y<u8`<@tR&x(%RTU=RuI4-4ys|xe+ zqpG)ZhL`CbQ28^9h&birkg2R*$MS&P1u>3u#BglB;u81&0-cRLH-`zt3Z=e5sKCN^ z8XU!(TPgrzls_rLSLr~={QhckryzcVNX9M=WGW(A8DQ-$Ee&FK|4d<xS{UHU500k@ zl1RAV`@Kz^kWX?K#5p<?h9(NVvR0Gl$jHR~se5)XSWvrBZUfGqgI8s8F};K^5Ojd- z8-R04$#booH5bsw6eTm`E%{&W$CFcDQmPj9D8;e<8xQqRiK;8>(UJ2hD{1xl4w~19 zB;k~_`N~9{M(|_wALe04daVy|bw~69-2Drl??>v=?$pF6+*&X&mSvTtXFr1FhADxk zR_TK`zYb6O=2ujK`~>u2ks2ddg`Qpp3g$dDOv0^Z2p6AspVUWzR73o^Aj}OxIR@~d zPT2E8HJkkvP<v5j1BP%=nqUN*|7yA04=aTxYJM=WUwjU?<NQmC>jn=-r0mtPZggm^ zLGltSpOuY1PvNYhCBm2t5;Zz#8foAZ5Ho-s3D;q<h$Ddw+6e*mD2^<SZdMc7Aha}~ zMYf$e_<I|&B2fO@@|2?ndZ9e4U;f7|BXmF0m4mRP=+O30qZy-SjVBs|2hHMw!|#+K zBI5k>Q6k6kxm`(tCu3`+@Kyro7z8Cff?b!7JHauJp4jUWlwa-d%}6ppQ|pr4@Nk6! zD|jU_H%=X<^7q+AePTIrh_$KA9=RyZmLTpOTRM0_x=^_Mt5==B%s}oGikbR2YmoHS zc)nttFWNC_LOXJND6or?%t^XUanf0hpU%u=UvHu@+c)-SjA+sH_9nrD1Qh@>AYcK{ zFae0F(h|KY$sT{zCyk67-j6<{w^EfV5kA6ditkEgF4o9zVDFBwf)L8w1<YIE+dta@ zugSJ=OC3arfuG;`%nn1H$r9D3zz-6H^o^GMb0|_xL=z2sf}12v!EEaTpTg#1s}jil zktDyB8u&Wqb2><b#w~=H|IFXcy?NIRZ|LT_-vB^9&I4k;Q$>R*u*4zEQnD)!dTK5i z<oZ;D(}<36nW8i?Cv9HOlUWTvw!$tD$aXvEV3+hU48@wK^*H@cNp|A18YR#vhs{+r z>FK@>=web@TX;xtr5*#QEhq#4p@A+w*+f=U5EmRnL7G%hj50wlyN(W=q!`OOq?(7l z7r%O0p1F|e!FGg&Yg#K0*TOsjGgvtmpJYx?+lEQo6=Wg2Q`DDOFL`4x_v^QC(l-ka zkb-WFhkf37nwjwf@cn>t;5U$W@A|5<TE0^GFWf82aAN$fV*@8^gi$=eBaB<v%vUcD z5EBGTuQgVi6+y7_0=I5~E?jr6_SFxza$G6`WD9~Xn739|JZJzzaTxXGA#{HpzW7zR z43?(`Nqd0@>H^Ls#akn@X&{C4${FLPNP_oMseF$2t4vbh68}D&MpGcOp@N(-qRr7{ zpxK}7IZpJ(P?Fu67DiahfVE8V=8peG9`KS>Yw{>M{c+xG5Xvd`*M0|AsUY?YW3S$< z6Dx{S{<Y*h)|FN-c}|eEkjX$ht}Ai0#l`n1CN}cKq;341yLjs^kUeJl1uPst;PUb` zo?dguhJvR~8d8Uz{!pRTc&Q8?o(!<PV@zCN`SC^;KbyS`kT+#I{E%qo=OhD;dGB6d zkg*-Q$Pc!`{^PKF5@altjIr*JO|Jtr{Vc?H&W;7zu!)Gs=jXBGf1p{Sw+)C+k%qI_ zx>bM3wfya84owCG&3K)`ZJzD{FB(bxh{YSm*KOu@02+mU8Sq6qgg#nbtl^kd^)lrV z!Ev0)Lb={+SDX=ES!gPjxi$q91|th{AvjyW?pn2DXbWQ@dZcvvip(d0Fz|Fc7ACH# z`;;nqimbqTW}`tZ;VJMM@yS9vEk@gdhLs(_W>3i2dw3Bzu~zG`1T@H}7^gA+lEYbB zkTiNQD=@lV_x{0zEwB8M<R7ldnVWmZ+_j&OBh(*n*cy~@_^xcu#kn6&{3&p(<MNLg z=k9f$`E{c6qRYcuhKL_O{&?Q?s?GhM<uH%SabLClCS9J@p)^9PsDs3_C$`VelbAZ6 z_c)O#OV=hJVbNH6rH`OHX3|P?enQeEy`4Li3Ac7*cn;)L%iJKTs;95Kh`GZ)J6!D1 zY-^0qEUZ~JuBdU)X_ja`qD=Thc8Qi7&?7Tf50j3f&jOirH1{`&9WhYsTZ*)M>1Eit z_Yg1NL$+ijt;YoAdW?OL1#enA&VibX%aO(7Ud86td}yrsfc@G(+8JA&ln>GwLcj4O z*kH3BWg;ffSDu)Ml`v~g0+%m@*(we3?KWb!eDzl!=-Xba{VO{w=6Ae9!!P+a$3$g# z`Q+o7BP+V+(_&C~n+(L<(Jl?^4^E&tTkk<VN$8a<S|y^wcR)%uUH1q2YT?-%?64Z& zf$;iJfWZu`UfEG_7=4ts!k;2&a%AxV?vUM2ZmTu^i=svO;qPt|-6&%5shm{gsdcy~ zE<i%t5LaTYEsV2~;cmv$=j>`L&Dncc=>fy}^j$ZP1Z;7Pm538yFVO-GqLTcowP}F| z9;UcW9w|@}Z2k!L{MXj3ao8w1u#e{eX0f5?X#NWB3f_GCd&UJZ)ykW$Sc)A_va!5Y z;a3@AK+~rz-vKAooM=GJ9fN&y7556jF9|tYoS_8M?eG8mM9hxlbGKOAz`ZkNs<WTn zJ)URep(_IFKneH3S{R;f${bc%C8a;8VT4lbFh%e;kZmgXN;hGh5i2NwFFl&c3t#M* zl`R9__4sx8uQ?!Pd0u6x;{q&v&{GMi7d)8N2`Ky}8I?W81waz6?!oY29LK$aK5wqu z2ljzVaBT>JwdjAmE8quS|CmT5HSN?$7Thl6!L8&i%>#0R7?ss9-{*2WvhTT2$L6o0 zQ?|g5tDMHFqLo|0mk6i#f;+ok6Lf$-Ie!xQZq)6*v$^m?(B?bB?s+9L^I0am!jEu! zbKsTuMsi~hP(Lt;0-#9<bLwr<+BxkJ9jq9rrF#+n#@W-ld4sez0WOTX00}_Q?Ms^T z?T<T`0`S?J^}MSXJdkqI2;gzb#NwH0<gS(~n(oR#4W4f1rOyd!iQiE`h)ZOl4J2)( z;C7&lZ3JLz(&tAwmD6QjCqA&L*_`&tawz&u4qMN{bUr2u-qhk%VM_z^viyoQha_T? z)`Eo%4_#w!x4!h4^aW2)!Tb?Ef98}WFac&Kb>mT2L5&XLHV{t`84e$BQ>d{*9;fQY z?I<{B%#6rR?!51>UOCSL#C+0#`^0xGHRtiFYa2ZQkuounup}B`fkL)NgS%jEvps$p zTO+ufS`W{i^$@NA0&O(s*^kZHm#1S;?fQyKef=Kb%cs8qfuB6*7BuH?7TPr@|1Qp! zxRSnAEB?NYZ2Ass78prF1N_`)p1Afhu!=j4B&f+Y8>DlxxtEt<4I7E&-auQT$Ap0} z3$+;D7VdN5`juE+3-ILuEzn&|K|{~im`u1bK~)GI_mxDYny1sTM158ey(x|?5$4lN z^t~%-K&@M0su9EHKuu`(LvUZ^H2Tz8HJm?ZL2vr@?R>qJft=LgA7mow)RpK|+{8P0 z!#R1<4EYBB1t=<TPr2pP0iaUKX-nO<<kbm1OlBMXbM8YLJO&U1Ydq-0@`B#ThIK?L zk*lq(%|QIzf;j|c<-h1%De55v$>RE|#}&O>NrzLoCW-tGIWPskE}-7Str7}>o@2iH zqTUBmozLfs!q=vZK+j+8#gNGjg^pVAmDXq=o;xA<%5txtXNGbVr-NZx5QcyN2&!7+ zvVIjh<m~9g#JNq|egQnvp=xSRJ%BSAAUo})^UL+|KlO2G$~z3f%@gYVg>GJ$Sg#7e zS9((1;3l5l_CX*J3*aDpoP;20I~tv)tahiCkEA~)={Y%6OU_lowVai~t)1aV3j8U( zc%%z`L?2|y)pBxR$`eZ93WOKi3Ggc@r~3Kec?8O#ZQL34uYGrKUg9T+5DvC2h4diL znV(GKvOoPC&sBl`Z9wGQp8WkH_je0l|H3I=Xs7*fag@0+zqzqTrs6~x`=Cu);H-o5 zaB*g{M|^w0-i97eP-6qP@zl>Of)S)mQm8S9+fkMr?CtFx3WG4(SxIY`w`V!XH1>S$ z9B&8Pf`e?jpvS#3nz?Z!m?>f8BBj@l^B%8P3E6mPk<$IuPfUk$2dWecFQ|N$W0VpR zn}tXgsnEQf@j13(<oNg!N%1%CZqa|$=p-Msv+FY!lVn3TZP25|2II{&=cC<%s6j8< z<WMqcNqr3V3elc&GZXY6Z$u96UVj)^BM5}YJtbWX%G4;mx%}X8QuVKzK5-v1Pf$LW zI1Y*1q`9ULC;J)G-Kh4}Eu*>_bT5z#i^FW3*M<!O$XgNKH-69b+exkPWu{bHTTh3G z&m(>Mc7{6B)vnWZmzTK95%g3EmOZG59-i$|nmA;y=_4^4{)W2zTYLZ1{a=E+9G@NJ z8Gcf?FkE?^Vk*w?94<!4reD}70((>wg==EBCJGZEsIF^2hGG3RL-k<TK(6Uriq_>d zVf{fWRi<`*;zZ-e+VwiI+p`&ZCG9A<e;9>B5FaF;S%;*Ih~zO>uH{h64>~BNqOO(r zH-0XB&ehDPd_XUqZ_=$-*K&Vwq^vf1eQBI$p-!Z)G_PRs+Pv}Em*NOY3ABs(Kbg86 zUwMh`gS7}_;x6b6VZKc7An<3ndJh*@HP1SfHIoQ^Cs2H3y~xzTj}9MEyosMW$i{QH z-a!3$d)ZBy@p7BXOTdLynF2jkZya7g=w*lJCnyg&ysXOJ^5yI;pU|y0hKrRR<8D!a z{`Rz^^7>3relxbS^XE73@rpZ5l^}wcNp3?*d1d>}$@^(~*(k~rtBSYb6i*_}NgmCn z{Uc8+wGl+Bqf%T+GjoT--;kNq^{<U72C#4nw&#FF!1m%<6t8dJ^fK9Z3#q3_wS2b! z+Fj5%x%r1Lb`!4Qs;hWDJ)W?!tWDd3y7ZVK04du>>15xKlsP+6hqMf&yZen!f9f!6 zUM;-*O``B<|064BO3zwz{$=68(6Cj%xOaV3jP-p;b;^!OBCWZ6s%lvCaVpa7*pI1- zX{n63;J0FkghQLh**$R1L-|L0Lh^(2)_cnj;yOe5XEIpDdmj{a>8Ws)-u93+TqhA_ zVS{?%J75-ObiPJU8022F;(7-NyhR{L;M}y5GnZ1|<gX4d{}AL{t2YU@RQZ%TH>DA~ za2&B<^Qr2bL5@PgA7GYx+HDUnB@0Z9qWZAhgD}^ag2e@$+zn4NZrO4ewEgdQ|CYhO j^#J<+nG0tgn$smsRJwX~9uOMg`E=gU^i1Aq=Ue{)32w!; diff --git a/_static/images/table_columns_storage.png b/_static/images/table_columns_storage.png index 322538dac74c289c8fff79fae17a2ff9f0170899..071e140ea75048555667656b476d5a72daa6a721 100644 GIT binary patch literal 54784 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 NR#1CfAaC;ee*kz~kShQH literal 46261 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 Iz$Nm30F(WRBme*a From a3a8ca58fb86cc736b03c850658dfe47d8755904 Mon Sep 17 00:00:00 2001 From: RosinTalia <talia@sqreamtech.com> Date: Sun, 11 Dec 2022 10:14:18 +0200 Subject: [PATCH 0314/1892] RN --- connecting_to_sqream/client_drivers/index.rst | 6 ++-- releases/2022.1.7.rst | 29 +++++++++---------- releases/2022.1_index.rst | 1 + 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 3cdcc54b7..58791e766 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -1,8 +1,8 @@ .. _client_drivers: -************************************ -Client Drivers for 2022.1.6 -************************************ +************** +Client Drivers +************** The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index f879b41a1..96fcff0b4 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -12,11 +12,11 @@ The 2022.1.7 release notes were released on 11/xx/2022 and describe the followin New Features ---------- - * Inserting data from a JSON file. + * Ingesting data from JSON files. :: - * ZLIB compression type performance enhancements. + * ZLIB compression performance enhancements. :: @@ -28,20 +28,17 @@ Known Issues Version 2022.1.7 resolved Issues --------- -+--------------------------------+--------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+================================+============================================================================================+ -| SQ-12228 | Executing ``CREATE AS SELECT`` with ``UNION`` and ``GROUP BY`` fails. | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command. | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns. | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-11772 | ``JOIN`` query performance issue. | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-11523 | ``SAVED QUERY`` execution internal error. | -+--------------------------------+--------------------------------------------------------------------------------------------+ - ++------------------+-----------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==================+=======================================================================+ +| SQ-11523 | ``SAVED QUERY`` execution internal error | ++------------------+-----------------------------------------------------------------------+ +| SQ-11772 | ``JOIN`` query performance issue | ++------------------+-----------------------------------------------------------------------+ +| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | ++------------------+-----------------------------------------------------------------------+ +| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command | ++------------------+-----------------------------------------------------------------------+ Configuration Changes -------- diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 1e2c0d256..e63294405 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.7 2022.1.6 2022.1.5 2022.1.4 From 2808cdd25dc86ec8ac483553799d6ccc0ef8e6f6 Mon Sep 17 00:00:00 2001 From: RosinTalia <talia@sqreamtech.com> Date: Sun, 11 Dec 2022 11:43:44 +0200 Subject: [PATCH 0315/1892] Update index.rst --- .../client_drivers/python/index.rst | 153 ++---------------- 1 file changed, 16 insertions(+), 137 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index e03df343d..7f8baac93 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -41,10 +41,6 @@ The connector requires Python 3.6.5 or newer. To verify your version of Python: Python 3.7.3 -.. note:: If both Python 2.x and 3.x are installed, you can run ``python3`` and ``pip3`` instead of ``python`` and ``pip`` respectively for the rest of this guide - -.. warning:: If you're running on an older version, ``pip`` will fetch an older version of ``pysqream``, with version <3.0.0. This version is currently not supported. - PIP ^^^^^^^^^^^^ The Python connector is installed via ``pip``, the Python package manager and installer. @@ -53,7 +49,7 @@ We recommend upgrading to the latest version of ``pip`` before installing. To ve .. code-block:: console - $ python -m pip install --upgrade pip + $ python3 -m pip install --upgrade pip Collecting pip Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) |████████████████████████████████| 1.4MB 1.6MB/s @@ -91,9 +87,9 @@ Install the connector with ``pip``: .. code-block:: console - $ pip install pysqream pysqream-sqlalchemy + $ pip3 install pysqream pysqream-sqlalchemy -``pip`` will automatically install all necessary libraries and modules. +``pip3`` will automatically install all necessary libraries and modules. Upgrading an Existing Installation -------------------------------------- @@ -101,7 +97,7 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins .. code-block:: console - $ pip install pysqream pysqream-sqlalchemy -U + $ pip3 install pysqream pysqream-sqlalchemy -U Validating Your Installation ----------------------------- @@ -109,9 +105,9 @@ This section describes how to validate your installation. **To validate your installation**: -1. Create a file called ``test.py``, containing the following: +1. Create a file called ``sample.py``, containing the following: -.. literalinclude:: test.py +.. literalinclude:: sample.py :language: python :caption: pysqream Validation Script :linenos: @@ -120,11 +116,11 @@ This section describes how to validate your installation. :: -3. Run the test file to verify that you can connect to SQream: +3. Run the sample file to verify that you can connect to SQream: .. code-block:: console - $ python test.py + $ python sample.py Version: v2020.1 If the validation was successful, you can build an application using the SQream Python connector. If you receive a connection error, verify the following: @@ -199,57 +195,6 @@ This section includes the following examples: :local: :depth: 1 -Describing Your Connection ---------------------------------------- -This example shows how to describe the connection. - -**Describing your connection**: - -1. Import the package and create a connection: - - .. code-block:: python - - # Import pysqream package - - import pysqream - - """ - Connection parameters include: - * IP/Hostname - * Port - * database name - * username - * password - * Connect through load balancer, or direct to worker (Default: false - direct to worker) - * use SSL connection (default: false) - * Optional service queue (default: 'sqream') - """ - - # Create a connection object - - con = pysqream.connect(host='127.0.0.1', port=3108, database='raviga' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - -2. Run a query and fetch the results: - - .. code-block:: python - - cur = con.cursor() # Create a new cursor - # Prepare and execute a query - cur.execute('select show_version()') - - result = cur.fetchall() # `fetchall` gets the entire data set - - print (f"Version: {result[0][0]}") - - The SQream version should be output, such as ``v2020.1``. - -3. Close the connection: - - .. code-block:: python - - con.close() Using the Cursor -------------------------------------------- @@ -298,6 +243,9 @@ To fetch all rows at once, use :py:meth:`~Connection.fetchall`: # To get all rows at once, use `fetchall` remaining_rows = cur.fetchall() + cur.close() + + # Close the connection when done con.close() @@ -360,13 +308,13 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea con = pysqream.connect(host='127.0.0.1', port=3108, database='master' , username='rhendricks', password='Tr0ub4dor&3' , clustered=True) - + , cur = con.cursor() 2. Create a table for loading: .. code-block:: python create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' - con.execute(create) + cur.execute(create) 3. Load your data into table using the ``INSERT`` command. @@ -384,7 +332,6 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea .. code-block:: python - cur = con.cursor() insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)' start = time() cur.executemany(insert, [data] * row_count) @@ -396,11 +343,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea cur.close() -7. Verify that the data was inserted correctly. - - :: - -8. Get a new cursor: +7. Verify that the data was inserted correctly: .. code-block:: python @@ -409,83 +352,19 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea result = cur.fetchall() # `fetchall` collects the entire data set print (f"Count of inserted rows: {result[0][0]}") -9. Close the cursor: +8. Close the cursor: .. code-block:: python cur.close() -10. Close the connection: +9. Close the connection: .. code-block:: python con.close() -Reading Data from a CSV File for Loading into a Table ----------------------------------------------------------- -This example shows how to write a helper function to create an :ref:`insert` statement, by reading an existing table's metadata. - -**To read data from a CSV file for loading into a table:** - -1. Run the following: - .. code-block:: python - - import pysqream - import datetime - - def insert_from_csv(cur, table_name, csv_filename, field_delimiter = ',', null_markers = []): - """ -2. Ask SQream for some table information. - - This is important for determining the number of columns, and helps create a matching ``INSERT`` statement: - - .. code-block:: python - - """ - - column_info = cur.execute(f"SELECT * FROM {table_name} LIMIT 0").description - - - def parse_datetime(v): - try: - return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S.%f') - except ValueError: - try: - return datetime.datetime.strptime(row[i], '%Y-%m-%d %H:%M:%S') - except ValueError: - return datetime.datetime.strptime(row[i], '%Y-%m-%d') - -3. Create enough placeholders (`?`) for the ``INSERT`` query string: - - - .. code-block:: python - - qstring = ','.join(['?'] * len(column_info)) - insert_statement = f"insert into {table_name} values ({qstring})" - -4. Open the CSV file: - - .. code-block:: python - - with open(csv_filename, mode='r') as csv_file: - csv_reader = csv.reader(csv_file, delimiter=field_delimiter) - -5. Execute the ``INSERT`` statement with the CSV data: - - .. code-block:: python - - cur.executemany(insert_statement, [row for row in csv_reader]) - - - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - - cur = con.cursor() - insert_from_csv(cur, 'nba', 'nba.csv', field_delimiter = ',', null_markers = []) - - con.close() Using SQLAlchemy ORM to Create and Populate Tables ----------------------------------------------------------------------- From 425857f22622386806126a086a9176a532fdd57b Mon Sep 17 00:00:00 2001 From: RosinTalia <talia@sqreamtech.com> Date: Sun, 11 Dec 2022 12:11:15 +0200 Subject: [PATCH 0316/1892] SELECT encryption disclaimer --- reference/sql/sql_statements/ddl_commands/create_table_as.rst | 2 ++ reference/sql/sql_statements/dml_commands/insert.rst | 3 +++ 2 files changed, 5 insertions(+) diff --git a/reference/sql/sql_statements/ddl_commands/create_table_as.rst b/reference/sql/sql_statements/ddl_commands/create_table_as.rst index c0d941f21..7ffd565df 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table_as.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table_as.rst @@ -64,6 +64,8 @@ This section includes the following examples: :local: :depth: 1 +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. + Creating a Copy of a Foreign Table or View --------------------------------------------------------------------------- diff --git a/reference/sql/sql_statements/dml_commands/insert.rst b/reference/sql/sql_statements/dml_commands/insert.rst index 2607669bd..4005b471e 100644 --- a/reference/sql/sql_statements/dml_commands/insert.rst +++ b/reference/sql/sql_statements/dml_commands/insert.rst @@ -113,6 +113,9 @@ For example, SELECT name, weight FROM all_animals WHERE region = 'Australia'; + +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``INSERT INTO TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. + Inserting data with positional placeholders --------------------------------------------- From 2a973fb02512c359565686fb0a1e0102b0b59509 Mon Sep 17 00:00:00 2001 From: RosinTalia <talia@sqreamtech.com> Date: Sun, 11 Dec 2022 14:11:01 +0200 Subject: [PATCH 0317/1892] rocksdb --- architecture/filesystem_and_filesystem_usage.rst | 4 ++-- architecture/internals_architecture.rst | 2 +- operational_guides/logging.rst | 4 ++-- reference/cli/upgrade_storage.rst | 6 +++--- troubleshooting/log_related_issues.rst | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst index c4e2e1d80..4830271e4 100644 --- a/architecture/filesystem_and_filesystem_usage.rst +++ b/architecture/filesystem_and_filesystem_usage.rst @@ -63,10 +63,10 @@ Each column directory will contain extents, which are collections of chunks. .. figure:: /_static/images/chunks_and_extents.png -``metadata`` or ``leveldb`` +``metadata`` or ``rocksdb`` ---------------------------- -SQream DB's metadata is an embedded key-value store, based on LevelDB. LevelDB helps SQream DB ensure efficient storage for keys, handle atomic writes, snapshots, durability, and automatic recovery. +SQream DB's metadata is an embedded key-value store, based on RocksDB. RocksDB helps SQream DB ensure efficient storage for keys, handle atomic writes, snapshots, durability, and automatic recovery. The metadata is where all database objects are stored, including roles, permissions, database and table structures, chunk mappings, and more. diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index f25dfeb22..571b5f9a0 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -45,7 +45,7 @@ The storage is split into the :ref:`metadata layer<metadata_system>` and an appe Metadata layer ^^^^^^^^^^^^^^^^^^^^^^ -The metadata layer uses LevelDB, and uses LevelDB's snapshot and write atomic features as part of the transaction system. +The metadata layer uses RocksDB, and uses RocksDB's snapshot and write atomic features as part of the transaction system. The metadata layer, together with the append-only bulk data layer help ensure consistency. diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 8d76b4a1a..03950784d 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -416,8 +416,8 @@ Finding Fatal Errors .. code-block:: psql t=> SELECT message FROM logs WHERE message_type_id=1010; - Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable - Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/rocksdb/LOCK: Resource temporarily unavailable + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/rocksdb/LOCK: Resource temporarily unavailable Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable diff --git a/reference/cli/upgrade_storage.rst b/reference/cli/upgrade_storage.rst index c95ef25f3..867df3e03 100644 --- a/reference/cli/upgrade_storage.rst +++ b/reference/cli/upgrade_storage.rst @@ -51,7 +51,7 @@ Results and error codes - ``no need to upgrade`` - Storage doesn't need an upgrade * - Failure: can't read storage - - ``levelDB is in use by another application`` + - ``RocksDB is in use by another application`` - Check permissions, and ensure no SQream DB workers or :ref:`metadata_server <metadata_server_cli_reference>` are running when performing this operation. @@ -64,7 +64,7 @@ Upgrade SQream DB's storage cluster .. code-block:: console $ ./upgrade_storage /home/rhendricks/raviga_database - get_leveldb_version path{/home/rhendricks/raviga_database} + get_rocksdb_version path{/home/rhendricks/raviga_database} current storage version 23 upgrade_v24 upgrade_storage to 24 @@ -75,7 +75,7 @@ Upgrade SQream DB's storage cluster upgrade_v26 upgrade_storage to 26 upgrade_storage to 26 - Done - validate_leveldb + validate_rocksdb storage has been upgraded successfully to version 26 This message confirms that the cluster has already been upgraded correctly. diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst index 12623c943..a259bff35 100644 --- a/troubleshooting/log_related_issues.rst +++ b/troubleshooting/log_related_issues.rst @@ -81,8 +81,8 @@ Finding Fatal Errors .. code-block:: psql t=> SELECT message FROM logs WHERE message_type_id=1010; - Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable - Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/leveldb/LOCK: Resource temporarily unavailable + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/rocksdb/LOCK: Resource temporarily unavailable + Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/rocksdb/LOCK: Resource temporarily unavailable Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Mismatch in storage version, upgrade is needed,Storage version: 25, Server version is: 26 Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable From 269cc1949ca9cdf35b9dcf90924fbf6913e4b79d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 11 Dec 2022 16:25:42 +0200 Subject: [PATCH 0318/1892] Update 2022.1.7.rst --- releases/2022.1.7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index 96fcff0b4..fa81f914f 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -33,7 +33,7 @@ Version 2022.1.7 resolved Issues +==================+=======================================================================+ | SQ-11523 | ``SAVED QUERY`` execution internal error | +------------------+-----------------------------------------------------------------------+ -| SQ-11772 | ``JOIN`` query performance issue | +| | ``JOIN`` query performance issue | +------------------+-----------------------------------------------------------------------+ | SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | +------------------+-----------------------------------------------------------------------+ From f44b95091daf1b1de65a39822b3a8e0cb3cf5ea0 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Dec 2022 10:34:31 +0200 Subject: [PATCH 0319/1892] c & e updates --- _static/images/chunks_and_extents.png | Bin 70037 -> 75831 bytes .../filesystem_and_filesystem_usage.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/images/chunks_and_extents.png b/_static/images/chunks_and_extents.png index 8b3cc8d0523a62b8c4b841ecb92d8bce58c8f8d9..972b624e3ecd1e3455df5deca1854a10ada4cadf 100644 GIT binary patch delta 60180 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 HzjOZuy#N<S delta 54395 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%0AR=~>cYpB4^J}tI!;Y)*eNE>C=!6p` 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 diff --git a/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst index 4830271e4..634097e23 100644 --- a/architecture/filesystem_and_filesystem_usage.rst +++ b/architecture/filesystem_and_filesystem_usage.rst @@ -27,7 +27,7 @@ The **cluster root** is the directory in which all data for SQream DB is stored. The databases directory houses all of the actual data in tables and columns. -Each database is stored as its own directory. Each table is stored under it's respective database, and columns are stored in their respective table. +Each database is stored as its own directory. Each table is stored under its respective database, and columns are stored in their respective table. .. figure:: /_static/images/table_columns_storage.png From 6f3d4f84b9e1583fe505f3ec27047b0c66c1df20 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Dec 2022 10:59:17 +0200 Subject: [PATCH 0320/1892] Update json.rst --- data_ingestion/json.rst | 229 +--------------------------------------- 1 file changed, 1 insertion(+), 228 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 16f0b20f1..50fe2258c 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1,228 +1 @@ -.. _json: - -************************** -Ingesting Data from JSON -************************** - -.. contents:: - :local: - :depth: 1 - -Overview -======== - -JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. - -The SQream DB JSON parser handles `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ and supports both JSON objects and object arrays. - -The only JSON standard supported by SQream is `JSON Lines <https://jsonlines.org/>`_. - - -Making JSON Files Accessible to Workers -======================================= - -To give workers access to files, every node in your system must have access to the storage being used. - -The following are required for JSON files to be accessible to workers: - -* For files hosted on NFS, ensure that the mount is accessible from all servers. - -* For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. - -* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. - -For more information about restricted worker access, see :ref:`workload_manager`. - - -Mapping between JSON and SQream -=============================== - -A JSON field consists of a key name and a value. - -Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. - -Values may be one of the following reserved words (lower-case): ``false``, ``true``, and ``null``, or any of the following data types: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - JSON Data Type - - Representation in SQream - * - Number - - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` - * - String - - ``TEXT`` - * - JSON Literal - - ``NULL``, ``TRUE``, ``FALSE`` - * - JSON Array - - ``TEXT`` - * - JSON Object - - ``TEXT`` - -Missing JSON fields are automatically mapped to SQream with ``null`` as a value. - -Character Escaping ------------------- - -The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to avoid a new line within a value string. - - -Ingesting JSON Data into SQream -=============================== - -.. contents:: In this topic: - :local: - -Syntax -------- -To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. - -The Foreign Data Wrapper (FDW) syntax is: - -.. code-block:: - - json_fdw [OPTIONS(option=value[,...])] - - -Parameters ------------- - -The following parameters are supported by ``json_fdw``: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``DATETIME_FORMAT`` - - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. - * - ``IGNORE_EXTRA_FIELDS`` - - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. - * - ``COMPRESSION`` - - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. - * - ``LOCATION`` - - A path on the local filesystem, S3, or HDFS URI. The local path must be an absolute path that SQream DB can access. - * - ``OFFSET`` - - The row number to start with. - * - ``LIMIT`` - - When specified, tells SQream DB to stop loading after the specified number of rows. Unlimited if unset. - * - ``ERROR_LOG`` - - When used, the ``COPY`` process will write error information from unparsable rows to the file specified by this parameter. - - * If an existing file path is specified, it will be overwritten. - - * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. - - * Specifing an error log when creating a foreign table will write a new error log for every query on the foreign table. - * - ``CONTINUE_ON_ERROR`` - - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. - * - ``ERROR_COUNT`` - - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. - * - ``ENFORCE_SINGLE_FILE`` - - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``max_file_size``. When set to ``true``, the single file size is not limited by the ``max_file_size`` setting. When set to ``false``, the combined file sizes cannot exceed the ``max_file_size``. Default value: ``false``. - * - ``MAX_FILE_SIZE`` - - Sets the maximum file size (bytes). - * - ``AWS_ID``, ``AWS_SECRET`` - - Specifies the authentication details for secured S3 buckets - - -Automatic Schema Inference ---------------------------- - -You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. - -For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. - -Automatic Schema Inference example: - -.. code-block:: postgres - - CREATE FOREIGN TABLE t - WRAPPER json_fdw - OPTIONS - ( - location = 'somefile.json' - ) - ; - - -Examples ------------- - -JSON object array: - -.. code-block:: postgres - - { "name":"Avery Bradley", "age":25, "position":"PG" } - { "name":"Jae Crowder", "age":25, "position":"PG" } - { "name":"John Holland", "age":27, "position":"SG" } - -JSON objects: - -.. code-block:: postgres - - [ - { "name":"Avery Bradley", "age":25, "position":"PG" }, - { "name":"Jae Crowder", "age":25, "position":"SF" }, - { "name":"John Holland", "age":27, "position":"SG" } - ] - -Using the ``COPY FROM`` statement: - -.. code-block:: postgres - - COPY t - FROM WRAPPER json_fdw - OPTIONS - ( - location = 'somefile.json' - ) - ; - -Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. - -.. code-block:: postgres - - COPY t - TO WRAPPER json_fdw - OPTIONS - ( - location = 'somefile.json' - ) - ; - -When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. - -.. code-block:: postgres - - CREATE FOREIGN TABLE t - ( - id int not null - ) - WRAPPER json_fdw - OPTIONS - ( - location = 'somefile.json' - ) - ; - -The following is an example of loading data from a JSON file into SQream: - -.. code-block:: postgres - - WRAPPER json_fdw - OPTIONS - ( - LOCATION = 'somefile.json' - ); - - - -.. tip:: - - An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. - - - +.. _json: ************************** Ingesting Data from JSON ************************** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ------------ The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference --------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples ------------ JSON object array: .. code-block:: postgres { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: postgres [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file From 15b10fe3e0ee2a4ced414d5406909ca2dbf909d4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:42:30 +0200 Subject: [PATCH 0321/1892] Update data_encryption_overview.rst --- feature_guides/data_encryption_overview.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index ca953ce2a..256e3d718 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -21,7 +21,7 @@ Encryption can be used for the following: * Selecting data from an encrypted column. -.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT`` or ``INSERT INTO TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. From 484f1469137f2d571a7813cb5435c278cfebdc69 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Dec 2022 13:17:55 +0200 Subject: [PATCH 0322/1892] Update index.rst --- external_storage_platforms/index.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index b7a591d65..92c35ee63 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -23,5 +23,3 @@ For more information, see the following: :: * :ref:`copy_to` - -.. note:: While you can ingest data into SQream from Parquet files, you can also store and run queries on data located on external Parquet files. For more information, see :ref:`parquet`. \ No newline at end of file From 1ff394a7cc8e2a780b73a00f3111de825e223b4d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Dec 2022 15:15:18 +0200 Subject: [PATCH 0323/1892] Update shutdown_server_command.rst --- .../utility_commands/shutdown_server_command.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index ebc3d9184..bc42fcd5d 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -11,7 +11,7 @@ The **SHUTDOWN_SERVER** guide describes the following: Overview =============== -SQream's current method for stopping the SQream server is running the ``shutdown_server ()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown by setting it to ``select shutdown_server([is_graceful, [timeout]]);``. This causes the server to wait for any queued statements to complete before shutting down. +SQream's current method for stopping the SQream server is running the ``shutdown_server()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown by setting it to ``select shutdown_server([is_graceful, [timeout]]);``. This causes the server to wait for any queued statements to complete before shutting down. How Does it Work? ======================== @@ -92,7 +92,7 @@ This section shows the following examples: .. code-block:: postgres - shutdown_server () + shutdown_server() **Example 2 - Activating a Graceful Shutdown** From 9498d047c401fbaf731cb230ed5dd6d431897e1e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 10:32:37 +0200 Subject: [PATCH 0324/1892] Update 2022.1.7.rst --- releases/2022.1.7.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index fa81f914f..af5561432 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -33,8 +33,6 @@ Version 2022.1.7 resolved Issues +==================+=======================================================================+ | SQ-11523 | ``SAVED QUERY`` execution internal error | +------------------+-----------------------------------------------------------------------+ -| | ``JOIN`` query performance issue | -+------------------+-----------------------------------------------------------------------+ | SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | +------------------+-----------------------------------------------------------------------+ | SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command | From 9644cbf5fc78395eed2fd7e71bda8aad2ff4d82f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 10:33:46 +0200 Subject: [PATCH 0325/1892] Update 2022.1.7.rst --- releases/2022.1.7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index af5561432..c9563f9b0 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.7 ************************** -The 2022.1.7 release notes were released on 11/xx/2022 and describe the following: +The 2022.1.7 release notes were released on 11/15/2022 and describe the following: .. contents:: :local: From b5e922fc7d7bef1ecdb8d092097e3e659d49a5e4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 10:42:52 +0200 Subject: [PATCH 0326/1892] Update 2022.1_index.rst --- releases/2022.1_index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index e63294405..5355f1cc4 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,6 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: + 2022.1.7 2022.1.6 2022.1.5 From d39f19854958ed3913c32dc5d5695a2c718afe54 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 13:36:34 +0200 Subject: [PATCH 0327/1892] release --- releases/2022.1.7.rst | 2 +- releases/2022.1.8.rst | 97 +++++++++++++++++++++++++++++++++++++++ releases/2022.1_index.rst | 2 +- 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 releases/2022.1.8.rst diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index c9563f9b0..22b147e29 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.7 ************************** -The 2022.1.7 release notes were released on 11/15/2022 and describe the following: +The 2022.1.7 release notes were released on 15/12/2022 and describe the following: .. contents:: :local: diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst new file mode 100644 index 000000000..f15b5d71d --- /dev/null +++ b/releases/2022.1.8.rst @@ -0,0 +1,97 @@ +.. _2022.1.8: + +************************** +Release Notes 2022.1.8 +************************** +The 2022.1.8 release notes were released on xx/xx/2022 and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +---------- + + * Ingesting data from JSON files. + + :: + + * ZLIB compression performance enhancements. + + :: + + +Known Issues +--------- +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + +Version 2022.1.8 resolved Issues +--------- + ++------------------+-----------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==================+=======================================================================+ +| SQ-11523 | ``SAVED QUERY`` execution internal error | ++------------------+-----------------------------------------------------------------------+ +| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | ++------------------+-----------------------------------------------------------------------+ +| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command | ++------------------+-----------------------------------------------------------------------+ + +Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v2022.1.8 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index 5355f1cc4..a41453b32 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,7 +13,7 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: - + 2022.1.8 2022.1.7 2022.1.6 2022.1.5 From 0b0e4da0a910257f5f009690aa0936a33707a4de Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 14:06:01 +0200 Subject: [PATCH 0328/1892] Update 2022.1.8.rst --- releases/2022.1.8.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index f15b5d71d..5364a5fde 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -31,11 +31,11 @@ Version 2022.1.8 resolved Issues +------------------+-----------------------------------------------------------------------+ | **SQ No.** | **Description** | +==================+=======================================================================+ -| SQ-11523 | ``SAVED QUERY`` execution internal error | +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | +------------------+-----------------------------------------------------------------------+ -| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | +| SQ-11772 | Slow ``JOIN`` query | +------------------+-----------------------------------------------------------------------+ -| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command | +| SQ-12228 | | +------------------+-----------------------------------------------------------------------+ Configuration Changes From 1ee8be95313e4706899613efbd1c427b615bfb11 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 15 Dec 2022 14:56:46 +0200 Subject: [PATCH 0329/1892] Update 2022.1.7.rst --- releases/2022.1.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index 22b147e29..b3fda33ff 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.7 ************************** -The 2022.1.7 release notes were released on 15/12/2022 and describe the following: +The 2022.1.7 release notes were released on 12/15/2022 and describe the following: .. contents:: :local: @@ -12,7 +12,7 @@ The 2022.1.7 release notes were released on 15/12/2022 and describe the followin New Features ---------- - * Ingesting data from JSON files. + * Ingesting data from :ref:`JSON<json>` files. :: From 1a492e6e89e4431a3788b40bd3992ea778d9f68c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Dec 2022 16:09:22 +0200 Subject: [PATCH 0330/1892] release --- external_storage_platforms/index.rst | 1 + external_storage_platforms/s3.rst | 3 ++- index.rst | 1 + releases/2022.1.8.rst | 33 ++++++++++++++++++---------- 4 files changed, 26 insertions(+), 12 deletions(-) diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index 92c35ee63..827fdf190 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -10,6 +10,7 @@ SQream supports the following external storage platforms: :titlesonly: s3 + hdfs For more information, see the following: diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index f8bb2dab6..a3111f3b9 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -12,7 +12,8 @@ The **Amazon S3** describes the following topics: S3 Configuration ============================== -Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. + +A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_ S3 URI Format =============== diff --git a/index.rst b/index.rst index c3d41c39c..61e31b593 100644 --- a/index.rst +++ b/index.rst @@ -81,6 +81,7 @@ If you're looking for an older version of the documentation, go to http://previo installation_guides/index data_ingestion/index connecting_to_sqream/index + external_storage_platforms/index loading_and_unloading_data/index feature_guides/index operational_guides/index diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index 5364a5fde..0fc5cafe6 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -12,11 +12,11 @@ The 2022.1.8 release notes were released on xx/xx/2022 and describe the followin New Features ---------- - * Ingesting data from JSON files. + * xxxxxxxxx GCP :: - * ZLIB compression performance enhancements. + * xxxxxxxxx :: @@ -28,15 +28,26 @@ Known Issues Version 2022.1.8 resolved Issues --------- -+------------------+-----------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+==================+=======================================================================+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+------------------+-----------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+------------------+-----------------------------------------------------------------------+ -| SQ-12228 | | -+------------------+-----------------------------------------------------------------------+ ++---------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++===============+==========================================================================================+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | ++---------------+------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------+ +| | | ++---------------+------------------------------------------------------------------------------------------+ + Configuration Changes -------- From 9fe508b97dca09e4e37fa26da469115638fa7ba5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 18 Dec 2022 12:34:46 +0200 Subject: [PATCH 0331/1892] Access control - UPDATE --- operational_guides/access_control.rst | 2 +- operational_guides/access_control_permissions.rst | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/operational_guides/access_control.rst b/operational_guides/access_control.rst index 8aba611eb..9a1ce9f17 100644 --- a/operational_guides/access_control.rst +++ b/operational_guides/access_control.rst @@ -8,8 +8,8 @@ Access Control :maxdepth: 1 :titlesonly: - access_control_password_policy access_control_overview + access_control_password_policy access_control_managing_roles access_control_permissions access_control_departmental_example \ No newline at end of file diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 5afc23009..25ff6ba14 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -88,7 +88,7 @@ GRANT TO <role> [, ...] -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL } [, ...] | ALL [PERMISSIONS]} + GRANT {{SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL [PERMISSIONS]} ON { TABLE <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] @@ -155,7 +155,7 @@ REVOKE FROM <role> [, ...] -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL } [, ...] | ALL } + REVOKE { { SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL } ON { [ TABLE ] <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...] } @@ -213,6 +213,7 @@ schema statement is run. | INSERT | DELETE | DDL + | UPDATE | EXECUTE | ALL } \ No newline at end of file From 1cf91841c43a04b4f31da817630cfaae072daf2d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:34:26 +0200 Subject: [PATCH 0332/1892] Update 2022.1.8.rst --- releases/2022.1.8.rst | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index 0fc5cafe6..50ae0a675 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -37,16 +37,24 @@ Version 2022.1.8 resolved Issues +---------------+------------------------------------------------------------------------------------------+ | SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | +---------------+------------------------------------------------------------------------------------------+ -| | | +| SQ-11296 | Slow catalog queries | +---------------+------------------------------------------------------------------------------------------+ -| | | +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | +---------------+------------------------------------------------------------------------------------------+ -| | | +| SQ-12255 | ``COPY TO`` string export error | +---------------+------------------------------------------------------------------------------------------+ -| | | +| SQ-12310 | ``DICT`` compression buffer size issue | +---------------+------------------------------------------------------------------------------------------+ -| | | +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | +---------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++---------------+------------------------------------------------------------------------------------------+ + + + + Configuration Changes From 31e595ee44f71425f8382d2b8bf5f6d43648a5db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Dec 2022 17:29:48 +0200 Subject: [PATCH 0333/1892] Trino --- .../client_platforms/index.rst | 1 + .../client_platforms/trino.rst | 95 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/trino.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index be5f4af16..d8c122480 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -21,6 +21,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :caption: In this section: :titlesonly: + trino informatica microstrategy pentaho diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst new file mode 100644 index 000000000..63ef65bc0 --- /dev/null +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -0,0 +1,95 @@ +.. _trino: + +************************* +Connecting to SQream Using Trino +************************* + +Overview +===================== +SQream's Trino connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. + +The **Connecting to SQream Using Trino** page is a Quick Start Guide that describes how to install Trino and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Trino. + + + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------- + +SQream version xxxxx +JDBC version 4.5.6 or later +Trino version 403 or later + + +Installing the Trino Connector Plugin +------------------------------------- + +Install the Trino plugin on all nodes dedicated to Trino within your cluster. + +1. Create a dedicated directory for the Trino plugin. + +2. Download the latest version of Trino plugin. + +3. Extract the Trino plugin ZIP file and copy the extracted directory into the Trino plugin directory. + +.. code-block:: postgres + + trino-server/ + └── plugin + └── sqream + ├── sqream-jdbc.jar + ├── trino-sqream-services.jar + ├── trino-sqream-SNAPSHOT.jar + └── all dependencies + + + +Connecting to SQream +-------------------- + +Under ``trino-server/etc/catalog``, create a ``sqream.properties`` file. + +.. code-block:: postgres + + connector.name=sqream + connection-url=jdbc:Sqream://<host>:<port>/<database>... + +Supported Data Types and Mapping +-------------------------------- + +When executing queries in Trino, use Trino data types. The plugin converts them into SQream data types. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Trino type + - SQream type + * - ``BOOLEAN`` + - ``BOOL`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``REAL`` + - ``REAL`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``VARCHAR(N)`` + - ``VARCHAR(N)`` + * - ``VARCHAR`` + - ``TEXT`` + * - ``DECIMAL(P,S)`` + - ``NUMERIC(P,S)`` + From 493486f11ca31472adb1f709f6bdd0e6c9681d91 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Dec 2022 09:46:57 +0200 Subject: [PATCH 0334/1892] Update create_table.rst --- .../ddl_commands/create_table.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index f32afe2dd..3d0299185 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -51,7 +51,7 @@ The following parameters can be used when creating a table: * - Parameter - Description * - ``OR REPLACE`` - - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + - Creates a new table and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check table contents or structure, only the table name. * - ``schema_name`` - The name of the schema in which to create the table. * - ``table_name`` @@ -263,7 +263,7 @@ The generated output of both of the statements above is identical. Creating a Table based on Foreign Tables and Views ~~~~~~~~~~~~ -The following is example of creating a table based on foreign tables and views: +The following is an example of creating a table based on foreign tables and views: .. code-block:: postgres @@ -271,24 +271,24 @@ The following is example of creating a table based on foreign tables and views: CREATE VIEW v as SELECT x+1,y,y || 'abc' from t1; CREATE TABLE t3 LIKE v; -When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be a regular or an external table, or a view. +When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be either a regular or an external table, or a view. -The following table describes the properties that must be copied from the target table: +The following table describes which properties are copied from the target table to the newly created table: +-----------------------------+------------------+---------------------------------+---------------------------------+ | **Property** | **Native Table** | **External Table** | **View** | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| Column names | Must be copied | Must be copied | Must be copied | +| Column names | Copied | Copied | Copied | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| Column types | Must be copied | Must be copied | Must be copied | +| Column types | Copied | Copied | Copied | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| ``NULL``/``NOT NULL`` | Must be copied | Must be copied | Must be copied | +| ``NULL``/``NOT NULL`` | Copied | Copied | Copied | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| ``text`` length constraints | Must be copied | Must be copied | Does not exist in source object | +| ``text`` length constraints | Copied | Copied | Does not exist in source object | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| Compression specification | Must be copied | Does not exist in source object | Does not exist in source object | +| Compression specification | Copied | Does not exist in source object | Does not exist in source object | +-----------------------------+------------------+---------------------------------+---------------------------------+ -| Default/identity | Must be copied | Does not exist in source object | Does not exist in source object | +| Default/identity | Copied | Does not exist in source object | Does not exist in source object | +-----------------------------+------------------+---------------------------------+---------------------------------+ Permissions From 378082f190601edb9787711398189aa149c5641c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Dec 2022 10:05:24 +0200 Subject: [PATCH 0335/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 3d0299185..47d684653 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -271,7 +271,7 @@ The following is an example of creating a table based on foreign tables and view CREATE VIEW v as SELECT x+1,y,y || 'abc' from t1; CREATE TABLE t3 LIKE v; -When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be either a regular or an external table, or a view. +When duplicating the column structure of an existing table, the target table of the ``LIKE`` clause can be either a native, a regular, or an external table, or a view. The following table describes which properties are copied from the target table to the newly created table: From 984b224c50e1e362aa1370a3d04534b4dc2657af Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Dec 2022 17:42:21 +0200 Subject: [PATCH 0336/1892] Trino --- .../client_drivers/jdbc/index.rst | 2 +- .../client_platforms/trino.rst | 86 +++++++++++++++---- releases/2022.1.8.rst | 2 +- 3 files changed, 69 insertions(+), 21 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 832987efa..83bdc3801 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -82,7 +82,7 @@ The following is the syntax for SQream: .. code-block:: text - jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>sqream;[<optional parameters>; ...] + jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>;[<optional parameters>; ...] Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst index 63ef65bc0..930d9b95c 100644 --- a/connecting_to_sqream/client_platforms/trino.rst +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -6,10 +6,7 @@ Connecting to SQream Using Trino Overview ===================== -SQream's Trino connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. - -The **Connecting to SQream Using Trino** page is a Quick Start Guide that describes how to install Trino and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Trino. - +The JDBC based SQream Trino plugin supports large volumes of data storage and fast querying. .. contents:: @@ -18,22 +15,32 @@ The **Connecting to SQream Using Trino** page is a Quick Start Guide that descri Prerequisites ------------- +To use Trino with SQream, you must have the following installed: + +* SQream version 2022.1.8 or later +* Trino version 403 or later +* SQream Trino plugin xxxx +* JDBC version 4.5.6 or later -SQream version xxxxx -JDBC version 4.5.6 or later -Trino version 403 or later - -Installing the Trino Connector Plugin -------------------------------------- -Install the Trino plugin on all nodes dedicated to Trino within your cluster. +Installation +------------ + +.. contents:: + :local: + :depth: 1 -1. Create a dedicated directory for the Trino plugin. -2. Download the latest version of Trino plugin. +SQream Trino Plugin +~~~~~~~~~~~~~~~~~~~ + +The SQream Trino plugin must be installed on each cluster node dedicated to Trino. + +1. Create a dedicated directory for the SQream Trino plugin. + +2. Download the `SQream Trino Plugin<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: -3. Extract the Trino plugin ZIP file and copy the extracted directory into the Trino plugin directory. .. code-block:: postgres @@ -45,22 +52,52 @@ Install the Trino plugin on all nodes dedicated to Trino within your cluster. ├── trino-sqream-SNAPSHOT.jar └── all dependencies +JDBC +~~~~ +In case JDBC is not yet installed on your system, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for installation and configuration guidance. Connecting to SQream -------------------- -Under ``trino-server/etc/catalog``, create a ``sqream.properties`` file. +Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish for Trino to have access to more than one SQream database or server, you must create additional catalogs. + +Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. + +The following is an example of a properties file: + +.. code-block:: postgres + + connector.name=<name> + connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] + connection-user=<user> + connection-password=<password> + +Syntax examples +--------------- + +The following is an example of the ``SHOW SCHEMAS FROM`` statement: .. code-block:: postgres - connector.name=sqream - connection-url=jdbc:Sqream://<host>:<port>/<database>... + SHOW SCHEMAS FROM sqream; + +The following is an example of the ``SHOW TABLES FROM`` statement: + +.. code-block:: postgres + + SHOW TABLES FROM sqream.public; + +The following is an example of the ``DESCRIBE sqream.public.t`` statement: + +.. code-block:: postgres + + DESCIBE sqream.public.t; + Supported Data Types and Mapping -------------------------------- - -When executing queries in Trino, use Trino data types. The plugin converts them into SQream data types. +Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. .. list-table:: :widths: auto @@ -93,3 +130,14 @@ When executing queries in Trino, use Trino data types. The plugin converts them * - ``DECIMAL(P,S)`` - ``NUMERIC(P,S)`` + + +Limitations +----------- + +SQream does not support the following SQL statements: + +``GRANT`` +``REVOKE`` +``SHOW GRANTSHOW ROLES`` +``SHOW ROLE GRANTS`` \ No newline at end of file diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index 50ae0a675..46ca54d1d 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -16,7 +16,7 @@ New Features :: - * xxxxxxxxx + * xxxxxxxxx Trino :: From 0190b95d720dff4ec3d778b001d51675bd662986 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 10:03:59 +0200 Subject: [PATCH 0337/1892] Update trino.rst --- connecting_to_sqream/client_platforms/trino.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst index 930d9b95c..cdbbc981a 100644 --- a/connecting_to_sqream/client_platforms/trino.rst +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -55,7 +55,7 @@ The SQream Trino plugin must be installed on each cluster node dedicated to Trin JDBC ~~~~ -In case JDBC is not yet installed on your system, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for installation and configuration guidance. +In case JDBC is not yet deployed, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. Connecting to SQream -------------------- @@ -92,7 +92,7 @@ The following is an example of the ``DESCRIBE sqream.public.t`` statement: .. code-block:: postgres - DESCIBE sqream.public.t; + DESCRIBE sqream.public.t; Supported Data Types and Mapping @@ -124,7 +124,7 @@ Use the appropriate Trino data type for executing queries. Upon execution, incom * - ``TIMESTAMP`` - ``DATETIME`` * - ``VARCHAR(N)`` - - ``VARCHAR(N)`` + - ``VARCHAR(N)``. Note that VARCHAR is soon to be deprecated and may not be used in SQream DB. * - ``VARCHAR`` - ``TEXT`` * - ``DECIMAL(P,S)`` From 61c748e181d33adcf1cfc940d09fd473d13a6c17 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 10:14:06 +0200 Subject: [PATCH 0338/1892] Delete trino.rst --- .../client_platforms/trino.rst | 143 ------------------ 1 file changed, 143 deletions(-) delete mode 100644 connecting_to_sqream/client_platforms/trino.rst diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst deleted file mode 100644 index cdbbc981a..000000000 --- a/connecting_to_sqream/client_platforms/trino.rst +++ /dev/null @@ -1,143 +0,0 @@ -.. _trino: - -************************* -Connecting to SQream Using Trino -************************* - -Overview -===================== -The JDBC based SQream Trino plugin supports large volumes of data storage and fast querying. - - -.. contents:: - :local: - :depth: 1 - -Prerequisites -------------- -To use Trino with SQream, you must have the following installed: - -* SQream version 2022.1.8 or later -* Trino version 403 or later -* SQream Trino plugin xxxx -* JDBC version 4.5.6 or later - - - -Installation ------------- - -.. contents:: - :local: - :depth: 1 - - -SQream Trino Plugin -~~~~~~~~~~~~~~~~~~~ - -The SQream Trino plugin must be installed on each cluster node dedicated to Trino. - -1. Create a dedicated directory for the SQream Trino plugin. - -2. Download the `SQream Trino Plugin<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: - - -.. code-block:: postgres - - trino-server/ - └── plugin - └── sqream - ├── sqream-jdbc.jar - ├── trino-sqream-services.jar - ├── trino-sqream-SNAPSHOT.jar - └── all dependencies - -JDBC -~~~~ - -In case JDBC is not yet deployed, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. - -Connecting to SQream --------------------- - -Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish for Trino to have access to more than one SQream database or server, you must create additional catalogs. - -Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. - -The following is an example of a properties file: - -.. code-block:: postgres - - connector.name=<name> - connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] - connection-user=<user> - connection-password=<password> - -Syntax examples ---------------- - -The following is an example of the ``SHOW SCHEMAS FROM`` statement: - -.. code-block:: postgres - - SHOW SCHEMAS FROM sqream; - -The following is an example of the ``SHOW TABLES FROM`` statement: - -.. code-block:: postgres - - SHOW TABLES FROM sqream.public; - -The following is an example of the ``DESCRIBE sqream.public.t`` statement: - -.. code-block:: postgres - - DESCRIBE sqream.public.t; - - -Supported Data Types and Mapping --------------------------------- -Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Trino type - - SQream type - * - ``BOOLEAN`` - - ``BOOL`` - * - ``TINYINT`` - - ``TINYINT`` - * - ``SMALLINT`` - - ``SMALLINT`` - * - ``INT`` - - ``INT`` - * - ``BIGINT`` - - ``BIGINT`` - * - ``REAL`` - - ``REAL`` - * - ``DOUBLE`` - - ``DOUBLE`` - * - ``DATE`` - - ``DATE`` - * - ``TIMESTAMP`` - - ``DATETIME`` - * - ``VARCHAR(N)`` - - ``VARCHAR(N)``. Note that VARCHAR is soon to be deprecated and may not be used in SQream DB. - * - ``VARCHAR`` - - ``TEXT`` - * - ``DECIMAL(P,S)`` - - ``NUMERIC(P,S)`` - - - -Limitations ------------ - -SQream does not support the following SQL statements: - -``GRANT`` -``REVOKE`` -``SHOW GRANTSHOW ROLES`` -``SHOW ROLE GRANTS`` \ No newline at end of file From 00c8c43f31165a9cb2daa36e74ed032448b6901e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 11:25:21 +0200 Subject: [PATCH 0339/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index d8c122480..8d468e5f5 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -21,7 +21,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :caption: In this section: :titlesonly: - trino + informatica microstrategy pentaho From 4ad945717e3a5d5ee1548ea8117af4daf772c12c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 16:47:38 +0200 Subject: [PATCH 0340/1892] Trino --- .../client_platforms/index.rst | 1 + .../client_platforms/trino.rst | 143 ++++++++++++++++++ operational_guides/index.rst | 1 + operational_guides/ldap.rst | 110 ++++++++++++++ .../sql_statements/dml_commands/delete.rst | 7 + releases/2022.1.8.rst | 4 +- releases/4.0.0_index.rst | 116 ++++++++++++++ releases/index.rst | 3 + 8 files changed, 383 insertions(+), 2 deletions(-) create mode 100644 connecting_to_sqream/client_platforms/trino.rst create mode 100644 operational_guides/ldap.rst create mode 100644 releases/4.0.0_index.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 8d468e5f5..5d6092e14 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -22,6 +22,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :titlesonly: + trino informatica microstrategy pentaho diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst new file mode 100644 index 000000000..b0e21f954 --- /dev/null +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -0,0 +1,143 @@ +.. _trino: + +************************* +Connecting to SQream Using Trino +************************* + +Overview +===================== +The JDBC based SQream Trino plugin supports large volumes of data storage and fast querying. + + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------- +To use Trino with SQream, you must have the following installed: + +* SQream version 2022.1.8 or later +* Trino version 403 or later +* SQream Trino plugin xxxx +* JDBC version 4.5.6 or later + + + +Installation +------------ + +.. contents:: + :local: + :depth: 1 + + +SQream Trino Plugin +~~~~~~~~~~~~~~~~~~~ + +The SQream Trino plugin must be installed on each cluster node dedicated to Trino. + +1. Create a dedicated directory for the SQream Trino plugin. + +2. Download the `SQream Trino Plugin<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: + + +.. code-block:: postgres + + trino-server/ + └── plugin + └── sqream + ├── sqream-jdbc.jar + ├── trino-sqream-services.jar + ├── trino-sqream-SNAPSHOT.jar + └── all dependencies + +JDBC +~~~~ + +In case JDBC is not yet deployed, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. + +Connecting to SQream +-------------------- + +Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish for Trino to have access to more than one SQream database or server, you must create additional catalogs. + +Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. + +The following is an example of a properties file: + +.. code-block:: postgres + + connector.name=<name> + connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] + connection-user=<user> + connection-password=<password> + +Syntax examples +--------------- + +The following is an example of the ``SHOW SCHEMAS FROM`` statement: + +.. code-block:: postgres + + SHOW SCHEMAS FROM sqream; + +The following is an example of the ``SHOW TABLES FROM`` statement: + +.. code-block:: postgres + + SHOW TABLES FROM sqream.public; + +The following is an example of the ``DESCRIBE sqream.public.t`` statement: + +.. code-block:: postgres + + DESCRIBE sqream.public.t; + + +Supported Data Types and Mapping +-------------------------------- +Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Trino type + - SQream type + * - ``BOOLEAN`` + - ``BOOL`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``REAL`` + - ``REAL`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``VARCHAR(N)`` + - ``VARCHAR(N)``. + * - ``VARCHAR`` + - ``TEXT`` + * - ``DECIMAL(P,S)`` + - ``NUMERIC(P,S)`` + +.. note:: ``VARCHAR`` is soon to be deprecated and may not be used in SQream DB. + +Limitations +----------- + +SQream does not support the following SQL statements: + +``GRANT`` +``REVOKE`` +``SHOW GRANTSHOW ROLES`` +``SHOW ROLE GRANTS`` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 048efb06f..ee45ec254 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -21,6 +21,7 @@ This section summarizes the following operational guides: logging monitoring_query_performance security + ldap saved_queries seeing_system_objects_as_ddl configuration diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst new file mode 100644 index 000000000..1cfe78bd2 --- /dev/null +++ b/operational_guides/ldap.rst @@ -0,0 +1,110 @@ +.. _ldap: + +************************* +LDAP Authentication +************************* + +.. contents:: In this topic: + :local: + + +Overview +============ + +Lightweight Directory Access Protocol (LDAP) is an external authentication source. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an external LDAP server. + + +New Flag Attributes +------------------- +To enable LDAP Authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Attribute + - Description + * - ``authenticationMethod`` + - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP, choose ``ldap``. + * - ``ldapDomain`` + - Configure users` location domain. + * - ``ldapIpAddress`` + - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + * - ``ldapConnTimeoutSec`` + - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. + + +LDAP Configuration +================== + +Configuring system roles +------------------------ +It is recommend to set up the roles of externally authenticated users in advance. + +To set up roles, follow these steps: + +1. Create a new role. + +.. code-block:: postgres + + CREATE ROLE my_new_role; + +2. Grant new role login permissions. + +.. code-block:: postgres + + GRANT LOGIN TO my_new_role; + +Grant a specific database role ``CONNECT`` permissions. + +.. code-block:: postgres + + GRANT CONNECT ON DATABASE my_database TO my_new_role; + +Note - in the case that no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. + + +Enabling LDAP Authentication +---------------------------- + +Only roles with admin privileges or higher may enable LDAP Authentication. + +To enable LDAP Authentication, follow these steps. The provided syntax for each of the steps is an example. + +1. Set the ``ldapIpAddress`` attribute. + +.. code-block:: postgres + + ALTER SYSTEM SET ldapIpAddress = 'ldaps://192.168.10.20'; + +2. Set the ``ldapDomain`` attribute. + +.. code-block:: postgres + + ALTER SYSTEM SET ldapDomain = '@sqream.loc'; + +3. Set the ``ldapConnTimeoutSec`` attribute (Optional). + +.. code-block:: postgres + + ALTER SYSTEM SET ldapConnTimeoutSec = 15; + +4. Set the ``authenticationMethod`` attribute. + +.. code-block:: postgres + + ALTER SYSTEM SET authenticationMethod = 'ldap'; + +5. **Reset all ``sqreamd`` servers.** + + +Disabling LDAP Authentication +----------------------------- + +To disable LDAB authentication and configure sqream authentication, execute the following syntax: + +.. code-block:: postgres + + ALTER SYSTEM SET authenticationMethod = 'sqream'; + + diff --git a/reference/sql/sql_statements/dml_commands/delete.rst b/reference/sql/sql_statements/dml_commands/delete.rst index 2aa9c6729..9240172e7 100644 --- a/reference/sql/sql_statements/dml_commands/delete.rst +++ b/reference/sql/sql_statements/dml_commands/delete.rst @@ -72,6 +72,13 @@ The following is the correct syntax for triggering a clean-up: schema_name ::= identifier +For high-concurrency storage systems, use the following syntax to enhance deletion performance and shorten runtime: + +.. code-block:: postgres + + SELECT set_parallel_delete_threads(x); + +.. note:: You may configure up to 10 threads. Parameters ============ diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index 46ca54d1d..d081d3998 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -12,11 +12,11 @@ The 2022.1.8 release notes were released on xx/xx/2022 and describe the followin New Features ---------- - * xxxxxxxxx GCP + * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature :: - * xxxxxxxxx Trino + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities :: diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst new file mode 100644 index 000000000..829177e8e --- /dev/null +++ b/releases/4.0.0_index.rst @@ -0,0 +1,116 @@ +.. _4.0.0: + +************************** +Release Notes 4.0.0 +************************** +The 4.0.0 release notes were released on xx/xx/20xx and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +---------- + + * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature + + :: + + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + + :: + + +Known Issues +--------- +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + +Version 4.0.0 resolved Issues +--------- + ++---------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++===============+==========================================================================================+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12255 | ``COPY TO`` string export error | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12310 | ``DICT`` compression buffer size issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++---------------+------------------------------------------------------------------------------------------+ + + + + + + +Configuration Changes +-------- +No configuration changes were made. + +Naming Changes +------- +No relevant naming changes were made. + +Deprecated Features +------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +------- +No End of Support changes were made. + +Upgrading to v4.0.0 +------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/index.rst b/releases/index.rst index 84024586e..107f323c8 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,6 +12,8 @@ Release Notes * - Version - Release Date + * - :ref:`4.0.0` + - XXXX xx, xxxx * - :ref:`2022.1` - July 19, 2022 * - :ref:`2021.2` @@ -32,6 +34,7 @@ Release Notes :glob: :hidden: + 4.0.0_index 2022.1_index 2021.2_index 2021.1_index From 7564a0d97c276c8b535fca0b4c2ba8355a997468 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 17:15:49 +0200 Subject: [PATCH 0341/1892] Deletion --- reference/sql/sql_statements/dml_commands/delete.rst | 2 +- releases/2022.1.8.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/delete.rst b/reference/sql/sql_statements/dml_commands/delete.rst index 9240172e7..b561eaf78 100644 --- a/reference/sql/sql_statements/dml_commands/delete.rst +++ b/reference/sql/sql_statements/dml_commands/delete.rst @@ -72,7 +72,7 @@ The following is the correct syntax for triggering a clean-up: schema_name ::= identifier -For high-concurrency storage systems, use the following syntax to enhance deletion performance and shorten runtime: +For systems with delete parallelism capabilities, use the following syntax to enhance deletion performance and shorten runtime: .. code-block:: postgres diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst index d081d3998..c7ea25263 100644 --- a/releases/2022.1.8.rst +++ b/releases/2022.1.8.rst @@ -16,7 +16,7 @@ New Features :: - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + * :ref:`Physical deletion performance enhancement<delete>` for file systems with delete parallelism capabilities :: From 63ef1a112cbf39698e1c59cd0e94a81ec4afc8a6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Dec 2022 17:42:02 +0200 Subject: [PATCH 0342/1892] Update ldap.rst --- operational_guides/ldap.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 1cfe78bd2..596dd382e 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -25,9 +25,9 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut * - Attribute - Description * - ``authenticationMethod`` - - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP, choose ``ldap``. + - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. * - ``ldapDomain`` - - Configure users` location domain. + - Configure users` domain. * - ``ldapIpAddress`` - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` @@ -39,9 +39,9 @@ LDAP Configuration Configuring system roles ------------------------ -It is recommend to set up the roles of externally authenticated users in advance. +When using external authentication such as LDAP, it is recommend that roles be configured in advance. -To set up roles, follow these steps: +To configure roles, follow these steps: 1. Create a new role. @@ -55,7 +55,7 @@ To set up roles, follow these steps: GRANT LOGIN TO my_new_role; -Grant a specific database role ``CONNECT`` permissions. +Grant the new role ``CONNECT`` permissions. .. code-block:: postgres From daa2205903dba5f46487e67813176996e6dad7fc Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 12:19:01 +0200 Subject: [PATCH 0343/1892] Update ldap.rst --- operational_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 596dd382e..cf8036739 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -11,7 +11,7 @@ LDAP Authentication Overview ============ -Lightweight Directory Access Protocol (LDAP) is an external authentication source. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an external LDAP server. +Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an external LDAP server. New Flag Attributes From 7b8b68e317ab2deffd0113dcf0a48c9651d8e08b Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 12:21:56 +0200 Subject: [PATCH 0344/1892] Update ldap.rst --- operational_guides/ldap.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index cf8036739..16b2e1115 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -9,13 +9,13 @@ LDAP Authentication Overview -============ +======== -Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an external LDAP server. +Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an LDAP server. -New Flag Attributes -------------------- +Flag Attributes +--------------- To enable LDAP Authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: .. list-table:: From 7e68e0d14cc9623b91ee96dcb8a8b127b160cedd Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 12:24:54 +0200 Subject: [PATCH 0345/1892] Update ldap.rst --- operational_guides/ldap.rst | 38 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 16b2e1115..2133927d9 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -13,26 +13,6 @@ Overview Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an LDAP server. - -Flag Attributes ---------------- -To enable LDAP Authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Attribute - - Description - * - ``authenticationMethod`` - - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. - * - ``ldapDomain`` - - Configure users` domain. - * - ``ldapIpAddress`` - - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. - * - ``ldapConnTimeoutSec`` - - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. - LDAP Configuration ================== @@ -63,6 +43,24 @@ Grant the new role ``CONNECT`` permissions. Note - in the case that no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. +Flag Attributes +--------------- +To enable LDAP Authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Attribute + - Description + * - ``authenticationMethod`` + - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + * - ``ldapDomain`` + - Configure users` domain. + * - ``ldapIpAddress`` + - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + * - ``ldapConnTimeoutSec`` + - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. Enabling LDAP Authentication ---------------------------- From 2e76150951c4669e3858ef4e17ee7a501762ec4f Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 12:49:23 +0200 Subject: [PATCH 0346/1892] Update ldap.rst --- operational_guides/ldap.rst | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 2133927d9..44e707559 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -1,25 +1,26 @@ .. _ldap: -************************* -LDAP Authentication -************************* - -.. contents:: In this topic: - :local: +************************************* +Configuring authentication using LDAP +************************************* -Overview -======== - Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an LDAP server. + +.. contents:: In this topic: + :local: + + LDAP Configuration ================== Configuring system roles ------------------------ -When using external authentication such as LDAP, it is recommend that roles be configured in advance. + +It is recommended that SQream roles be configured before implementing LDAP authentication. + To configure roles, follow these steps: From bfa8442273777d4745cac40542af0d5f067fbc1c Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 12:52:35 +0200 Subject: [PATCH 0347/1892] Update ldap.rst --- operational_guides/ldap.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 44e707559..63f64d2c4 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -16,13 +16,13 @@ Lightweight Directory Access Protocol (LDAP) is an authentication management ser LDAP Configuration ================== -Configuring system roles +Configuring SQream roles ------------------------ It is recommended that SQream roles be configured before implementing LDAP authentication. -To configure roles, follow these steps: +**Procedure** 1. Create a new role. From d20105ad15807ee3578bc27046836cc418041b3a Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 13:02:01 +0200 Subject: [PATCH 0348/1892] Update ldap.rst --- operational_guides/ldap.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 63f64d2c4..6ab04dbdb 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -24,25 +24,26 @@ It is recommended that SQream roles be configured before implementing LDAP authe **Procedure** -1. Create a new role. +1. To create a new role, run: .. code-block:: postgres - CREATE ROLE my_new_role; + CREATE ROLE <new_role>; -2. Grant new role login permissions. +2. To grant new role login permissions: .. code-block:: postgres - GRANT LOGIN TO my_new_role; + GRANT LOGIN TO <new_role>; -Grant the new role ``CONNECT`` permissions. +3. To grant the new role ``CONNECT`` permissions: .. code-block:: postgres - GRANT CONNECT ON DATABASE my_database TO my_new_role; + GRANT CONNECT ON DATABASE <my_database> TO <new_role>; -Note - in the case that no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. + +If no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. Flag Attributes --------------- From b732256201e825c87d45b21e4f1c53de0cf10869 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 13:38:30 +0200 Subject: [PATCH 0349/1892] Update ldap.rst --- operational_guides/ldap.rst | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 6ab04dbdb..c500dd8d1 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -13,37 +13,39 @@ Lightweight Directory Access Protocol (LDAP) is an authentication management ser :local: -LDAP Configuration -================== Configuring SQream roles ------------------------- +======================== It is recommended that SQream roles be configured before implementing LDAP authentication. **Procedure** -1. To create a new role, run: +1. Create a new role: .. code-block:: postgres CREATE ROLE <new_role>; -2. To grant new role login permissions: +2. Grant new role login permission: .. code-block:: postgres GRANT LOGIN TO <new_role>; -3. To grant the new role ``CONNECT`` permissions: +3. Grant the new role ``CONNECT`` permission: .. code-block:: postgres GRANT CONNECT ON DATABASE <my_database> TO <new_role>; -If no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. +.. note:: If no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. + + +Configuring LDAP Authentication +============================ Flag Attributes --------------- @@ -63,33 +65,34 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. +.. comment:: Enabling LDAP Authentication ----------------------------- +------------------------------- Only roles with admin privileges or higher may enable LDAP Authentication. -To enable LDAP Authentication, follow these steps. The provided syntax for each of the steps is an example. +**Procedure** -1. Set the ``ldapIpAddress`` attribute. +1. Set the ``ldapIpAddress`` attribute: .. code-block:: postgres - ALTER SYSTEM SET ldapIpAddress = 'ldaps://192.168.10.20'; + ALTER SYSTEM SET ldapIpAddress = 'ldaps://<192.168.10.20>'; -2. Set the ``ldapDomain`` attribute. +2. Set the ``ldapDomain`` attribute: .. code-block:: postgres - ALTER SYSTEM SET ldapDomain = '@sqream.loc'; + ALTER SYSTEM SET ldapDomain = <'@sqream.loc'>; -3. Set the ``ldapConnTimeoutSec`` attribute (Optional). +3. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: .. code-block:: postgres - ALTER SYSTEM SET ldapConnTimeoutSec = 15; + ALTER SYSTEM SET ldapConnTimeoutSec = <15>; -4. Set the ``authenticationMethod`` attribute. +4. Set the ``authenticationMethod`` attribute: .. code-block:: postgres @@ -101,7 +104,7 @@ To enable LDAP Authentication, follow these steps. The provided syntax for each Disabling LDAP Authentication ----------------------------- -To disable LDAB authentication and configure sqream authentication, execute the following syntax: +To disable LDAP authentication and configure sqream authentication, execute the following syntax: .. code-block:: postgres From 6175f17fb59bdd7acb441526bd23fe145288fb58 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 14:13:51 +0200 Subject: [PATCH 0350/1892] Update ldap.rst --- operational_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index c500dd8d1..299ed02c7 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -1,7 +1,7 @@ .. _ldap: ************************************* -Configuring authentication using LDAP +Configuring LDAP authentication ************************************* From 058f3ca96b9e0148c49bf91e293fdea9a56e0b5c Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 26 Dec 2022 14:16:00 +0200 Subject: [PATCH 0351/1892] Update ldap.rst --- operational_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/ldap.rst b/operational_guides/ldap.rst index 299ed02c7..a91e3387c 100644 --- a/operational_guides/ldap.rst +++ b/operational_guides/ldap.rst @@ -104,7 +104,7 @@ Only roles with admin privileges or higher may enable LDAP Authentication. Disabling LDAP Authentication ----------------------------- -To disable LDAP authentication and configure sqream authentication, execute the following syntax: +To disable LDAP authentication and configure sqream authentication, use the following syntax: .. code-block:: postgres From 55e1a472e6006b0ebee30ad1ed16422b3cb127e4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Dec 2022 10:36:06 +0200 Subject: [PATCH 0352/1892] LDAP --- configuration_guides/index.rst | 1 + .../ldap.rst | 18 ++++++++++-------- operational_guides/index.rst | 1 - 3 files changed, 11 insertions(+), 9 deletions(-) rename {operational_guides => configuration_guides}/ldap.rst (79%) diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 6805bc188..9c0b206e7 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -12,5 +12,6 @@ The **Configuration Guides** page describes the following configuration informat spooling configuring_sqream + ldap configuration_flags previous_configuration_method \ No newline at end of file diff --git a/operational_guides/ldap.rst b/configuration_guides/ldap.rst similarity index 79% rename from operational_guides/ldap.rst rename to configuration_guides/ldap.rst index a91e3387c..e9c13ad7f 100644 --- a/operational_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,7 +5,7 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing roles, with the exception of a ``SUPERUSER``, are required to be authenticated by an LDAP server. +Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. @@ -17,7 +17,7 @@ Lightweight Directory Access Protocol (LDAP) is an authentication management ser Configuring SQream roles ======================== -It is recommended that SQream roles be configured before implementing LDAP authentication. +It is recommended that SQream roles be configured before implementing LDAP authentication. **Procedure** @@ -45,7 +45,7 @@ It is recommended that SQream roles be configured before implementing LDAP authe Configuring LDAP Authentication -============================ +=============================== Flag Attributes --------------- @@ -62,7 +62,7 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut * - ``ldapDomain`` - Configure users` domain. * - ``ldapIpAddress`` - - Configure the IP address of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. .. comment:: @@ -70,7 +70,7 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut Enabling LDAP Authentication ------------------------------- -Only roles with admin privileges or higher may enable LDAP Authentication. +Only roles with SQream ``SUPERUSER`` privileges or higher may enable LDAP Authentication. **Procedure** @@ -98,16 +98,18 @@ Only roles with admin privileges or higher may enable LDAP Authentication. ALTER SYSTEM SET authenticationMethod = 'ldap'; -5. **Reset all ``sqreamd`` servers.** +5. Restart all sqreamd servers. Disabling LDAP Authentication ----------------------------- -To disable LDAP authentication and configure sqream authentication, use the following syntax: +To disable LDAP authentication and configure sqream authentication: + +1. Execute the following syntax: .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'sqream'; - +2. Restart all sqreamd servers. diff --git a/operational_guides/index.rst b/operational_guides/index.rst index ee45ec254..048efb06f 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -21,7 +21,6 @@ This section summarizes the following operational guides: logging monitoring_query_performance security - ldap saved_queries seeing_system_objects_as_ddl configuration From 0a4e26fc7a829d8ac1e7fb6ea822cfaf3c135d7e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Dec 2022 13:13:31 +0200 Subject: [PATCH 0353/1892] Update ldap.rst --- configuration_guides/ldap.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index e9c13ad7f..c4a03fa87 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,9 +5,9 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. +Lightweight Directory Access Protocol (LDAP) is a Microsoft Active Directory authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. - +It is recommended that SQream roles be configured before integrating LDAP authentication. This is ideal for when SQream DB is installed within an environment which had already been integrated with LDAP or for when creating a new SQream role when SQream DB had already been integrated with LDAP. .. contents:: In this topic: :local: @@ -17,7 +17,6 @@ Lightweight Directory Access Protocol (LDAP) is an authentication management ser Configuring SQream roles ======================== -It is recommended that SQream roles be configured before implementing LDAP authentication. **Procedure** From d08c4126b396f1eef515cd8e450e0b317f987485 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Dec 2022 13:25:42 +0200 Subject: [PATCH 0354/1892] Update ldap.rst --- configuration_guides/ldap.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index c4a03fa87..41f726644 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -7,7 +7,11 @@ Configuring LDAP authentication Lightweight Directory Access Protocol (LDAP) is a Microsoft Active Directory authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. -It is recommended that SQream roles be configured before integrating LDAP authentication. This is ideal for when SQream DB is installed within an environment which had already been integrated with LDAP or for when creating a new SQream role when SQream DB had already been integrated with LDAP. +It is recommended that SQream roles be configured before integrating LDAP authentication. + +This is ideal for when: + * SQream DB is being installed within an environment which had already been integrated with LDAP + * Creating a new SQream role when SQream DB had already been integrated with LDAP .. contents:: In this topic: :local: From b36dfdba5722428eda7e2a036f5cb0406c8e97c9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Dec 2022 16:33:27 +0200 Subject: [PATCH 0355/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 0edb0a4d6..783f9a4f9 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -96,7 +96,7 @@ The following table shows the ``COPY_TO`` elements: * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). Default value: 16*2^20 (16MB). * - ``ENFORCE_SINGLE_FILE`` - - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``FALSE``. + - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``TRUE``. Usage Notes =============== From 1343f354a55be33bfd8196db02cf289e862f7665 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 11:47:35 +0200 Subject: [PATCH 0356/1892] Update ldap.rst --- configuration_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 41f726644..9080699cd 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,7 +5,7 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is a Microsoft Active Directory authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. +Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. It is recommended that SQream roles be configured before integrating LDAP authentication. From b8c9274d694b79fc3df63620661fde1319857ad3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 12:53:04 +0200 Subject: [PATCH 0357/1892] Update 4.0.0_index.rst --- releases/4.0.0_index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index 829177e8e..6a81d2338 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -9,6 +9,8 @@ The 4.0.0 release notes were released on xx/xx/20xx and describe the following: :local: :depth: 1 +SQream is introducing a more commonly used versioning system, beginning with 4.0.0 as a minor version. + New Features ---------- From 9c7c9e9ccb4628c48c8145684440f542e72500ba Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 13:07:54 +0200 Subject: [PATCH 0358/1892] double --- .../sql/sql_functions/scalar_functions/numeric/ceiling.rst | 2 +- reference/sql/sql_functions/scalar_functions/numeric/round.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index fad39aae6..39a63ddab 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -* ``CEIL`` Always returns a floating point result. +``CEIL`` always returns a ``double`` floating point number. Notes diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index 842224edd..553344246 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -Always returns a floating point result. +``ROUND``always returns a ``double`` floating point number. Notes ======= From fa55f8770e23b22377667fba4cf87ade9a773be9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 15:15:44 +0200 Subject: [PATCH 0359/1892] Update ldap.rst --- configuration_guides/ldap.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 9080699cd..d3fa0ddcb 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,13 +5,12 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once LDAP is configured to authenticate SQream users, all existing SQream roles, with the exception of a ``SUPERUSER``, will be required to be authenticated by an LDAP server. +Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. -It is recommended that SQream roles be configured before integrating LDAP authentication. +Prior to integrating SQream with LDAP, two preconditions must be considered: -This is ideal for when: - * SQream DB is being installed within an environment which had already been integrated with LDAP - * Creating a new SQream role when SQream DB had already been integrated with LDAP + * If SQream DB is being installed within an LDAP-integrated environment, it is best practice to ensure that the newly created SQream role names are consistent with existing LDAP user names. + * If LDAP is being integrated with a SQream environment, it is best practice to ensure that the newly created LDAP user names are consistent with existing SQream role names. Note that after LDAP has been successfully integrated, SQream roles that were mistakenly not configured or have conflicting names with LDAP will be recreated in SQream as roles without the ability to log in, without permissions, and without a default schema. .. contents:: In this topic: :local: @@ -44,7 +43,6 @@ Configuring SQream roles GRANT CONNECT ON DATABASE <my_database> TO <new_role>; -.. note:: If no role exists but LDAP authentication is successful, a role with no login or connection permissions will be added. Configuring LDAP Authentication @@ -81,13 +79,13 @@ Only roles with SQream ``SUPERUSER`` privileges or higher may enable LDAP Authen .. code-block:: postgres - ALTER SYSTEM SET ldapIpAddress = 'ldaps://<192.168.10.20>'; + ALTER SYSTEM SET ldapIpAddress = '<ldaps://192.168.10.20>'; 2. Set the ``ldapDomain`` attribute: .. code-block:: postgres - ALTER SYSTEM SET ldapDomain = <'@sqream.loc'>; + ALTER SYSTEM SET ldapDomain = '<@sqream.loc>'; 3. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: From 72a733349e28a0f0f6b0117c555b0d306b4e760e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 15:56:22 +0200 Subject: [PATCH 0360/1892] Update 4.0.0_index.rst --- releases/4.0.0_index.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index 6a81d2338..f846edb4f 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -3,13 +3,16 @@ ************************** Release Notes 4.0.0 ************************** + +**SQream is introducing a more commonly used versioning system, beginning with 4.0.0 as a minor version.** + The 4.0.0 release notes were released on xx/xx/20xx and describe the following: .. contents:: :local: :depth: 1 -SQream is introducing a more commonly used versioning system, beginning with 4.0.0 as a minor version. + New Features ---------- From eec82e0b16b21fedd7e961a30ada0209c8ad58db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 15:59:52 +0200 Subject: [PATCH 0361/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 44579a068..940e21822 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -3,7 +3,7 @@ ************************* Converting and Casting Types ************************* -SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the query results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. +SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. @@ -25,4 +25,24 @@ SQream supports the following three data conversion types: * See the :ref:`SQL functions reference <sql_functions>` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. -.. note:: SQream interprets integer constants exceeding the maximum bigint value as float constants, which may cause precision loss. \ No newline at end of file + +Supported Casts +--------------- + ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME** | **VARCHAR**/**TEXT** | ++==============================================+===========+==============================================+=================+==============+========================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | N/A | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **DATE**/**DATETIME** | ✗ | ✗ | ✗ | ✗ | N/A | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ + + :check_mark: \ No newline at end of file From 710f6ee3e0b538628392bc8bf675995f12cbf94f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 16:25:30 +0200 Subject: [PATCH 0362/1892] Update ldap.rst --- configuration_guides/ldap.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index d3fa0ddcb..56332eea1 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,7 +5,7 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. +Lightweight Directory Access Protocol (LDAP) is an authentication management service widely use with Microsoft Active Directory. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. Prior to integrating SQream with LDAP, two preconditions must be considered: @@ -20,8 +20,6 @@ Prior to integrating SQream with LDAP, two preconditions must be considered: Configuring SQream roles ======================== - - **Procedure** 1. Create a new role: @@ -43,6 +41,7 @@ Configuring SQream roles GRANT CONNECT ON DATABASE <my_database> TO <new_role>; +You may also wish to :ref:`rename SQream roles<rename_role>`. Configuring LDAP Authentication @@ -71,7 +70,7 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut Enabling LDAP Authentication ------------------------------- -Only roles with SQream ``SUPERUSER`` privileges or higher may enable LDAP Authentication. +Roles with admin privileges or higher may enable LDAP Authentication. **Procedure** From f79cc31425499c8e1e461d206438239c972cdbfc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:36:24 +0200 Subject: [PATCH 0363/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index b4869c181..e64d792a0 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -1,7 +1,7 @@ .. _server_picker_cli_reference: ************************* -server_picker +Server Picker ************************* SQream DB's load balancer is called ``server_picker``. From 8d221468130d4c25b6f4b7b188a28b7bff888015 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Dec 2022 17:46:09 +0200 Subject: [PATCH 0364/1892] cnt --- .../sql/sql_functions/scalar_functions/string/left.rst | 6 ++++-- .../sql/sql_functions/scalar_functions/string/right.rst | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/left.rst b/reference/sql/sql_functions/scalar_functions/string/left.rst index 77c99b0f1..143c6eeb7 100644 --- a/reference/sql/sql_functions/scalar_functions/string/left.rst +++ b/reference/sql/sql_functions/scalar_functions/string/left.rst @@ -27,13 +27,15 @@ Arguments * - ``expr`` - String expression * - ``character_count`` - - A positive integer that specifies how many characters to return. - + - A positive integer that specifies how many characters to return + * - ``cnt`` + - The number of characters to be returned. If ``cnt <= 0``, an empty string is returned. Returns ============ Returns the same type as the argument supplied. + Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/string/right.rst b/reference/sql/sql_functions/scalar_functions/string/right.rst index 158de7da0..8cf750510 100644 --- a/reference/sql/sql_functions/scalar_functions/string/right.rst +++ b/reference/sql/sql_functions/scalar_functions/string/right.rst @@ -28,7 +28,8 @@ Arguments - String expression * - ``character_count`` - A positive integer that specifies how many characters to return. - + * - ``cnt`` + - The number of characters to be returned. If ``cnt <= 0``, an empty string is returned. Returns ============ From 727a8dca1ec272d0cdd142bd359199c638bf2e0b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 08:58:00 +0200 Subject: [PATCH 0365/1892] Update round.rst --- reference/sql/sql_functions/scalar_functions/numeric/round.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index 553344246..d362c9abd 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -``ROUND``always returns a ``double`` floating point number. +``ROUND`` always returns a ``double`` floating point number. Notes ======= From db06670f9e12200ccbdd34978349152441c93b3a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 13:19:50 +0200 Subject: [PATCH 0366/1892] kafka --- .../client_drivers/dotnet/index.rst | 2 +- connecting_to_sqream/client_drivers/index.rst | 16 +- .../client_drivers/jdbc/index.rst | 2 +- .../client_drivers/kafka/index.rst | 192 ++++++++++++++++++ .../client_drivers/nodejs/index.rst | 2 +- .../client_drivers/odbc/index.rst | 2 +- .../client_drivers/python/index.rst | 2 +- .../client_platforms/power_bi.rst | 2 +- 8 files changed, 208 insertions(+), 12 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/kafka/index.rst diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 1d28069a7..ed0c61557 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -1,7 +1,7 @@ .. _net: ************************* -.NET +Connecting to SQream Using .NET ************************* The SqreamNet ADO.NET Data Provider lets you connect to SQream through your .NET environment. diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 58791e766..ce6b1ef8d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,22 +18,26 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.3 (.jar) - * `JDBC driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html#>`_ + * :ref:`java_jdbc` .. _.net: * **.NET**: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ - * `.NET driver <https://docs.sqream.com/en/v2022.1.6/connecting_to_sqream/client_drivers/dotnet/index.html>`_ + * :ref:`net` +* **Kafka**: + + * `Kafka file <>`_ + * :ref:`kafka` .. _python: * **Python** - Recommended installation via ``pip``: * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.1.3>`_ - pysqream v3.1.3 (.tar.gz) - * `Python driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/python/index.html>`_ + * :ref:`pysqream` .. _nodejs: @@ -41,7 +45,7 @@ The following are applicable to all operating systems: * **Node.JS** - Recommended installation via ``npm``: * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) - * `Node.JS driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/nodejs/index.html>`_ + * :ref:`nodejs` .. _tableau_connector: @@ -49,7 +53,7 @@ The following are applicable to all operating systems: * **Tableau**: * `Tableau connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - SQream (.taco) - * `Tableau manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/tableau.html#>`_ + * :ref:`tableau` .. _powerbi_connector: @@ -57,7 +61,7 @@ The following are applicable to all operating systems: * **Power BI**: * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) - * `Power BI manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/power_bi.html>`_ + * :ref:`power_bi` Windows diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 83bdc3801..438df0ad7 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -1,7 +1,7 @@ .. _java_jdbc: ************************* -JDBC +Connecting to SQream Using JDBC ************************* The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst new file mode 100644 index 000000000..5b762576d --- /dev/null +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -0,0 +1,192 @@ +.. _kafka: + +************************* +Connecting to SQream Using Kafka +************************* + +Intro to Kafka producer, consumer, and loader. +Data formats +Confluent GUI + + +The Kafka page includes the following sections: + +.. contents:: + :local: + :depth: 1 + +Getting Started +================================== +System requirements +------------------- +No system requirements + + +Download Kafka connector files +------------------------------ + + +Installation and configuration +============= + +Prerequisites +---------------- +Both Kafka consumer and SQream loader require JAVA 11. + + + +Kafka producer +============== + +Installing Kafka producer +--------------------------- +The Kafka producer is installed on the 192.168.0.125 server. + +Operating Kafka producer +-------------------------- + +For the producer to properly function, two processes must continuously be running: Kafka producer and Zookeeper. Note that Kafka producer will not run unless Zookeeper is already running. + +Running Zookeeper: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + bin/zookeeper-server-start.sh -daemon config/zookeeper.properties + +Running Kafka producer: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + bin/kafka-server-start.sh -daemon config/server.properties + +Creating a new topic: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + bin/kafka-topics.sh --create --bootstrap-server localhost:2181 --replication-factor 1 --partitions 1 --topic <topic name> + +Reading data from a topic: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + ./kafka-console-consumer.sh --topic <topic name> --from-beginning --bootstrap-server localhost:9092 + +Loading data from a file: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + ./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic <topic name> < <full path to file> + +To close Kafka producer, you must first stop the producer and only then stop Zookeeper. + +Closing Kafka producer: + +.. code-block:: postgres + + cd /home/sqream/kafka_2.12-3.2.1/ + bin/kafka-server-stop.sh + +Verifying that the producer is running +-------------------------------------- + + +Known Driver Limitations +---------------------------- + * Unicode characters are not supported when using ``INSERT INTO AS SELECT``. + + * To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. + +Connecting to SQream For the First Time +============================================== +An initial connection to SQream must be established by creating a **SqreamConnection** object using a connection string. + +.. contents:: + :local: + :depth: 1 + + +Connection String +-------------------- +To connect to SQream, instantiate a **SqreamConnection** object using this connection string. + +The following is the syntax for SQream: + +.. code-block:: text + + "Data Source=<hostname or ip>,<port>;User=<username>;Password=<password>;Initial Catalog=<database name>;Integrated Security=true"; + +Connection Parameters +^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - State + - Default + - Description + * - ``<data source>`` + - Mandatory + - None + - Hostname/IP/FQDN and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` + * - ``<initial catalog>`` + - Mandatory + - None + - Database name to connect to. For example, ``master`` + * - ``<username>`` + - Mandatory + - None + - Username of a role to use for connection. For example, ``username=rhendricks`` + * - ``<password>`` + - Mandatory + - None + - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` + * - ``<service>`` + - Optional + - ``sqream`` + - Specifices service queue to use. For example, ``service=etl`` + * - ``<ssl>`` + - Optional + - ``false`` + - Specifies SSL for this connection. For example, ``ssl=true`` + * - ``<cluster>`` + - Optional + - ``true`` + - Connect via load balancer (use only if exists, and check port). + +Connection String Examples +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The following is an example of a SQream cluster with load balancer and no service queues (with SSL): + +.. code-block:: text + + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master;Integrated Security=true;ssl=true;cluster=true; + + +The following is a minimal example for a local standalone SQream database: + +.. code-block:: text + + + Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master; + +The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` + +.. code-block:: text + + Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=raviga;Integrated Security=true;service=etl;cluster=true; + +Sample C# Program +-------------------- +You can download the :download:`.NET Application Sample File <sample.cs>` below by right-clicking and saving it to your computer. + +.. literalinclude:: sample.cs + :language: C# + :caption: .NET Application Sample + :linenos: diff --git a/connecting_to_sqream/client_drivers/nodejs/index.rst b/connecting_to_sqream/client_drivers/nodejs/index.rst index 8ddd0d0bc..94b84a072 100644 --- a/connecting_to_sqream/client_drivers/nodejs/index.rst +++ b/connecting_to_sqream/client_drivers/nodejs/index.rst @@ -1,7 +1,7 @@ .. _nodejs: ************************* -Node.JS +Connecting to SQream Using Node.JS ************************* The SQream DB Node.JS driver allows Javascript applications and tools connect to SQream DB. diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 3ee093692..691e7e999 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -1,7 +1,7 @@ .. _odbc: ************************* -ODBC +Connecting to SQream Using ODBC ************************* .. toctree:: diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 7f8baac93..3ad7b1594 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -1,7 +1,7 @@ .. _pysqream: ************************* -Python (pysqream) +Connecting to SQream Using Python (pysqream) ************************* The **Python** connector page describes the following: diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index 1cdf7c81b..b43adf578 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -1,7 +1,7 @@ .. _power_bi: ************************* -Connect to SQream Using Power BI Desktop +Connecting to SQream Using Power BI Desktop ************************* Overview From f9e65f1e4e0e6b4dea6a1c94cdc1afbb1747f183 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 14:39:05 +0200 Subject: [PATCH 0367/1892] Update index.rst --- .../client_drivers/kafka/index.rst | 287 ++++++++++++------ 1 file changed, 194 insertions(+), 93 deletions(-) diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 5b762576d..20d339746 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -16,17 +16,22 @@ The Kafka page includes the following sections: :depth: 1 Getting Started -================================== -System requirements +=============== + +.. contents:: + :local: + :depth: 1 + +System Requirements ------------------- No system requirements -Download Kafka connector files +Download Kafka Connector Files ------------------------------ -Installation and configuration +Installation and Configuration ============= Prerequisites @@ -35,14 +40,18 @@ Both Kafka consumer and SQream loader require JAVA 11. -Kafka producer +Kafka Producer ============== -Installing Kafka producer +.. contents:: + :local: + :depth: 1 + +Installing Kafka Producer --------------------------- The Kafka producer is installed on the 192.168.0.125 server. -Operating Kafka producer +Operating Kafka Producer -------------------------- For the producer to properly function, two processes must continuously be running: Kafka producer and Zookeeper. Note that Kafka producer will not run unless Zookeeper is already running. @@ -91,102 +100,194 @@ Closing Kafka producer: cd /home/sqream/kafka_2.12-3.2.1/ bin/kafka-server-stop.sh -Verifying that the producer is running +Verifying that the Producer is Running -------------------------------------- +To verify that both Kafka and Zookeeper are running, log in to your machine using SQream credentials: + + * User: sqream + * Password: sqream11 + + And run the following string: + + .. code-block:: postgres + + [sqream@metadata-0-125 ~]$ ps -ef |grep java + +Example of an output indicating that both processes are running: + .. code-block:: postgres + + sqream 63082 1 0 Sep11 ? 00:03:50 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties + sqream 63614 1 0 Sep11 ? 00:19:22 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar kafka.Kafka config/server.properties -Known Driver Limitations ----------------------------- - * Unicode characters are not supported when using ``INSERT INTO AS SELECT``. - - * To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. - -Connecting to SQream For the First Time -============================================== -An initial connection to SQream must be established by creating a **SqreamConnection** object using a connection string. +Kafka Consumer +=============== .. contents:: :local: :depth: 1 - -Connection String --------------------- -To connect to SQream, instantiate a **SqreamConnection** object using this connection string. +The Kafka consumer converts data formatted as CSV and JSON into .tmp files and saves it in the predefined directory. +You must define the number of files to be converted before they are saved as a sqream.batchRecordCount file. Once reaching the defined number of files, the consumer saves the converted files and begins the process all over again. + +Installing Kafka Consumer +-------------------------- -The following is the syntax for SQream: +The Kafka consumer version is located under /home/sqream/kafkaconnect1, machine IP 192.168.0.102 +Credentials: +user = sqream +pass = sqprj2021$ -.. code-block:: text +Configuring Kafka Consumer +--------------------------- - "Data Source=<hostname or ip>,<port>;User=<username>;Password=<password>;Initial Catalog=<database name>;Integrated Security=true"; +Connection string: -Connection Parameters -^^^^^^^^^^^^^^^^^^^^^^^^ + .. code-block:: postgres + + vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties + +Configuration file structure: -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Item - - State - - Default - - Description - * - ``<data source>`` - - Mandatory - - None - - Hostname/IP/FQDN and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` - * - ``<initial catalog>`` - - Mandatory - - None - - Database name to connect to. For example, ``master`` - * - ``<username>`` - - Mandatory - - None - - Username of a role to use for connection. For example, ``username=rhendricks`` - * - ``<password>`` - - Mandatory - - None - - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` - * - ``<service>`` - - Optional - - ``sqream`` - - Specifices service queue to use. For example, ``service=etl`` - * - ``<ssl>`` - - Optional - - ``false`` - - Specifies SSL for this connection. For example, ``ssl=true`` - * - ``<cluster>`` - - Optional - - ``true`` - - Connect via load balancer (use only if exists, and check port). - -Connection String Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following is an example of a SQream cluster with load balancer and no service queues (with SSL): - -.. code-block:: text - - Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master;Integrated Security=true;ssl=true;cluster=true; - - -The following is a minimal example for a local standalone SQream database: - -.. code-block:: text - - - Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master; - -The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` - -.. code-block:: text - - Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=raviga;Integrated Security=true;service=etl;cluster=true; - -Sample C# Program --------------------- -You can download the :download:`.NET Application Sample File <sample.cs>` below by right-clicking and saving it to your computer. - -.. literalinclude:: sample.cs - :language: C# - :caption: .NET Application Sample - :linenos: + .. code-block:: postgres + + name=SQReamFileSink + topics=topsqreamtest1 + tasks.max=4 + connector.class=tr.com.entegral.FileSinkConnector + errors.tolerance=all + errors.log.enable=true + errors.log.include.messages=true + value.converter=org.apache.kafka.connect.json.JsonConverter + value.converter.schemas.enable=false + transforms=flatten + transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value + transforms.flatten.delimiter=. + sqream.outputdir=/home/sqream/kafkaconnect/outputs + sqream.batchRecordCount =10 + sqream.fileExtension=csv + sqream.removeNewline =false + sqream.outputType=csv + sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv + + +What needs to be configured: + +topics + +sqream.batchrecordcount – best to configure according to an estimated number of messages. + +outputdir – address requirement to copy and save for later. + +csvorder – Create table columns. + +Running commands: + + .. code-block:: postgres + + export JAVA_HOME=/home/sqream/copy-from-util/jdk-11;export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar;cd /home/sqream/kafkaconnect1/kafka/bin/ && ./connect-standalone.sh /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/connect-standalone.properties /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties & + +In SQream, create a table according to the columns defined using csvorder. + + .. code-block:: postgres + + Note – Copy the sqream.outputdir path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path. + +SQream Loader +============== + + + +Installing SQream loader +Sqream loader credentials: +ip machine: 192.168.0.102 +user = sqream +pass = sqprj2021$ + +Configuring SQream Loader +---------------------------- + +Building SQream loader: + + .. code-block:: postgres + + git clone -b develop http://gitlab.sq.l/java/copy-from-util.git + mvn clean package + + +Running SQream loader: + + .. code-block:: postgres + + git clone -b develop http://gitlab.sq.l/java/copy-from-util.git + mvn clean package + + + + +Configuration file structure: + + + .. code-block:: postgres + + + #config.yaml + + com: + sqream: + kafka: + common: + root: "/home/sqream/copy_from_root" + readyFileSuffix: ".csv" + connection: + ip: "127.0.0.1" + port: 3108 + database: "master" + cluster: true + user: sqream + pass: sqream + delimiter: "," + tables: + - schema: "public" + name: "t1" + parallel: 5 + - schema: "public" + name: "t2" + parallel: 3 + - schema: "public" + name: "t3" + parallel: 1 + + +What needs to be configured: +root – paste copied path to root +schema +name +Running commands: + + .. code-block:: postgres + + /home/sqream/copy-from-util/jdk-11/bin/java -jar /home/sqream/copy-from-util/copy-from-util/target/copy-from-util-0.0.1-SNAPSHOT.jar --spring.config.additional-location=/home/sqream/copy-from-util/config.yaml & + +Logging and Monitoring +======================== + +The following log files are created: + * JAVA application fails (consumer or loader?) + * Files cannot be saved to folder due to +Either + * Folder permission issue +Or + * SQream loader folder is not the same as Kenan folder +Purging +======= +Ingested files are automatically zipped and archived for 60 days. + +Limitations +=========== + +Latency +Retention + +Example +========= From d1546388788281fce06c1fa0cb85073586c55556 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 15:29:10 +0200 Subject: [PATCH 0368/1892] update --- operational_guides/access_control_managing_roles.rst | 2 +- operational_guides/access_control_permissions.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index 373b9a212..15729fa53 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -80,7 +80,7 @@ Altering Public Role Permissions There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can create, :ref:`insert`, :ref:`delete`, and :ref:`select` from objects in the ``PUBLIC`` schema. +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can ``CREATE``, :ref:`insert`, :ref:`delete`, :ref:`select` and :ref:`UPDATE` from objects in the ``PUBLIC`` schema. Altering Role Membership (Groups) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 25ff6ba14..2d8b9bf0e 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -39,7 +39,7 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``INSERT`` | :ref:`insert` into the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``UPDATE`` | UPDATE the value of certain columns in existing rows without creating a table | +| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -213,7 +213,7 @@ schema statement is run. | INSERT | DELETE | DDL - | UPDATE + | UPDATE | EXECUTE | ALL } \ No newline at end of file From 78d5f40d5c01e124ee25cb62e8f0825a6c426cf4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 16:32:11 +0200 Subject: [PATCH 0369/1892] copy to / --- connecting_to_sqream/client_drivers/python/index.rst | 2 +- reference/sql/sql_statements/dml_commands/copy_to.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 3ad7b1594..e3e53c8b3 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -165,7 +165,7 @@ The following is a standard connection example: res = engine.execute('select * from test') Pulling a Table into Pandas ---------------------------------- +--------------------------- The following example shows how to pull a table in Pandas. This examples uses the URL method to create the connection string: .. code-block:: python diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 783f9a4f9..fcdb96a9f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -90,7 +90,7 @@ The following table shows the ``COPY_TO`` elements: * - ``HEADER`` - The CSV file will contain a header line with the names of each column in the file. This option is allowed only when using CSV format. * - ``DELIMITER`` - - Specifies the character that separates fields (columns) within each row of the file. The default is a comma character (``,``). + - Specifies the character or string that separates fields (columns) within each row of the file. The default is a comma character (``,``). * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets * - ``MAX_FILE_SIZE`` @@ -269,8 +269,6 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 34 | " | Double Quote | 42 | 22 | 100010 | &#34; | &quot; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 39 | ' | Single Quote | 47 | 27 | 100111 | &#39; | &apos; | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 45 | - | Minus Sign | 55 | 2D | 101101 | &#45; | &minus; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 46 | . | Period | 56 | 2E | 101110 | &#46; | &period; | @@ -349,6 +347,8 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 90 | Z | Upper Case Letter Z | 132 | 5A | 1011010 | &#90; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 92 | \\ | Backslash | 134 | 5C | 01011100 | | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 97 | a | Lower Case Letter a | 141 | 61 | 1100001 | &#97; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 98 | b | Lower Case Letter b | 142 | 62 | 1100010 | &#98; | | From eb2c1add971f80e6b7bb9ed1e39fcd20f7c85d25 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 17:07:16 +0200 Subject: [PATCH 0370/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index fcdb96a9f..01c0006a5 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -347,7 +347,7 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 90 | Z | Upper Case Letter Z | 132 | 5A | 1011010 | &#90; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 92 | \\ | Backslash | 134 | 5C | 01011100 | | | +| 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 97 | a | Lower Case Letter a | 141 | 61 | 1100001 | &#97; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ @@ -379,7 +379,7 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 111 | o | Lower Case Letter o | 157 | 6F | 1101111 | &#111; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 112 | p | Lower Case Letter p | 160 | 70 | 1110000 | p | | +| 112 | p | Lower Case Letter p | 160 | 70 | 1110000 | &#112; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 113 | q | Lower Case Letter q | 161 | 71 | 1110001 | &#113; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ From 9d69eacb32acafe984e48b15b5548cbd84fba293 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 17:17:35 +0200 Subject: [PATCH 0371/1892] SQLAlchemy --- .../client_drivers/python/index.rst | 56 ++++++++++++++----- .../sql_statements/dml_commands/copy_to.rst | 2 +- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index e3e53c8b3..5d09c785c 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -143,26 +143,54 @@ This section includes the following examples: Standard Connection Example --------------------------------- -The following is a standard connection example: + .. code-block:: python - import sqlalchemy as sa - from sqlalchemy.engine.url import URL + import sqlalchemy as sa + from sqlalchemy.engine.url import URL - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) + engine_url = URL('sqream' + , username='rhendricks' + , password='secret_passwor" + , host='localhost' + , port=5000 + , database='raviga' + , query={'use_ssl': False}) - engine = sa.create_engine(engine_url) + engine = sa.create_engine(engine_url) + + res = engine.execute('create or replace table test (ints int, ints2 int)') + res = engine.execute('insert into test (ints,ints2) values (5,1), (6,2)') + res = engine.execute('select * from test') + for item in res: + print(item) + +Multi Cluster Connection Example +------------------------ + +The following example is for using a ServerPicker: + +.. code-block:: python + + import sqlalchemy as sa + from sqlalchemy.engine.url import URL + + engine_url = URL('sqream' + , username='rhendricks' + , password='secret_passwor" + , host='localhost' + , port=3108 + , database='raviga' + , query={'use_ssl': False}) + + engine = sa.create_engine(engine_url , connect_args={"clustered": True}) - res = engine.execute('create table test (ints int)') - res = engine.execute('insert into test values (5), (6)') - res = engine.execute('select * from test') + res = engine.execute('create or replace table test (ints int, ints2 int)') + res = engine.execute('insert into test (ints,ints2) values (5,1), (6,2)') + res = engine.execute('select * from test') + for item in res: + print(item) Pulling a Table into Pandas --------------------------- diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 01c0006a5..3708d85ae 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -161,7 +161,7 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | [ | Left Square Bracket | 91 | 133 | 5B | 1011011 | &#91; | &lsqb; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -| \ | Backslash | 92 | 134 | 5C | 1011100 | &#92; | &bsol; | +| \ | Backslash | 92 | 134 | 5C | 1011100 | \&\#92\; | &bsol; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | ] | Right Square Bracket | 93 | 135 | 5D | 1011101 | &#93; | &rsqb; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ From 662a82cc5cc61a215e92cd33df3368ecb9326a37 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Jan 2023 17:24:08 +0200 Subject: [PATCH 0372/1892] python --- connecting_to_sqream/client_drivers/index.rst | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index ce6b1ef8d..58791e766 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,26 +18,22 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.3 (.jar) - * :ref:`java_jdbc` + * `JDBC driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html#>`_ .. _.net: * **.NET**: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ - * :ref:`net` + * `.NET driver <https://docs.sqream.com/en/v2022.1.6/connecting_to_sqream/client_drivers/dotnet/index.html>`_ -* **Kafka**: - - * `Kafka file <>`_ - * :ref:`kafka` .. _python: * **Python** - Recommended installation via ``pip``: * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.1.3>`_ - pysqream v3.1.3 (.tar.gz) - * :ref:`pysqream` + * `Python driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/python/index.html>`_ .. _nodejs: @@ -45,7 +41,7 @@ The following are applicable to all operating systems: * **Node.JS** - Recommended installation via ``npm``: * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) - * :ref:`nodejs` + * `Node.JS driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/nodejs/index.html>`_ .. _tableau_connector: @@ -53,7 +49,7 @@ The following are applicable to all operating systems: * **Tableau**: * `Tableau connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - SQream (.taco) - * :ref:`tableau` + * `Tableau manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/tableau.html#>`_ .. _powerbi_connector: @@ -61,7 +57,7 @@ The following are applicable to all operating systems: * **Power BI**: * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) - * :ref:`power_bi` + * `Power BI manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/power_bi.html>`_ Windows From afb27d69a3e0467c2ec347ca258f7b72c16f7d1b Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 2 Jan 2023 13:20:19 +0200 Subject: [PATCH 0373/1892] Update trino.rst --- .../client_platforms/trino.rst | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst index b0e21f954..7e63bc68b 100644 --- a/connecting_to_sqream/client_platforms/trino.rst +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -4,9 +4,8 @@ Connecting to SQream Using Trino ************************* -Overview -===================== -The JDBC based SQream Trino plugin supports large volumes of data storage and fast querying. + +If you are using Trino for distributed SQL query processing and wish to use it to connect to a SQream, follow these instructions. .. contents:: @@ -31,6 +30,11 @@ Installation :local: :depth: 1 +JDBC +~~~~ + +In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. + SQream Trino Plugin ~~~~~~~~~~~~~~~~~~~ @@ -52,15 +56,12 @@ The SQream Trino plugin must be installed on each cluster node dedicated to Trin ├── trino-sqream-SNAPSHOT.jar └── all dependencies -JDBC -~~~~ -In case JDBC is not yet deployed, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. Connecting to SQream -------------------- -Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish for Trino to have access to more than one SQream database or server, you must create additional catalogs. +Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish Trino to have access to more than one SQream database or server, you must create additional catalogs. Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. @@ -137,7 +138,7 @@ Limitations SQream does not support the following SQL statements: -``GRANT`` -``REVOKE`` -``SHOW GRANTSHOW ROLES`` -``SHOW ROLE GRANTS`` \ No newline at end of file +* ``GRANT`` +* ``REVOKE`` +* ``SHOW GRANTSHOW ROLES`` +* ``SHOW ROLE GRANTS`` \ No newline at end of file From 1ff73b9f48d8e8deee9d69c4e877720c9b4320bf Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 2 Jan 2023 13:24:58 +0200 Subject: [PATCH 0374/1892] Update trino.rst --- connecting_to_sqream/client_platforms/trino.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst index 7e63bc68b..be1e7e9b7 100644 --- a/connecting_to_sqream/client_platforms/trino.rst +++ b/connecting_to_sqream/client_platforms/trino.rst @@ -136,7 +136,7 @@ Use the appropriate Trino data type for executing queries. Upon execution, incom Limitations ----------- -SQream does not support the following SQL statements: +The SQream Trino plugin does not support the following SQL statements: * ``GRANT`` * ``REVOKE`` From 50583d64980f8c396c80cec156c8d297de839527 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:42:09 +0200 Subject: [PATCH 0375/1892] Update 4.0.0_index.rst --- releases/4.0.0_index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index f846edb4f..f2b96c4d5 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -4,7 +4,7 @@ Release Notes 4.0.0 ************************** -**SQream is introducing a more commonly used versioning system, beginning with 4.0.0 as a minor version.** +**SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. No considerable preparations are required upon the 4.0.0 version release, as it is a minor version upgrade.** The 4.0.0 release notes were released on xx/xx/20xx and describe the following: From bf57e3389c9adcf0255c6cc270c3027096c46c8a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Jan 2023 11:05:10 +0200 Subject: [PATCH 0376/1892] sqlalchemy --- .../client_drivers/python/index.rst | 23 +++++++++++-------- releases/4.0.0_index.rst | 2 +- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 5d09c785c..1b5a7ccd4 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -173,24 +173,26 @@ The following example is for using a ServerPicker: .. code-block:: python - import sqlalchemy as sa + import sqlalchemy as sa + import pandas as pd from sqlalchemy.engine.url import URL + engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" + , username='dor' + , password='DorBerg123$' , host='localhost' , port=3108 - , database='raviga' - , query={'use_ssl': False}) + , database='pushlive') - engine = sa.create_engine(engine_url , connect_args={"clustered": True}) + engine = sa.create_engine(engine_url,connect_args={"clustered": True}) - res = engine.execute('create or replace table test (ints int, ints2 int)') - res = engine.execute('insert into test (ints,ints2) values (5,1), (6,2)') - res = engine.execute('select * from test') + res = engine.execute("create or replace table test100 (dor int);") + res = engine.execute('insert into test100 values (5), (6);') + res = engine.execute('select * from test100') for item in res: - print(item) + print(item) + Pulling a Table into Pandas --------------------------- @@ -337,6 +339,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea , username='rhendricks', password='Tr0ub4dor&3' , clustered=True) , cur = con.cursor() + 2. Create a table for loading: .. code-block:: python diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index f2b96c4d5..8458ba8b7 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -4,7 +4,7 @@ Release Notes 4.0.0 ************************** -**SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. No considerable preparations are required upon the 4.0.0 version release, as it is a minor version upgrade.** +**SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released 4.0.0 version is a minor version upgrade and does not require considerable preparation.** The 4.0.0 release notes were released on xx/xx/20xx and describe the following: From 0972b4e6e9aad7734e6f4f23d2dddeeb82bfba58 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Jan 2023 14:49:35 +0200 Subject: [PATCH 0377/1892] Kafka --- connecting_to_sqream/client_drivers/index.rst | 24 ++- .../client_drivers/kafka/index.rst | 190 ++++++++++-------- 2 files changed, 121 insertions(+), 93 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 58791e766..d35b1662f 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,22 +18,26 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.3 (.jar) - * `JDBC driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html#>`_ + * :ref:`java_jdbc` .. _.net: * **.NET**: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ - * `.NET driver <https://docs.sqream.com/en/v2022.1.6/connecting_to_sqream/client_drivers/dotnet/index.html>`_ + * :ref:`net` +* **Kafka**: + + * `Kafka download file <>`_ + * :ref:`kafka` .. _python: * **Python** - Recommended installation via ``pip``: * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.1.3>`_ - pysqream v3.1.3 (.tar.gz) - * `Python driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/python/index.html>`_ + * :ref:`pysqream` .. _nodejs: @@ -41,7 +45,7 @@ The following are applicable to all operating systems: * **Node.JS** - Recommended installation via ``npm``: * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) - * `Node.JS driver <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/nodejs/index.html>`_ + * :ref:`nodejs` .. _tableau_connector: @@ -49,7 +53,7 @@ The following are applicable to all operating systems: * **Tableau**: * `Tableau connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - SQream (.taco) - * `Tableau manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/tableau.html#>`_ + * :ref:`tableau` .. _powerbi_connector: @@ -57,7 +61,7 @@ The following are applicable to all operating systems: * **Power BI**: * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) - * `Power BI manual installation <https://docs.sqream.com/en/v2021.1/third_party_tools/client_platforms/power_bi.html>`_ + * :ref:`power_bi` Windows @@ -78,12 +82,12 @@ Linux The following are applicable to Linux: * `SQream SQL (x86_64) <https://sq-ftp-public.s3.amazonaws.com/sqream-sql-v2020.1.1_stable.x86_64.tar.gz>`_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* `Sqream SQL CLI Reference <https://docs.sqream.com/en/v2021.1/reference/cli/sqream_sql.html#sqream-sql-cli-reference>`_ - Interactive command-line SQL client for Intel-based machines +* :ref:`sqream_sql_cli_reference` - Interactive command-line SQL client for Intel-based machines :: * `SQream SQL*(IBM POWER9) <https://sq-ftp-public.s3.amazonaws.com/sqream-sql-v2020.1.1_stable.ppc64le.tar.gz>`_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* `Sqream SQL CLI Reference <https://docs.sqream.com/en/v2021.1/reference/cli/sqream_sql.html#sqream-sql-cli-reference>`_ - Interactive command-line SQL client for IBM POWER9-based machines +* :ref:`sqream_sql_cli_reference` - Interactive command-line SQL client for IBM POWER9-based machines :: @@ -98,6 +102,8 @@ The following are applicable to Linux: jdbc/index python/index + dotnet/index + kafka/index nodejs/index odbc/index dotnet/index @@ -106,7 +112,7 @@ The following are applicable to Linux: .. rubric:: Need help? -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://support.sqream.com>`_ for additional support. +If you couldn't find what you're looking for, we're always happy to help. Visit :ref:`information_for_support` for additional support. .. rubric:: Looking for older drivers? diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 20d339746..895ccf475 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -4,57 +4,59 @@ Connecting to SQream Using Kafka ************************* -Intro to Kafka producer, consumer, and loader. -Data formats -Confluent GUI - - -The Kafka page includes the following sections: +This page describes how to connect SQream with the Kafka Apache stream-processing software platform. .. contents:: :local: :depth: 1 -Getting Started -=============== + +Installation and Configuration +============= .. contents:: :local: :depth: 1 - -System Requirements -------------------- -No system requirements - - -Download Kafka Connector Files ------------------------------- - - -Installation and Configuration -============= Prerequisites ---------------- -Both Kafka consumer and SQream loader require JAVA 11. - + * JAVA 11 + * Network bandwidth should be not less than X Giga/Sec + +Supported Data Formats +---------------------- +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Data Format + - Specification + * - JSON + - + * - CSV + - + * - Avro + - Kafka Producer -============== +-------------- + +The Kafka Producer can be used for creating new topics, reading data from existing topics, and loading data from files. + +In order for the Kafka producer to operate correctly, both the Kafka producer and Zookeeper processes must be running simultaneously. If Zookeeper is not running, the Kafka producer will not start. .. contents:: :local: :depth: 1 -Installing Kafka Producer ---------------------------- -The Kafka producer is installed on the 192.168.0.125 server. +Kafka Producer Installation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Operating Kafka Producer --------------------------- +The Kafka producer is installed on the 192.168.0.125 server. -For the producer to properly function, two processes must continuously be running: Kafka producer and Zookeeper. Note that Kafka producer will not run unless Zookeeper is already running. +Kafka Producer Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Running Zookeeper: @@ -70,6 +72,26 @@ Running Kafka producer: cd /home/sqream/kafka_2.12-3.2.1/ bin/kafka-server-start.sh -daemon config/server.properties +Verifying that both Zookeeper and Kafka producer are running: + +1. Log in to your machine using the following SQream credentials: + + * User: sqream + * Password: sqream11 + +2. Run the following string: + + .. code-block:: postgres + + [sqream@metadata-0-125 ~]$ ps -ef |grep java + +The following is an example of an output indicating that both processes are running: + + .. code-block:: postgres + + sqream 63082 1 0 Sep11 ? 00:03:50 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties + sqream 63614 1 0 Sep11 ? 00:19:22 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar kafka.Kafka config/server.properties + Creating a new topic: .. code-block:: postgres @@ -91,55 +113,53 @@ Loading data from a file: cd /home/sqream/kafka_2.12-3.2.1/ ./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic <topic name> < <full path to file> -To close Kafka producer, you must first stop the producer and only then stop Zookeeper. - Closing Kafka producer: +To close the Kafka producer, you must first stop the producer and then stop Zookeeper. + .. code-block:: postgres cd /home/sqream/kafka_2.12-3.2.1/ bin/kafka-server-stop.sh - -Verifying that the Producer is Running --------------------------------------- -To verify that both Kafka and Zookeeper are running, log in to your machine using SQream credentials: - - * User: sqream - * Password: sqream11 - - And run the following string: - - .. code-block:: postgres - - [sqream@metadata-0-125 ~]$ ps -ef |grep java - -Example of an output indicating that both processes are running: - - .. code-block:: postgres - - sqream 63082 1 0 Sep11 ? 00:03:50 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties - sqream 63614 1 0 Sep11 ? 00:19:22 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar kafka.Kafka config/server.properties Kafka Consumer -=============== +--------------- .. contents:: :local: :depth: 1 -The Kafka consumer converts data formatted as CSV and JSON into .tmp files and saves it in the predefined directory. -You must define the number of files to be converted before they are saved as a sqream.batchRecordCount file. Once reaching the defined number of files, the consumer saves the converted files and begins the process all over again. +The Kafka consumer converts data formatted as CSV and JSON into ``.tmp`` files and saves it in a predefined directory. +You must define the number of files to be converted before they are saved as a ``sqream.batchRecordCount`` file. Once reaching the defined number of files, the consumer saves the converted files and begins the process all over again. -Installing Kafka Consumer --------------------------- +Kafka Consumer Installation +~~~~~~~~~~~~~~~~~~~~~~~~~~~ The Kafka consumer version is located under /home/sqream/kafkaconnect1, machine IP 192.168.0.102 Credentials: user = sqream pass = sqprj2021$ -Configuring Kafka Consumer ---------------------------- +Kafka Consumer Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +What needs to be configured: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - Topic + - A category or feed name to which messages are published and subscribed to + * - ``sqream.batchrecordcount`` + - Preferably configured according to an estimated number of messages + * - ``outputdir`` + - Copy the ``sqream.outputdir`` path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path + * - ``csvorder`` + - Create table columns + Connection string: @@ -169,17 +189,8 @@ Configuration file structure: sqream.removeNewline =false sqream.outputType=csv sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv - - -What needs to be configured: - -topics - -sqream.batchrecordcount – best to configure according to an estimated number of messages. - -outputdir – address requirement to copy and save for later. - -csvorder – Create table columns. + +SQream tables must be created according to the columns configured in ``csvorder``. Running commands: @@ -187,25 +198,26 @@ Running commands: export JAVA_HOME=/home/sqream/copy-from-util/jdk-11;export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar;cd /home/sqream/kafkaconnect1/kafka/bin/ && ./connect-standalone.sh /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/connect-standalone.properties /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties & -In SQream, create a table according to the columns defined using csvorder. - .. code-block:: postgres - - Note – Copy the sqream.outputdir path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path. + SQream Loader -============== +------------- +.. contents:: + :local: + :depth: 1 +SQream Loader Installation +~~~~~~~~~~~~~~~~~~~~~~~~~~ -Installing SQream loader Sqream loader credentials: ip machine: 192.168.0.102 user = sqream pass = sqprj2021$ -Configuring SQream Loader ----------------------------- +SQream Loader Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Building SQream loader: @@ -222,15 +234,26 @@ Running SQream loader: git clone -b develop http://gitlab.sq.l/java/copy-from-util.git mvn clean package +What needs to be configured: +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``root`` + – paste copied path to root + * - ``schema`` + - + * - ``name`` + - Configuration file structure: - .. code-block:: postgres - #config.yaml com: @@ -259,10 +282,8 @@ Configuration file structure: parallel: 1 -What needs to be configured: -root – paste copied path to root -schema -name + + Running commands: .. code-block:: postgres @@ -279,6 +300,7 @@ Either * Folder permission issue Or * SQream loader folder is not the same as Kenan folder + Purging ======= Ingested files are automatically zipped and archived for 60 days. @@ -289,5 +311,5 @@ Limitations Latency Retention -Example +Examples ========= From 88ad92d8f589fc6cf9c73c8ca400988c7a44e8b8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Jan 2023 15:34:29 +0200 Subject: [PATCH 0378/1892] Update index.rst --- connecting_to_sqream/client_drivers/kafka/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 895ccf475..9c64a03e1 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -249,7 +249,6 @@ What needs to be configured: * - ``name`` - - Configuration file structure: .. code-block:: postgres From 5140c109460bd3293daa655764e57c912fd3f7ee Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Jan 2023 16:48:22 +0200 Subject: [PATCH 0379/1892] Update compression.rst --- feature_guides/compression.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index ab26e9986..74874b980 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -35,7 +35,9 @@ When loading data, SQream DB automatically decides on the compression schemes fo Compression Methods ------------------------ -The following table shows the available compression methods: +In some cases, if SQream finds that the given compression method cannot effectively compress the data, it will return to the default compression type. + +The following table shows the supported compression methods: .. list-table:: :widths: auto From 74ebf6f18977db29a7526a91c0b0a933fbde95e4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Jan 2023 13:16:34 +0200 Subject: [PATCH 0380/1892] Kafka --- connecting_to_sqream/client_drivers/kafka/index.rst | 11 ++++------- connecting_to_sqream/client_drivers/python/index.rst | 3 +-- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 9c64a03e1..22c06709c 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -4,7 +4,7 @@ Connecting to SQream Using Kafka ************************* -This page describes how to connect SQream with the Kafka Apache stream-processing software platform. +This page describes how to connect SQream with Kafka Apache. .. contents:: :local: @@ -74,10 +74,7 @@ Running Kafka producer: Verifying that both Zookeeper and Kafka producer are running: -1. Log in to your machine using the following SQream credentials: - - * User: sqream - * Password: sqream11 +1. Log in to your machine. 2. Run the following string: @@ -89,8 +86,8 @@ The following is an example of an output indicating that both processes are runn .. code-block:: postgres - sqream 63082 1 0 Sep11 ? 00:03:50 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/zookeeper-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties - sqream 63614 1 0 Sep11 ? 00:19:22 /usr/lib/jvm/jre-1.8.0-openjdk/bin/java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xloggc:/home/sqream/kafka_2.12-3.2.1/bin/../logs/kafkaServer-gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/home/sqream/kafka_2.12-3.2.1/bin/../logs -Dlog4j.configuration=file:bin/../config/log4j.properties -cp /home/sqream/kafka_2.12-3.2.1/bin/../libs/activation-1.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/aopalliance-repackaged-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/argparse4j-0.7.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/audience-annotations-0.5.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-cli-1.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/commons-lang3-3.8.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-basic-auth-extension-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-json-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-mirror-client-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-runtime-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/connect-transforms-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-api-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-locator-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/hk2-utils-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-core-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-databind-2.12.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-dataformat-csv-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-datatype-jdk8-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-base-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-jaxrs-json-provider-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-jaxb-annotations-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jackson-module-scala_2.12-2.12.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.activation-api-1.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.annotation-api-1.3.5.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.inject-2.6.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.validation-api-2.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.ws.rs-api-2.1.6.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jakarta.xml.bind-api-2.3.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javassist-3.27.0-GA.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.servlet-api-3.1.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/javax.ws.rs-api-2.1.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jaxb-api-2.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-client-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-common-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-container-servlet-core-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-hk2-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jersey-server-2.34.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-client-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-continuation-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-http-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-io-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-security-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-server-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlet-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-servlets-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jetty-util-ajax-9.4.44.v20210927.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jline-3.21.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jopt-simple-5.0.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/jose4j-0.7.9.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-clients-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-log4j-appender-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-metadata-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-raft-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-server-common-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-shell-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-storage-api-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-examples-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-scala_2.12-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-streams-test-utils-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/kafka-tools-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/lz4-java-1.8.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/maven-artifact-3.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-2.2.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/metrics-core-4.1.12.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-buffer-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-codec-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-handler-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-resolver-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-tcnative-classes-2.0.46.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-classes-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-epoll-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/netty-transport-native-unix-common-4.1.73.Final.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/osgi-resource-locator-1.0.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/paranamer-2.8.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/plexus-utils-3.3.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reflections-0.9.12.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/reload4j-1.2.19.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/rocksdbjni-6.29.4.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-collection-compat_2.12-2.6.0.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-java8-compat_2.12-1.0.2.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-library-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-logging_2.12-3.9.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/scala-reflect-2.12.15.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-api-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/slf4j-reload4j-1.7.36.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/snappy-java-1.1.8.4.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/trogdor-3.2.1.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zookeeper-jute-3.6.3.jar:/home/sqream/kafka_2.12-3.2.1/bin/../libs/zstd-jni-1.5.2-1.jar kafka.Kafka config/server.properties + <JAVA_HOME>/bin/java... org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties + <JAVA_HOME>/bin/java... kafka.Kafka config/server.properties Creating a new topic: diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 1b5a7ccd4..f29679bc0 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -173,8 +173,7 @@ The following example is for using a ServerPicker: .. code-block:: python - import sqlalchemy as sa - import pandas as pd + import sqlalchemy as sa from sqlalchemy.engine.url import URL From 2327b820780b07cb049e4c4a8b4fb9e7e42444b3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Jan 2023 15:15:27 +0200 Subject: [PATCH 0381/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 47d684653..3f9e9d578 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -74,7 +74,7 @@ Default Value Constraints The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. -The default value may be a literal, GETDATE(), or NULL. +The default value may be a literal or NULL. .. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. From 86a66f59d934d32e72232e6902bc505cda9a96e9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Jan 2023 17:02:17 +0200 Subject: [PATCH 0382/1892] Update round.rst --- .../scalar_functions/numeric/round.rst | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index d362c9abd..420bd3c0f 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -13,8 +13,10 @@ Syntax .. code-block:: postgres - ROUND( expr [, scale ] ) - + ROUND( numeric ) -> numeric + ROUND( numeric [, int ] ) -> numeric + ROUND( double ) -> double + Arguments ============ @@ -24,20 +26,23 @@ Arguments * - Parameter - Description - * - ``expr`` - - Numeric expression to round - * - ``scale`` - - Number of digits after the decimal point to round to. Defaults to 0 if not specified. + * - ``numeric`` + - Stores numeric values such as integers, decimal numbers, and currency values + * - ``int`` + - Stores integer values Returns ============ -``ROUND`` always returns a ``double`` floating point number. +The ``ROUND()`` function returns a ``numeric`` value when used with numeric input types, such as ``integer`` or ``decimal``. When the input is ``double``, the return type is also ``double``. + + +.. note:: ``integer`` data types are automatically cast to ``numeric`` data types. Notes ======= -* If the input value is NULL, the result is NULL. +If the input value is NULL, the result is NULL. Examples =========== From 02671cf6a2de00de5fbecfe5e02920c50467c953 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 8 Jan 2023 11:38:40 +0200 Subject: [PATCH 0383/1892] Spark --- .../client_platforms/index.rst | 1 + .../client_platforms/spark.rst | 382 ++++++++++++++++++ 2 files changed, 383 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/spark.rst diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 5d6092e14..903800b35 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -22,6 +22,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :titlesonly: + spark trino informatica microstrategy diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst new file mode 100644 index 000000000..d610f5d42 --- /dev/null +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -0,0 +1,382 @@ +.. _spark: + +************************* +Connecting to SQream Using Spark +************************* + + +If you are using Spark for distributed processing and analysis and wish to use it to connect to SQream, follow these instructions. + + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------- +To use Spark with SQream, you must have the following installed: + +* SQream version 2022.1.8 or later +* Spark version 3.3.1 or later +* SQream Spark plugin xxxx +* JDBC version 4.5.6 or later + + + +Installation +------------ + +.. contents:: + :local: + :depth: 1 + +JDBC +~~~~ + +In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. + + +SQream Spark Plugin +~~~~~~~~~~~~~~~~~~~ + +The SQream Spark plugin supports bi-directional data transfer between the different clusters. The Spark cluster may be self-hosted or third-party hosted, using services such as Qubole, AWS EMR, or Databricks. + +Connection Parameters +~~~~~~~~~~~~~~~~~~~~~ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - Default + - Description + * - ``url`` + - + - The JDBC URL of the form ``jdbc:subprotocol:subname`` to connect to. The source-specific connection properties may be specified in the URL. e.g., ``jdbc:Sqream://localhost/test?user=fred&password=secret`` + * - ``dbtable`` + - + - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + * - ``query`` + - + - A query that will be used to read data into Spark. The specified query will be parenthesized and used as a subquery in the ``FROM`` clause. Spark will also assign an alias to the subquery clause. As an example, spark will issue a query of the following form to the JDBC Source. ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. Restrictions while using this option: 1. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. 2. It is not allowed to specify ``query`` and ``partitionColumn`` options at the same time. When specifying ``partitionColumn`` option is required, the subquery can be specified using ``dbtable`` option instead and partition columns can be qualified using the subquery alias provided as part of ``dbtable``. + Example: ``spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load()`` + * - ``driver`` + - + - The class name of the JDBC driver to use to connect to this URL. + * - ``numPartitions`` + - + - The maximum number of partitions that can be used for parallelism in table reading and writing. This also determines the maximum number of concurrent JDBC connections. If the number of partitions to write exceeds this limit, we decrease it to this limit by calling ``coalesce(numPartitions)`` before writing. + * - ``queryTimeout`` + - 0 + - The number of seconds the driver will wait for a Statement object to execute to the given number of seconds. Zero means there is no limit. In the write path, this option depends on how JDBC drivers implement the API ``setQueryTimeout``, e.g., the h2 JDBC driver checks the timeout of each query instead of an entire JDBC batch. + * - ``fetchsize`` + - 1 + - The JDBC fetch size, which determines how many rows to fetch per round trip. This can help performance on JDBC drivers which default to low fetch size (e.g. Oracle with 10 rows). + * - ``batchsize`` + - 1000000 + - The JDBC batch size, which determines how many rows to insert per round trip. This can help performance on JDBC drivers. This option applies only to writing. + * - ``sessionInitStatement`` + - + - After each database session is opened to the remote DB and before starting to read data, this option executes a custom SQL statement (or a PL/SQL block). Use this to implement session initialization code. Example: ``option("sessionInitStatement", """BEGIN execute immediate 'alter session set "_serial_direct_read"=true'; END;""")`` + * - ``truncate`` + - ``false`` + - This is a JDBC writer related option. When ``SaveMode.Overwrite`` is enabled, this option causes Spark to truncate an existing table instead of dropping and recreating it. This can be more efficient, and prevents the table metadata (e.g., indices) from being removed. However, it will not work in some cases, such as when the new data has a different schema. In case of failures, users should turn off ``truncate`` option to use ``DROP TABLE`` again. Also, due to the different behavior of ``TRUNCATE TABLE`` among DBMS, it's not always safe to use this. MySQLDialect, DB2Dialect, MsSqlServerDialect, DerbyDialect, and OracleDialect supports this while PostgresDialect and default JDBCDirect doesn't. For unknown and unsupported JDBCDirect, the user option ``truncate`` is ignored. + * - ``cascadeTruncate`` + - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect + - This is a JDBC writer related option. If enabled and supported by the JDBC database (PostgreSQL and Oracle at the moment), this options allows execution of a ``TRUNCATE TABLE t CASCADE`` (in the case of PostgreSQL a TRUNCATE TABLE ONLY t CASCADE is executed to prevent inadvertently truncating descendant tables). This will affect other tables, and thus should be used with care. + * - ``createTableOptions`` + - + - This is a JDBC writer related option. If specified, this option allows setting of database-specific table and partition options when creating a table (e.g., ``CREATE TABLE t (name string) ENGINE=InnoDB.``). + * - ``createTableColumnTypes`` + - + - The database column data types to use instead of the defaults, when creating the table. Data type information should be specified in the same format as CREATE TABLE columns syntax (e.g: ``"name CHAR(64), comments VARCHAR(1024)"``). The specified types should be valid spark sql data types. + * - ``customSchema`` + - + - The custom schema to use for reading data from JDBC connectors. For example, ``"id DECIMAL(38, 0), name STRING"``. You can also specify partial fields, and the others use the default type mapping. For example, ``"id DECIMAL(38, 0)"``. The column names should be identical to the corresponding column names of JDBC table. Users can specify the corresponding data types of Spark SQL instead of using the defaults. + * - ``pushDownPredicate`` + - ``true`` + - The option to enable or disable predicate push-down into the JDBC data source. The default value is true, in which case Spark will push down filters to the JDBC data source as much as possible. Otherwise, if set to false, no filter will be pushed down to the JDBC data source and thus all filters will be handled by Spark. Predicate push-down is usually turned off when the predicate filtering is performed faster by Spark than by the JDBC data source. + * - ``pushDownAggregate`` + - ``false`` + - The option to enable or disable aggregate push-down in V2 JDBC data source. The default value is false, in which case Spark will not push down aggregates to the JDBC data source. Otherwise, if sets to true, aggregates will be pushed down to the JDBC data source. Aggregate push-down is usually turned off when the aggregate is performed faster by Spark than by the JDBC data source. Please note that aggregates can be pushed down if and only if all the aggregate functions and the related filters can be pushed down. If ``numPartitions`` equals to 1 or the group by key is the same as ``partitionColumn``, Spark will push down aggregate to data source completely and not apply a final aggregate over the data source output. Otherwise, Spark will apply a final aggregate over the data source output. + * - ``pushDownLimit`` + - ``false`` + - The option to enable or disable LIMIT push-down into V2 JDBC data source. The LIMIT push-down also includes LIMIT + SORT , a.k.a. the Top N operator. The default value is false, in which case Spark does not push down LIMIT or LIMIT with SORT to the JDBC data source. Otherwise, if sets to true, LIMIT or LIMIT with SORT is pushed down to the JDBC data source. If ``numPartitions`` is greater than 1, SPARK still applies LIMIT or LIMIT with SORT on the result from data source even if LIMIT or LIMIT with SORT is pushed down. Otherwise, if LIMIT or LIMIT with SORT is pushed down and ``numPartitions`` equals to 1, SPARK will not apply LIMIT or LIMIT with SORT on the result from data source. + * - ``pushDownTableSample`` + - ``false`` + - The option to enable or disable TABLESAMPLE push-down into V2 JDBC data source. The default value is false, in which case Spark does not push down TABLESAMPLE to the JDBC data source. Otherwise, if value sets to true, TABLESAMPLE is pushed down to the JDBC data source. + * - ``connectionProvider`` + - + - The name of the JDBC connection provider to use to connect to this URL, e.g. ``db2``, ``mssql``. Must be one of the providers loaded with the JDBC data source. Used to disambiguate when more than one provider can handle the specified driver and options. The selected provider must not be disabled by ``spark.sql.sources.disabledJdbcConnProviderList``. + + +Data transfer from SQream to Spark +-------------------- + +1. Use the read() method of the SqlContext object to construct a DataFrameReader. + +2. Specify SQREAM_SOURCE_NAME using the format() method. For the definition + +3. Specify the connector options using either the option() or options() method. + +4. Specify one of the following options for the table data to be read: + + * dbtable: The name of the table to be read. All columns and records are retrieved (i.e. it is equivalent to SELECT * FROM db_table). + + * query: The exact query (SELECT statement) to run. + +Examples +--------------- + +To read an entire table: + +.. code-block:: postgres + + val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .load() + +To read query results: + +.. code-block:: postgres + + val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("query", "<EXECUTED_QUERY> <table_name>") .load() + + +Data transfer from Spark to SQream +-------------------------------- + +1. Use the write() method of the DataFrame to construct a DataFrameWriter. + +2. Specify SQREAM_SOURCE_NAME using the format() method. + +3. Specify the connector options using either the option() or options() method. + +4. Use the dbtable option to specify the table to which data is written. + +5. Use the mode() method to specify the save mode for the content. + +Examples +--------------- +To read an entire table: + +.. code-block:: postgres + + df.write .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .mode(SaveMode.Overwrite) .save() + +Supported Data Types and Mapping +-------------------------------- + +SQream data types mapped to Spark + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SQream + - Spark + * - ``BIGINT`` + - ``LONGINT`` + * - ``BOOL`` + - ``BooleanType`` + * - ``DATE`` + - ``DateType`` + * - ``DOUBLE`` + - ``DoubleType`` + * - ``REAL`` + - ``FloateType`` + * - ``DECIMAL`` + - ``DeciamlType`` + * - ``INT`` + - ``Integer`` + * - ``SMALLINT`` + - ``ShortType`` + * - ``TINYINT`` + - ``ShortType`` + * - ``DATETIME`` + - ``TimestampType`` + +Spark data types mapped to SQream + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Spark + - SQream + * - ``BooleanType`` + - ``BOOL`` + * - ``ByteType`` + - ``SMALLINT`` + * - ``DateType`` + - ``DATE`` + * - ``DecimalType`` + - ``DECIMAL`` + * - ``DoubleType`` + - ``DOUBLE`` + * - ``FloatType`` + - ``REAL`` + * - ``IntegerType`` + - ``INT`` + * - ``LongType`` + - ``BIGINT`` + * - ``ShortType`` + - ``SMALLINT`` + * - ``StringType`` + - ``TEXT`` + * - ``TimestampType`` + - ``DATETIME`` + + +Examples +--------- + +Scala + +.. code-block:: postgres + + // Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods + // Loading data from a JDBC source + val jdbcDF = spark.read + .format("jdbc") + .option("url", "jdbc:Sqream:dbserver") + .option("dbtable", "schema.tablename") + .option("user", "username") + .option("password", "password") + .load() + + val connectionProperties = new Properties() + connectionProperties.put("user", "username") + connectionProperties.put("password", "password") + val jdbcDF2 = spark.read + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) + // Specifying the custom data types of the read schema + connectionProperties.put("customSchema", "id DECIMAL(38, 0), name TEXT") + val jdbcDF3 = spark.read + .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties) + + // Saving data to a JDBC source + jdbcDF.write + .format("jdbc") + .option("url", "jdbc:Sqream:dbserver") + .option("dbtable", "schema.tablename") + .option("user", "username") + .option("password", "password") + .save() + + jdbcDF2.write + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) + + // Specifying create table column data types on write + jdbcDF.write + .option("createTableColumnTypes", "name TEXT, comments TEXT") + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) + +JAVA + +.. code-block:: postgres + + // Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods + // Loading data from a JDBC source + Dataset<Row> jdbcDF = spark.read() + .format("jdbc") + .option("url", "jdbc:Sqream:dbserver") + .option("dbtable", "schema.tablename") + .option("user", "username") + .option("password", "password") + .load(); + + Properties connectionProperties = new Properties(); + connectionProperties.put("user", "username"); + connectionProperties.put("password", "password"); + Dataset<Row> jdbcDF2 = spark.read() + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); + + // Saving data to a JDBC source + jdbcDF.write() + .format("jdbc") + .option("url", "jdbc:Sqream:dbserver") + .option("dbtable", "schema.tablename") + .option("user", "username") + .option("password", "password") + .save(); + + jdbcDF2.write() + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); + + // Specifying create table column data types on write + jdbcDF.write() + .option("createTableColumnTypes", "name TEXT, comments TEXT") + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); + +Python + +.. code-block:: postgres + + # Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods + # Loading data from a JDBC source + jdbcDF = spark.read \ + .format("jdbc") \ + .option("url", "jdbc:Sqream:dbserver") \ + .option("dbtable", "schema.tablename") \ + .option("user", "username") \ + .option("password", "password") \ + .load() + + jdbcDF2 = spark.read \ + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", + properties={"user": "username", "password": "password"}) + + # Specifying dataframe column data types on read + jdbcDF3 = spark.read \ + .format("jdbc") \ + .option("url", "jdbc:Sqream:dbserver") \ + .option("dbtable", "schema.tablename") \ + .option("user", "username") \ + .option("password", "password") \ + .option("customSchema", "id DECIMAL(38, 0), name TEXT") \ + .load() + + # Saving data to a JDBC source + jdbcDF.write \ + .format("jdbc") \ + .option("url", "jdbc:Sqream:dbserver") \ + .option("dbtable", "schema.tablename") \ + .option("user", "username") \ + .option("password", "password") \ + .save() + + jdbcDF2.write \ + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", + properties={"user": "username", "password": "password"}) + + # Specifying create table column data types on write + jdbcDF.write \ + .option("createTableColumnTypes", "name TEXT, comments TEXT") \ + .jdbc("jdbc:Sqream:dbserver", "schema.tablename", + properties={"user": "username", "password": "password"}) + +R + +.. code-block:: postgres + + # Loading data from a JDBC source + df <- read.jdbc("jdbc:Sqream:dbserver", "schema.tablename", user = "username", password = "password") + + # Saving data to a JDBC source + write.jdbc(df, "jdbc:Sqream:dbserver", "schema.tablename", user = "username", password = "password") + +SQL + +.. code-block:: postgres + + CREATE TEMPORARY VIEW jdbcTable + USING org.apache.spark.sql.jdbc + OPTIONS ( + url "jdbc:Sqream:dbserver", + dbtable "schema.tablename", + user 'username', + password 'password' + ) + + INSERT INTO TABLE jdbcTable + SELECT * FROM resultTable \ No newline at end of file From 4e8739a95dc9b63b8797fb1669c3c4a2b1942bd5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 8 Jan 2023 14:18:24 +0200 Subject: [PATCH 0384/1892] Spark --- .../client_platforms/spark.rst | 125 +++++++++--------- reference/cli/server_picker.rst | 2 +- 2 files changed, 65 insertions(+), 62 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index d610f5d42..7a5adc225 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -48,67 +48,70 @@ Connection Parameters :widths: auto :header-rows: 1 - * - Item - - Default - - Description - * - ``url`` - - - - The JDBC URL of the form ``jdbc:subprotocol:subname`` to connect to. The source-specific connection properties may be specified in the URL. e.g., ``jdbc:Sqream://localhost/test?user=fred&password=secret`` - * - ``dbtable`` - - - - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. - * - ``query`` - - - - A query that will be used to read data into Spark. The specified query will be parenthesized and used as a subquery in the ``FROM`` clause. Spark will also assign an alias to the subquery clause. As an example, spark will issue a query of the following form to the JDBC Source. ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. Restrictions while using this option: 1. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. 2. It is not allowed to specify ``query`` and ``partitionColumn`` options at the same time. When specifying ``partitionColumn`` option is required, the subquery can be specified using ``dbtable`` option instead and partition columns can be qualified using the subquery alias provided as part of ``dbtable``. - Example: ``spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load()`` - * - ``driver`` - - - - The class name of the JDBC driver to use to connect to this URL. - * - ``numPartitions`` - - - - The maximum number of partitions that can be used for parallelism in table reading and writing. This also determines the maximum number of concurrent JDBC connections. If the number of partitions to write exceeds this limit, we decrease it to this limit by calling ``coalesce(numPartitions)`` before writing. - * - ``queryTimeout`` - - 0 - - The number of seconds the driver will wait for a Statement object to execute to the given number of seconds. Zero means there is no limit. In the write path, this option depends on how JDBC drivers implement the API ``setQueryTimeout``, e.g., the h2 JDBC driver checks the timeout of each query instead of an entire JDBC batch. - * - ``fetchsize`` - - 1 - - The JDBC fetch size, which determines how many rows to fetch per round trip. This can help performance on JDBC drivers which default to low fetch size (e.g. Oracle with 10 rows). - * - ``batchsize`` - - 1000000 - - The JDBC batch size, which determines how many rows to insert per round trip. This can help performance on JDBC drivers. This option applies only to writing. - * - ``sessionInitStatement`` - - - - After each database session is opened to the remote DB and before starting to read data, this option executes a custom SQL statement (or a PL/SQL block). Use this to implement session initialization code. Example: ``option("sessionInitStatement", """BEGIN execute immediate 'alter session set "_serial_direct_read"=true'; END;""")`` - * - ``truncate`` - - ``false`` - - This is a JDBC writer related option. When ``SaveMode.Overwrite`` is enabled, this option causes Spark to truncate an existing table instead of dropping and recreating it. This can be more efficient, and prevents the table metadata (e.g., indices) from being removed. However, it will not work in some cases, such as when the new data has a different schema. In case of failures, users should turn off ``truncate`` option to use ``DROP TABLE`` again. Also, due to the different behavior of ``TRUNCATE TABLE`` among DBMS, it's not always safe to use this. MySQLDialect, DB2Dialect, MsSqlServerDialect, DerbyDialect, and OracleDialect supports this while PostgresDialect and default JDBCDirect doesn't. For unknown and unsupported JDBCDirect, the user option ``truncate`` is ignored. - * - ``cascadeTruncate`` - - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect - - This is a JDBC writer related option. If enabled and supported by the JDBC database (PostgreSQL and Oracle at the moment), this options allows execution of a ``TRUNCATE TABLE t CASCADE`` (in the case of PostgreSQL a TRUNCATE TABLE ONLY t CASCADE is executed to prevent inadvertently truncating descendant tables). This will affect other tables, and thus should be used with care. - * - ``createTableOptions`` - - - - This is a JDBC writer related option. If specified, this option allows setting of database-specific table and partition options when creating a table (e.g., ``CREATE TABLE t (name string) ENGINE=InnoDB.``). - * - ``createTableColumnTypes`` - - - - The database column data types to use instead of the defaults, when creating the table. Data type information should be specified in the same format as CREATE TABLE columns syntax (e.g: ``"name CHAR(64), comments VARCHAR(1024)"``). The specified types should be valid spark sql data types. - * - ``customSchema`` - - - - The custom schema to use for reading data from JDBC connectors. For example, ``"id DECIMAL(38, 0), name STRING"``. You can also specify partial fields, and the others use the default type mapping. For example, ``"id DECIMAL(38, 0)"``. The column names should be identical to the corresponding column names of JDBC table. Users can specify the corresponding data types of Spark SQL instead of using the defaults. - * - ``pushDownPredicate`` - - ``true`` - - The option to enable or disable predicate push-down into the JDBC data source. The default value is true, in which case Spark will push down filters to the JDBC data source as much as possible. Otherwise, if set to false, no filter will be pushed down to the JDBC data source and thus all filters will be handled by Spark. Predicate push-down is usually turned off when the predicate filtering is performed faster by Spark than by the JDBC data source. - * - ``pushDownAggregate`` - - ``false`` - - The option to enable or disable aggregate push-down in V2 JDBC data source. The default value is false, in which case Spark will not push down aggregates to the JDBC data source. Otherwise, if sets to true, aggregates will be pushed down to the JDBC data source. Aggregate push-down is usually turned off when the aggregate is performed faster by Spark than by the JDBC data source. Please note that aggregates can be pushed down if and only if all the aggregate functions and the related filters can be pushed down. If ``numPartitions`` equals to 1 or the group by key is the same as ``partitionColumn``, Spark will push down aggregate to data source completely and not apply a final aggregate over the data source output. Otherwise, Spark will apply a final aggregate over the data source output. - * - ``pushDownLimit`` - - ``false`` - - The option to enable or disable LIMIT push-down into V2 JDBC data source. The LIMIT push-down also includes LIMIT + SORT , a.k.a. the Top N operator. The default value is false, in which case Spark does not push down LIMIT or LIMIT with SORT to the JDBC data source. Otherwise, if sets to true, LIMIT or LIMIT with SORT is pushed down to the JDBC data source. If ``numPartitions`` is greater than 1, SPARK still applies LIMIT or LIMIT with SORT on the result from data source even if LIMIT or LIMIT with SORT is pushed down. Otherwise, if LIMIT or LIMIT with SORT is pushed down and ``numPartitions`` equals to 1, SPARK will not apply LIMIT or LIMIT with SORT on the result from data source. - * - ``pushDownTableSample`` - - ``false`` - - The option to enable or disable TABLESAMPLE push-down into V2 JDBC data source. The default value is false, in which case Spark does not push down TABLESAMPLE to the JDBC data source. Otherwise, if value sets to true, TABLESAMPLE is pushed down to the JDBC data source. - * - ``connectionProvider`` - - - - The name of the JDBC connection provider to use to connect to this URL, e.g. ``db2``, ``mssql``. Must be one of the providers loaded with the JDBC data source. Used to disambiguate when more than one provider can handle the specified driver and options. The selected provider must not be disabled by ``spark.sql.sources.disabledJdbcConnProviderList``. + + * - Item + - Default + - Description + * - ``url`` + - + - The JDBC URL of the form ``jdbc:subprotocol:subname`` to connect to. The source-specific connection properties may be specified in the URL. e.g., ``jdbc:Sqream://localhost/test?user=fred&password=secret``. + * - ``dbtable`` + - + - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + * - ``dbtable`` + - + - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + * - ``query`` + - + - A query that will be used to read data into Spark. The specified query will be parenthesized and used as a subquery in the ``FROM`` clause. Spark will also assign an alias to the subquery clause. As an example, spark will issue a query of the following form to the JDBC Source. ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. Restrictions while using this option: 1. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. 2. It is not allowed to specify ``query`` and ``partitionColumn`` options at the same time. When specifying ``partitionColumn`` option is required, the subquery can be specified using ``dbtable`` option instead and partition columns can be qualified using the subquery alias provided as part of ``dbtable``. Example: ``spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load()`` + * - ``driver`` + - + - The class name of the JDBC driver to use to connect to this URL. + * - ``numPartitions`` + - + - The maximum number of partitions that can be used for parallelism in table reading and writing. This also determines the maximum number of concurrent JDBC connections. If the number of partitions to write exceeds this limit, we decrease it to this limit by calling ``coalesce(numPartitions)`` before writing. + * - ``queryTimeout`` + - 0 + - The number of seconds the driver will wait for a Statement object to execute to the given number of seconds. Zero means there is no limit. In the write path, this option depends on how JDBC drivers implement the API ``setQueryTimeout``, e.g., the h2 JDBC driver checks the timeout of each query instead of an entire JDBC batch. + * - ``fetchsize`` + - 1 + - The JDBC fetch size, which determines how many rows to fetch per round trip. This can help performance on JDBC drivers which default to low fetch size (e.g. Oracle with 10 rows). + * - ``batchsize`` + - 1000000 + - The JDBC batch size, which determines how many rows to insert per round trip. This can help performance on JDBC drivers. This option applies only to writing. + * - ``sessionInitStatement`` + - + - After each database session is opened to the remote DB and before starting to read data, this option executes a custom SQL statement (or a PL/SQL block). Use this to implement session initialization code. Example: ``option("sessionInitStatement", """BEGIN execute immediate 'alter session set "_serial_direct_read"=true'; END;""")`` + * - ``truncate`` + - ``false`` + - This is a JDBC writer related option. When ``SaveMode.Overwrite`` is enabled, this option causes Spark to truncate an existing table instead of dropping and recreating it. This can be more efficient, and prevents the table metadata (e.g., indices) from being removed. However, it will not work in some cases, such as when the new data has a different schema. In case of failures, users should turn off ``truncate`` option to use ``DROP TABLE`` again. Also, due to the different behavior of ``TRUNCATE TABLE`` among DBMS, it's not always safe to use this. MySQLDialect, DB2Dialect, MsSqlServerDialect, DerbyDialect, and OracleDialect supports this while PostgresDialect and default JDBCDirect doesn't. For unknown and unsupported JDBCDirect, the user option ``truncate`` is ignored. + * - ``cascadeTruncate`` + - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect + - This is a JDBC writer related option. If enabled and supported by the JDBC database (PostgreSQL and Oracle at the moment), this options allows execution of a ``TRUNCATE TABLE t CASCADE`` (in the case of PostgreSQL a TRUNCATE TABLE ONLY t CASCADE is executed to prevent inadvertently truncating descendant tables). This will affect other tables, and thus should be used with care. + * - ``createTableOptions`` + - + - This is a JDBC writer related option. If specified, this option allows setting of database-specific table and partition options when creating a table (e.g., ``CREATE TABLE t (name string) ENGINE=InnoDB.``). + * - ``createTableColumnTypes`` + - + - The database column data types to use instead of the defaults, when creating the table. Data type information should be specified in the same format as CREATE TABLE columns syntax (e.g: ``"name CHAR(64), comments VARCHAR(1024)"``). The specified types should be valid spark sql data types. + * - ``customSchema`` + - + - The custom schema to use for reading data from JDBC connectors. For example, ``"id DECIMAL(38, 0), name STRING"``. You can also specify partial fields, and the others use the default type mapping. For example, ``"id DECIMAL(38, 0)"``. The column names should be identical to the corresponding column names of JDBC table. Users can specify the corresponding data types of Spark SQL instead of using the defaults. + * - ``pushDownPredicate`` + - ``true`` + - The option to enable or disable predicate push-down into the JDBC data source. The default value is true, in which case Spark will push down filters to the JDBC data source as much as possible. Otherwise, if set to false, no filter will be pushed down to the JDBC data source and thus all filters will be handled by Spark. Predicate push-down is usually turned off when the predicate filtering is performed faster by Spark than by the JDBC data source. + * - ``pushDownAggregate`` + - ``false`` + - The option to enable or disable aggregate push-down in V2 JDBC data source. The default value is false, in which case Spark will not push down aggregates to the JDBC data source. Otherwise, if sets to true, aggregates will be pushed down to the JDBC data source. Aggregate push-down is usually turned off when the aggregate is performed faster by Spark than by the JDBC data source. Please note that aggregates can be pushed down if and only if all the aggregate functions and the related filters can be pushed down. If ``numPartitions`` equals to 1 or the group by key is the same as ``partitionColumn``, Spark will push down aggregate to data source completely and not apply a final aggregate over the data source output. Otherwise, Spark will apply a final aggregate over the data source output. + * - ``pushDownLimit`` + - ``false`` + - The option to enable or disable LIMIT push-down into V2 JDBC data source. The LIMIT push-down also includes LIMIT + SORT , a.k.a. the Top N operator. The default value is false, in which case Spark does not push down LIMIT or LIMIT with SORT to the JDBC data source. Otherwise, if sets to true, LIMIT or LIMIT with SORT is pushed down to the JDBC data source. If ``numPartitions`` is greater than 1, SPARK still applies LIMIT or LIMIT with SORT on the result from data source even if LIMIT or LIMIT with SORT is pushed down. Otherwise, if LIMIT or LIMIT with SORT is pushed down and ``numPartitions`` equals to 1, SPARK will not apply LIMIT or LIMIT with SORT on the result from data source. + * - ``pushDownTableSample`` + - ``false`` + - The option to enable or disable TABLESAMPLE push-down into V2 JDBC data source. The default value is false, in which case Spark does not push down TABLESAMPLE to the JDBC data source. Otherwise, if value sets to true, TABLESAMPLE is pushed down to the JDBC data source. + * - ``connectionProvider`` + - + - The name of the JDBC connection provider to use to connect to this URL, e.g. ``db2``, ``mssql``. Must be one of the providers loaded with the JDBC data source. Used to disambiguate when more than one provider can handle the specified driver and options. The selected provider must not be disabled by ``spark.sql.sources.disabledJdbcConnProviderList``. Data transfer from SQream to Spark diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index e64d792a0..3bfd4a004 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -31,7 +31,7 @@ Positional command line arguments * - ``TCP listen port`` - ``3108`` - TCP port for server picker to listen on - * - ``Metadata server port`` + * - ``SSL listen port`` - ``3109`` - SSL port for server picker to listen on From 6faec673ce3b64e2e3c27e1ba6d0b905167230c5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 8 Jan 2023 16:37:50 +0200 Subject: [PATCH 0385/1892] RN --- .../client_platforms/spark.rst | 4 +- releases/4.0.0_index.rst | 51 ++++++++----------- 2 files changed, 22 insertions(+), 33 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index 7a5adc225..d7c9e13ad 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -23,8 +23,8 @@ To use Spark with SQream, you must have the following installed: -Installation ------------- +Installation and Configuration +------------------------------ .. contents:: :local: diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index 8458ba8b7..4a490c16a 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -12,66 +12,55 @@ The 4.0.0 release notes were released on xx/xx/20xx and describe the following: :local: :depth: 1 - - New Features ----------- +------------ * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature :: - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles :: + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + +SQream Studio Updates and Improvements +-------------------------------------- + + * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. + + :: Known Issues ---------- +------------ :ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 4.0.0 resolved Issues ---------- +----------------------------- +---------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +===============+==========================================================================================+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | +| SQ-10544 | | +---------------+------------------------------------------------------------------------------------------+ | SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | +---------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | +| SQ-12580 | Server Picker GPU dependency | +---------------+------------------------------------------------------------------------------------------+ -| SQ-12255 | ``COPY TO`` string export error | +| SQ-12652 | Result panel adjustment | +---------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+---------------+------------------------------------------------------------------------------------------+ - - - - - Configuration Changes --------- +--------------------- No configuration changes were made. Naming Changes -------- +-------------- No relevant naming changes were made. Deprecated Features -------- +------------------- SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -80,11 +69,11 @@ TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR End of Support -------- +--------------- No End of Support changes were made. Upgrading to v4.0.0 -------- +------------------- 1. Generate a back-up of the metadata by running the following command: .. code-block:: console From 3115b10b5ca0d207c1b49a30305a112b068bf796 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 8 Jan 2023 17:32:50 +0200 Subject: [PATCH 0386/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 3708d85ae..b0610efcd 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -91,6 +91,8 @@ The following table shows the ``COPY_TO`` elements: - The CSV file will contain a header line with the names of each column in the file. This option is allowed only when using CSV format. * - ``DELIMITER`` - Specifies the character or string that separates fields (columns) within each row of the file. The default is a comma character (``,``). + * - ``RECORD_DELIMITER`` + - Specifies the character or string that separates records in a data set. This option is allowed only when using CSV format. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets * - ``MAX_FILE_SIZE`` @@ -458,7 +460,7 @@ The following is an example of exporting a table to a TSV file with a HEADER row .. code-block:: psql - COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = '|', HEADER = true); + COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = '\t', HEADER = true); .. code-block:: console From 1afef227e31e2b17e5d0b661a6d9881de96c2e37 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 9 Jan 2023 13:23:23 +0200 Subject: [PATCH 0387/1892] Update spark.rst --- .../client_platforms/spark.rst | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index d7c9e13ad..20472ceef 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -1,11 +1,11 @@ .. _spark: ************************* -Connecting to SQream Using Spark +Using Spark With SQream ************************* -If you are using Spark for distributed processing and analysis and wish to use it to connect to SQream, follow these instructions. +If you are using Spark for distributed processing and analysis and wish to use it with SQream, follow these instructions. .. contents:: @@ -33,17 +33,19 @@ Installation and Configuration JDBC ~~~~ -In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. +If JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. SQream Spark Plugin ~~~~~~~~~~~~~~~~~~~ -The SQream Spark plugin supports bi-directional data transfer between the different clusters. The Spark cluster may be self-hosted or third-party hosted, using services such as Qubole, AWS EMR, or Databricks. +The SQream Spark plugin supports bi-directional data transfer between the Spark and the SQream cluster. -Connection Parameters +Connection Command and Parameters ~~~~~~~~~~~~~~~~~~~~~ +**Missing connection command** + .. list-table:: :widths: auto :header-rows: 1 @@ -114,18 +116,20 @@ Connection Parameters - The name of the JDBC connection provider to use to connect to this URL, e.g. ``db2``, ``mssql``. Must be one of the providers loaded with the JDBC data source. Used to disambiguate when more than one provider can handle the specified driver and options. The selected provider must not be disabled by ``spark.sql.sources.disabledJdbcConnProviderList``. -Data transfer from SQream to Spark --------------------- +Transferring Data From SQream to Spark +------------------------------------- -1. Use the read() method of the SqlContext object to construct a DataFrameReader. +In the Spark UI, configure Spark to write to the SQream database. -2. Specify SQREAM_SOURCE_NAME using the format() method. For the definition +1. From the SqlContext object, use the read() method to construct a DataFrameReader. -3. Specify the connector options using either the option() or options() method. +2. Use the format() method to specify SQREAM_SOURCE_NAME. + +3. Use either the option() or options() method to specify the connector options. -4. Specify one of the following options for the table data to be read: +4. Specify one of the following options for reading tables: - * dbtable: The name of the table to be read. All columns and records are retrieved (i.e. it is equivalent to SELECT * FROM db_table). + * dbtable: The name of the table to be read. All columns and records are retrieved (i.e. it is equivalent to ``SELECT * FROM db_table``). * query: The exact query (SELECT statement) to run. @@ -145,8 +149,10 @@ To read query results: val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("query", "<EXECUTED_QUERY> <table_name>") .load() -Data transfer from Spark to SQream --------------------------------- +Transferring data From Spark to SQream +-------------------------------------- + +In the Spark UI, configure Spark to read from the SQream database. 1. Use the write() method of the DataFrame to construct a DataFrameWriter. From 3641996e77fa05ad6f5444cacfd9f8cb6dff2b53 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 09:30:47 +0200 Subject: [PATCH 0388/1892] comment --- configuration_guides/current_method_configuration_levels.rst | 2 +- configuration_guides/current_method_configuration_roles.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 47ccf32b3..216919991 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -11,7 +11,7 @@ SQream's configuration parameters are based on the following hierarchy: Cluster-Based Configuration -------------- -Cluster-based configuration lets you centralize configurations for all workers on the cluster. Only Regular and Cluster flag types can be modified on the cluster level. These modifications are persistent and stored at the metadata level, which are applied globally to all workers in the cluster. +Cluster-based configuration lets you centralize configurations for all workers on the cluster. Only :ref:`Regular and Cluster flag types<current_method_flag_types>` can be modified on the cluster level. These modifications are persistent and stored at the metadata level, which are applied globally to all workers in the cluster. .. note:: While cluster-based configuration was designed for configuring Workers, you can only configure Worker values set to the Regular or Cluster type. diff --git a/configuration_guides/current_method_configuration_roles.rst b/configuration_guides/current_method_configuration_roles.rst index 11b7e4bfb..b3afc2b46 100644 --- a/configuration_guides/current_method_configuration_roles.rst +++ b/configuration_guides/current_method_configuration_roles.rst @@ -5,7 +5,7 @@ Configuration Roles ************************** SQream divides flags into the following roles, each with their own set of permissions: -* :ref:`admin_flags` - can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: **Comment** - *I don't think we need to mention the command here, as it's described below, and also not mentioned for Generic Flags.* +* :ref:`admin_flags` - can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: * Regular * Worker From eb38bde73cd833d276f78b9e30f9b6d7cf022f84 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 11:04:12 +0200 Subject: [PATCH 0389/1892] Kafka --- .../current_method_configuration_levels.rst | 2 +- .../client_drivers/kafka/index.rst | 23 +++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 216919991..a6d9b91aa 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -17,7 +17,7 @@ Cluster-based configuration lets you centralize configurations for all workers o Worker-Based Configuration -------------- -Worker-based configuration lets you modify the configuration belong to individual workers from the worker configuration file. +Worker-based configuration lets you modify individual workers using a worker configuration file. Worker-based configuration modifications are persistent. For more information on making configurations from the worker configuration file, see `Modifying Your Configuration Using a Legacy Configuration File <https://docs.sqream.com/en/latest/configuration_guides/current_configuration_method.html#modifying-your-configuration-using-a-legacy-configuration-file>`_. diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 22c06709c..524dc5243 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -4,7 +4,8 @@ Connecting to SQream Using Kafka ************************* -This page describes how to connect SQream with Kafka Apache. +If you are using Kafka Apache for distributed streaming and wish to use it with SQream, follow these instructions. + .. contents:: :local: @@ -42,9 +43,7 @@ Supported Data Formats Kafka Producer -------------- -The Kafka Producer can be used for creating new topics, reading data from existing topics, and loading data from files. - -In order for the Kafka producer to operate correctly, both the Kafka producer and Zookeeper processes must be running simultaneously. If Zookeeper is not running, the Kafka producer will not start. +The Kafka Producer requires both the Kafka producer and Zookeeper processes to be running in order to create new topics, read data from existing topics, and load data from files. If Zookeeper is not running, the Kafka producer will not start. .. contents:: :local: @@ -53,7 +52,7 @@ In order for the Kafka producer to operate correctly, both the Kafka producer an Kafka Producer Installation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Kafka producer is installed on the 192.168.0.125 server. +The Kafka Producer is installed on the 192.168.0.125 server. Kafka Producer Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -110,34 +109,34 @@ Loading data from a file: cd /home/sqream/kafka_2.12-3.2.1/ ./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic <topic name> < <full path to file> -Closing Kafka producer: +Terminating the Kafka Producer requires that both the Kafka Producer and Zookeeper be terminated. To avoid data inconsistency and potential data loss, terminate the Kafka Producer before terminating the Zookeeper. -To close the Kafka producer, you must first stop the producer and then stop Zookeeper. +Terminating the Kafka Producer: .. code-block:: postgres cd /home/sqream/kafka_2.12-3.2.1/ bin/kafka-server-stop.sh -Kafka Consumer +SQream Consumer --------------- .. contents:: :local: :depth: 1 -The Kafka consumer converts data formatted as CSV and JSON into ``.tmp`` files and saves it in a predefined directory. +The SQream Consumer converts data formatted as CSV and JSON into ``.tmp`` files and saves it in a predefined directory. You must define the number of files to be converted before they are saved as a ``sqream.batchRecordCount`` file. Once reaching the defined number of files, the consumer saves the converted files and begins the process all over again. -Kafka Consumer Installation +SQream Consumer Installation ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The Kafka consumer version is located under /home/sqream/kafkaconnect1, machine IP 192.168.0.102 +The SQream Consumer version is located under /home/sqream/kafkaconnect1, machine IP 192.168.0.102 Credentials: user = sqream pass = sqprj2021$ -Kafka Consumer Configuration +SQream Consumer Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ What needs to be configured: From 3a95bb2e7182320eea461a2ea955e85b19a0a920 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 11:04:46 +0200 Subject: [PATCH 0390/1892] Update current_method_flag_types.rst --- configuration_guides/current_method_flag_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index b1bedecba..7908e65d0 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -5,7 +5,7 @@ Flag Types ************************** SQream uses three flag types, **Cluster**, **Worker**, and **Regular**. Each of these flag types is associated with one of three hierarchical configuration levels described earlier, making it easier to configure your system. -The highest level in the hierarchy is Cluster, which lets you set configurations across all workers in a given cluster. Modifying cluster values is **persistent**, meaning that any configurations you set are retained after shutting down your system. Configurations set at the Cluster level take the highest priority and override settings made on the Regular and Worker level **Comment** - *Confirm*. This is known as **cluster-based configuration**. Note that Cluster-based configuration lets you modify Cluster *and* Regular flag types. An example of a Cluster flag is **persisting your cache directory.** +The highest level in the hierarchy is Cluster, which lets you set configurations across all workers in a given cluster. Modifying cluster values is **persistent**, meaning that any configurations you set are retained after shutting down your system. Configurations set at the Cluster level take the highest priority and override settings made on the Regular and Worker level. This is known as **cluster-based configuration**. Note that Cluster-based configuration lets you modify Cluster *and* Regular flag types. An example of a Cluster flag is **persisting your cache directory.** The second level is Worker, which lets you configure individual workers. Modifying Worker values are also **persistent**. This is known as **worker-based configuration**. Some examples of Worker flags includes **setting total device memory usage** and **setting metadata server connection port**. From 691125ddacb881883d7e8c7c41366b36ba278b45 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 13:35:27 +0200 Subject: [PATCH 0391/1892] Update 4.0.0_index.rst --- releases/4.0.0_index.rst | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index 4a490c16a..1b962fbdc 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -4,7 +4,7 @@ Release Notes 4.0.0 ************************** -**SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released 4.0.0 version is a minor version upgrade and does not require considerable preparation.** +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. The 4.0.0 release notes were released on xx/xx/20xx and describe the following: @@ -42,13 +42,29 @@ Version 4.0.0 resolved Issues +---------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +===============+==========================================================================================+ -| SQ-10544 | | +| SQ-10544 | SQream Studio Worker Panel issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | +---------------+------------------------------------------------------------------------------------------+ | SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | +---------------+------------------------------------------------------------------------------------------+ +| SQ-12310 | ``DICT`` compression buffer size issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++---------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++---------------+------------------------------------------------------------------------------------------+ | SQ-12580 | Server Picker GPU dependency | +---------------+------------------------------------------------------------------------------------------+ -| SQ-12652 | Result panel adjustment | +| SQ-12652 | SQream Studio result panel adjustment | +---------------+------------------------------------------------------------------------------------------+ Configuration Changes From 23333c568fbc7bf796b1eb1a2cb135d16efec81c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 13:36:13 +0200 Subject: [PATCH 0392/1892] Update index.rst --- .../client_drivers/kafka/index.rst | 43 ++++++++----------- 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 524dc5243..ee8e3e98c 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -19,26 +19,15 @@ Installation and Configuration :local: :depth: 1 -Prerequisites +Before You Begin ---------------- - * JAVA 11 - * Network bandwidth should be not less than X Giga/Sec - -Supported Data Formats ----------------------- -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Data Format - - Specification - * - JSON - - - * - CSV - - - * - Avro - - +* You must have JAVA 11 installed +* Your network bandwidth must be at least X gigabits per second +* Supported data formats for streaming data are: + * JSON + * CSV + * Avro Kafka Producer -------------- @@ -125,8 +114,9 @@ SQream Consumer :local: :depth: 1 -The SQream Consumer converts data formatted as CSV and JSON into ``.tmp`` files and saves it in a predefined directory. -You must define the number of files to be converted before they are saved as a ``sqream.batchRecordCount`` file. Once reaching the defined number of files, the consumer saves the converted files and begins the process all over again. +The SQream Consumer reads Kafka topics and writes messages into text files in either CSV, JSON, or Avro format. The files are created with the extension ``.tmp`` and stored in the specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file. When the specified number of records is reached, the SQream Consumer closes the file, renames it to the ``sqream.fileExtension``, and then creates a new file. + +SQream tables must be created according to the columns configured in ``csvorder``. SQream Consumer Installation ~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -139,7 +129,7 @@ pass = sqprj2021$ SQream Consumer Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -What needs to be configured: +The following parameters require configuration. .. list-table:: :widths: auto @@ -150,11 +140,11 @@ What needs to be configured: * - Topic - A category or feed name to which messages are published and subscribed to * - ``sqream.batchrecordcount`` - - Preferably configured according to an estimated number of messages + - The record count to be written to each file * - ``outputdir`` - Copy the ``sqream.outputdir`` path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path * - ``csvorder`` - - Create table columns + - Defines table columns. SQream table columns must align with the ``csvorder`` table columns Connection string: @@ -186,7 +176,7 @@ Configuration file structure: sqream.outputType=csv sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv -SQream tables must be created according to the columns configured in ``csvorder``. + Running commands: @@ -215,7 +205,7 @@ pass = sqprj2021$ SQream Loader Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Building SQream loader: +Building the SQream Loader: .. code-block:: postgres @@ -223,7 +213,7 @@ Building SQream loader: mvn clean package -Running SQream loader: +Running the SQream Loader: .. code-block:: postgres @@ -236,6 +226,7 @@ What needs to be configured: :widths: auto :header-rows: 1 + * - Parameter - Description * - ``root`` From 708d8da1c57a95c968c9397ff8122770a75225c7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Jan 2023 15:52:44 +0200 Subject: [PATCH 0393/1892] healer_max_statement_inactivity_seconds --- .../healer_max_inactivity_hours.rst | 14 -------------- .../healer_max_statement_inactivity_seconds.rst | 14 ++++++++++++++ feature_guides/query_healer.rst | 4 ++-- releases/2021.2.1.24.rst | 2 +- 4 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 configuration_guides/healer_max_inactivity_hours.rst create mode 100644 configuration_guides/healer_max_statement_inactivity_seconds.rst diff --git a/configuration_guides/healer_max_inactivity_hours.rst b/configuration_guides/healer_max_inactivity_hours.rst deleted file mode 100644 index 56ddb78fc..000000000 --- a/configuration_guides/healer_max_inactivity_hours.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _healer_max_inactivity_hours: - -************************* -Configuring the Query Healer -************************* -The ``healerMaxInactivityHours`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. - -The following describes the ``healerMaxInactivityHours`` flag: - -* **Data type** - size_t -* **Default value** - ``5`` -* **Allowed values** - 1-4000000000 - -For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/configuration_guides/healer_max_statement_inactivity_seconds.rst b/configuration_guides/healer_max_statement_inactivity_seconds.rst new file mode 100644 index 000000000..0de4e68e6 --- /dev/null +++ b/configuration_guides/healer_max_statement_inactivity_seconds.rst @@ -0,0 +1,14 @@ +.. _healer_max_statement_inactivity_seconds: + +************************* +Configuring the Query Healer +************************* +The ``maxStatementInactivitySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The following describes the ``maxStatementInactivitySeconds`` worker level flag: + +* **Data type** - size_t +* **Default value** - ``5`` +* **Allowed values** - 1-4000000000 + +For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 305875447..4c87ec0a9 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -11,7 +11,7 @@ The **Query Healer** page describes the following: Overview ---------- -The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``healerMaxInactivityHours`` flag setting. The default setting of the ``healerMaxInactivityHours`` is five hours. The ``healerMaxInactivityHours`` log frequency is calculated as 5% of the flag setting. When set to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``maxStatementInactivitySeconds`` worker level flag setting. The default setting of the ``maxStatementInactivitySeconds`` is five hours. The ``maxStatementInactivitySeconds`` log frequency is calculated as 5% of the flag setting. When set to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. The following is an example of a log record for a query stuck in the query detection phase for more than five hours: @@ -55,4 +55,4 @@ The following **Administration Worker** flags are required to configure the Quer :: - * :ref:`healer_max_inactivity_hours` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. \ No newline at end of file + * :ref:`healer_max_statement_inactivity_seconds` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index d277ea51a..8b1992283 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -59,7 +59,7 @@ The following table lists the known issues for Version 2021.2.1.24: Operations and Configuration Changes -------- -The following configuration flags were added: +The following worker level configuration flags were added: * :ref:`is_healer_on` From 7dcd4f5e754089a105c848ba2028e193a44d0e32 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Wed, 11 Jan 2023 09:31:08 +0200 Subject: [PATCH 0394/1892] Update 2021.2.1.24.rst --- releases/2021.2.1.24.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 8b1992283..f1ab492dc 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -65,7 +65,7 @@ The following worker level configuration flags were added: :: - * :ref:`healer_max_inactivity_hours` + * :ref:`healer_max_statement_inactivity_seconds:` Naming Changes ------- From 51ecc5835ffe6a4f5a3c503fbb5b2b8531b73524 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:06:11 +0200 Subject: [PATCH 0395/1892] Update spark.rst --- .../client_platforms/spark.rst | 135 +++--------------- 1 file changed, 19 insertions(+), 116 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index 20472ceef..9b57063d6 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -18,7 +18,7 @@ To use Spark with SQream, you must have the following installed: * SQream version 2022.1.8 or later * Spark version 3.3.1 or later -* SQream Spark plugin xxxx +* SQream Spark plugin 1.0.0 * JDBC version 4.5.6 or later @@ -41,10 +41,25 @@ SQream Spark Plugin The SQream Spark plugin supports bi-directional data transfer between the Spark and the SQream cluster. -Connection Command and Parameters +How to use with Spark Shell ~~~~~~~~~~~~~~~~~~~~~ -**Missing connection command** +Plugin command: + +.. code-block:: postgres + + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} + + +Plugin command example: + +.. code-block:: postgres + + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar + + + +Spark options supported by SQream: .. list-table:: :widths: auto @@ -172,6 +187,7 @@ To read an entire table: df.write .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .mode(SaveMode.Overwrite) .save() + Supported Data Types and Mapping -------------------------------- @@ -238,47 +254,6 @@ Spark data types mapped to SQream Examples --------- - -Scala - -.. code-block:: postgres - - // Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods - // Loading data from a JDBC source - val jdbcDF = spark.read - .format("jdbc") - .option("url", "jdbc:Sqream:dbserver") - .option("dbtable", "schema.tablename") - .option("user", "username") - .option("password", "password") - .load() - - val connectionProperties = new Properties() - connectionProperties.put("user", "username") - connectionProperties.put("password", "password") - val jdbcDF2 = spark.read - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) - // Specifying the custom data types of the read schema - connectionProperties.put("customSchema", "id DECIMAL(38, 0), name TEXT") - val jdbcDF3 = spark.read - .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties) - - // Saving data to a JDBC source - jdbcDF.write - .format("jdbc") - .option("url", "jdbc:Sqream:dbserver") - .option("dbtable", "schema.tablename") - .option("user", "username") - .option("password", "password") - .save() - - jdbcDF2.write - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) - - // Specifying create table column data types on write - jdbcDF.write - .option("createTableColumnTypes", "name TEXT, comments TEXT") - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties) JAVA @@ -317,75 +292,3 @@ JAVA .option("createTableColumnTypes", "name TEXT, comments TEXT") .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); -Python - -.. code-block:: postgres - - # Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods - # Loading data from a JDBC source - jdbcDF = spark.read \ - .format("jdbc") \ - .option("url", "jdbc:Sqream:dbserver") \ - .option("dbtable", "schema.tablename") \ - .option("user", "username") \ - .option("password", "password") \ - .load() - - jdbcDF2 = spark.read \ - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", - properties={"user": "username", "password": "password"}) - - # Specifying dataframe column data types on read - jdbcDF3 = spark.read \ - .format("jdbc") \ - .option("url", "jdbc:Sqream:dbserver") \ - .option("dbtable", "schema.tablename") \ - .option("user", "username") \ - .option("password", "password") \ - .option("customSchema", "id DECIMAL(38, 0), name TEXT") \ - .load() - - # Saving data to a JDBC source - jdbcDF.write \ - .format("jdbc") \ - .option("url", "jdbc:Sqream:dbserver") \ - .option("dbtable", "schema.tablename") \ - .option("user", "username") \ - .option("password", "password") \ - .save() - - jdbcDF2.write \ - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", - properties={"user": "username", "password": "password"}) - - # Specifying create table column data types on write - jdbcDF.write \ - .option("createTableColumnTypes", "name TEXT, comments TEXT") \ - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", - properties={"user": "username", "password": "password"}) - -R - -.. code-block:: postgres - - # Loading data from a JDBC source - df <- read.jdbc("jdbc:Sqream:dbserver", "schema.tablename", user = "username", password = "password") - - # Saving data to a JDBC source - write.jdbc(df, "jdbc:Sqream:dbserver", "schema.tablename", user = "username", password = "password") - -SQL - -.. code-block:: postgres - - CREATE TEMPORARY VIEW jdbcTable - USING org.apache.spark.sql.jdbc - OPTIONS ( - url "jdbc:Sqream:dbserver", - dbtable "schema.tablename", - user 'username', - password 'password' - ) - - INSERT INTO TABLE jdbcTable - SELECT * FROM resultTable \ No newline at end of file From 5136a9a09c51341f9cdc5e1d858ff570fcdf6dae Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 12 Jan 2023 11:34:06 +0200 Subject: [PATCH 0396/1892] Update current_method_configuration_levels.rst --- configuration_guides/current_method_configuration_levels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index a6d9b91aa..cb55893b3 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -19,7 +19,7 @@ Worker-Based Configuration -------------- Worker-based configuration lets you modify individual workers using a worker configuration file. Worker-based configuration modifications are persistent. -For more information on making configurations from the worker configuration file, see `Modifying Your Configuration Using a Legacy Configuration File <https://docs.sqream.com/en/latest/configuration_guides/current_configuration_method.html#modifying-your-configuration-using-a-legacy-configuration-file>`_. +For more information on making configurations from the worker configuration file, see :ref:`current_method_modification_methods`. Session-Based Configuration -------------- From 197b770eeba0f6f841d85b4428b93e4ea8b5f253 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 12 Jan 2023 16:08:35 +0200 Subject: [PATCH 0397/1892] Update spark.rst --- .../client_platforms/spark.rst | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index 9b57063d6..823fa5728 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -12,17 +12,6 @@ If you are using Spark for distributed processing and analysis and wish to use i :local: :depth: 1 -Prerequisites -------------- -To use Spark with SQream, you must have the following installed: - -* SQream version 2022.1.8 or later -* Spark version 3.3.1 or later -* SQream Spark plugin 1.0.0 -* JDBC version 4.5.6 or later - - - Installation and Configuration ------------------------------ @@ -30,36 +19,48 @@ Installation and Configuration :local: :depth: 1 +Before You Begin +~~~~~~~~~~~~~~~~ + +To use Spark with SQream, you must have the following installed: + +* SQream version 2022.1.8 or later +* Spark version 3.3.1 or later +* SQream Spark Connector 1.0.0 +* JDBC version 4.5.6 or later + JDBC ~~~~ If JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. -SQream Spark Plugin +SQream-Spark Connector ~~~~~~~~~~~~~~~~~~~ -The SQream Spark plugin supports bi-directional data transfer between the Spark and the SQream cluster. +The SQream-Spark Connector enables inserting DataFrames into SQream tables and export tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. -How to use with Spark Shell -~~~~~~~~~~~~~~~~~~~~~ -Plugin command: +The SQream-Spark Connector command for Spark Shell: .. code-block:: postgres ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} -Plugin command example: +An example for the SQream-Spark Connector command: .. code-block:: postgres ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar +Connector Configuration +~~~~~~~~~~~~~~~~~~~~~~~ + +The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. -Spark options supported by SQream: +The following Spark connection properties are supported by SQream: .. list-table:: :widths: auto From 54e49546b3ab7ef7c020d0a19ab48c575843d0f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 12 Jan 2023 16:20:53 +0200 Subject: [PATCH 0398/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index b0610efcd..167f70c23 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -65,7 +65,6 @@ The following is the correct syntax for using the **COPY TO** statement: AWS Secret ::= string -.. note:: The DELIMITER is applicable to the CSV format only. .. note:: In Studio, you must write the parameters using lower case letters. Using upper case letters generates an error. @@ -90,7 +89,7 @@ The following table shows the ``COPY_TO`` elements: * - ``HEADER`` - The CSV file will contain a header line with the names of each column in the file. This option is allowed only when using CSV format. * - ``DELIMITER`` - - Specifies the character or string that separates fields (columns) within each row of the file. The default is a comma character (``,``). + - Specifies the character or string that separates fields (columns) within each row of the file. The default is a comma character (``,``). This option is allowed only when using CSV format. * - ``RECORD_DELIMITER`` - Specifies the character or string that separates records in a data set. This option is allowed only when using CSV format. * - ``AWS_ID``, ``AWS_SECRET`` From 0f8c16f272ba024a0eb71150e0a3df35028b2b89 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 12:09:46 +0200 Subject: [PATCH 0399/1892] Update creating_assigning_and_managing_roles_and_permissions.rst --- ...ing_and_managing_roles_and_permissions.rst | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst index 31ff716cb..648117ca7 100644 --- a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst @@ -63,11 +63,11 @@ An admin creates a **user** by granting login permissions and a password to a ro Clicking **New Role** lets you do the following: * Add and assign a role name (required) - * Enable or disable log-in permissions for the role. - * Set a password. - * Assign or delete parent roles. - * Add or delete permissions. - * Grant the selected user with superuser permissions. + * Enable or disable log-in permissions for the role + * Set a password + * Assign or delete parent roles + * Add or delete permissions + * Grant the selected user with superuser permissions From the New Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the New Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. @@ -79,13 +79,13 @@ Editing a Role -------------------- Once you've created a role, clicking the **Edit Role** button lets you do the following: - * Edit the role name. - * Enable or disable log-in permissions. - * Set a password. - * Assign or delete parent roles. - * Assign a role **administrator** permissions. - * Add or delete permissions. - * Grant the selected user with superuser permissions. + * Edit role name + * Enable or disable log-in permissions + * Set a password + * Assign or delete parent roles + * Assign a role **administrator** permissions + * Add or delete permissions + * Grant the selected user with superuser permissions From the Edit Role panel you view directly and indirectly (or inherited) granted permissions. Disabled permissions have no connect permissions for the referenced database and are displayed in gray text. You can add or remove permissions from the **Add permissions** field. From the Edit Role panel you can also search and scroll through the permissions. In the **Search** field you can use the **and** operator to search for strings that fulfill multiple criteria. From 2f66a5f3b4d7a0c5f5a2b7a1072a3709e6009c03 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 12:42:08 +0200 Subject: [PATCH 0400/1892] block_new_varchar_objects --- configuration_guides/admin_regular_flags.rst | 2 +- configuration_guides/block_new_varchar_objects.rst | 12 ++++++++++++ .../current_method_all_configurations.rst | 6 +++--- configuration_guides/varchar_identifiers.rst | 12 ------------ 4 files changed, 16 insertions(+), 16 deletions(-) create mode 100644 configuration_guides/block_new_varchar_objects.rst delete mode 100644 configuration_guides/varchar_identifiers.rst diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index 902ff224b..a9b0681bd 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -28,5 +28,5 @@ The **Regular Administration Flags** page describes **Regular** modification typ * `Setting Implicit Casts in ORC Files <https://docs.sqream.com/en/v2022.1.1/configuration_guides/orc_implicit_casts.html>`_ * `Setting Timeout Limit for Locking Objects before Executing Statements <https://docs.sqream.com/en/v2022.1.1/configuration_guides/statement_lock_timeout.html>`_ * `Interpreting Decimal Literals as Double Instead of Numeric <https://docs.sqream.com/en/v2022.1.1/configuration_guides/use_legacy_decimal_literals.html>`_ -* `Interpreting VARCHAR as TEXT <https://docs.sqream.com/en/v2022.1.1/configuration_guides/use_legacy_string_literals.html>`_ +* :ref:`Blocking New VARCHAR Objects<block_new_varchar_objects>` * `VARCHAR Identifiers <https://docs.sqream.com/en/v2022.1.1/configuration_guides/varchar_identifiers.html>`_ diff --git a/configuration_guides/block_new_varchar_objects.rst b/configuration_guides/block_new_varchar_objects.rst new file mode 100644 index 000000000..a64ff7995 --- /dev/null +++ b/configuration_guides/block_new_varchar_objects.rst @@ -0,0 +1,12 @@ +.. _block_new_varchar_objects: + +************************* +Blocking New VARCHAR Objects +************************* +The ``blockNewVarcharObjects`` flag disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. + +The following describes the ``blockNewVarcharObjects`` flag: + +* **Data type** - boolean +* **Default value** - ``false`` +* **Allowed values** - ``true``, ``false`` \ No newline at end of file diff --git a/configuration_guides/current_method_all_configurations.rst b/configuration_guides/current_method_all_configurations.rst index 7385066af..9a2352faf 100644 --- a/configuration_guides/current_method_all_configurations.rst +++ b/configuration_guides/current_method_all_configurations.rst @@ -423,9 +423,9 @@ The following table describes all **Generic** and **Administration** configurati - * - ``varcharIdentifiers`` + * - ``blockNewVarcharObjects`` - Admin - Regular - - Activates using varchar as an identifier. + - Disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. - boolean - - ``true`` \ No newline at end of file + - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/varchar_identifiers.rst b/configuration_guides/varchar_identifiers.rst deleted file mode 100644 index 889e5c16e..000000000 --- a/configuration_guides/varchar_identifiers.rst +++ /dev/null @@ -1,12 +0,0 @@ -.. _varchar_identifiers: - -************************* -Interpreting VARCHAR as TEXT -************************* -The ``varcharIdentifiers`` flag activates using **varchar** as an identifier. - -The following describes the ``varcharIdentifiers`` flag: - -* **Data type** - boolean -* **Default value** - ``true`` -* **Allowed values** - ``true``, ``false`` \ No newline at end of file From 217e7d8c788b092200bd6601673112c1fe1e3aee Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 13:20:22 +0200 Subject: [PATCH 0401/1892] Update admin_regular_flags.rst --- configuration_guides/admin_regular_flags.rst | 48 ++++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst index a9b0681bd..fd7131692 100644 --- a/configuration_guides/admin_regular_flags.rst +++ b/configuration_guides/admin_regular_flags.rst @@ -5,28 +5,28 @@ Regular Administration Flags ************************* The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: -* `Setting Bin Size <https://docs.sqream.com/en/v2022.1.1/configuration_guides/bin_sizes.html>`_ -* `Setting CUDA Memory <https://docs.sqream.com/en/v2022.1.1/configuration_guides/check_cuda_memory.html>`_ -* `Limiting Runtime to Utility Functions <https://docs.sqream.com/en/v2022.1.1/configuration_guides/compiler_gets_only_ufs.html>`_ -* `Enabling High Bin Control Granularity <https://docs.sqream.com/en/v2022.1.1/configuration_guides/copy_to_restrict_utf8.html>`_ -* `Reducing CPU Hashtable Sizes <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cpu_reduce_hashtable_size.html>`_ -* `Setting Chunk Size for Copying from CPU to GPU <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cuda_mem_cpy_max_size_bytes.html>`_ -* `Indicating GPU Synchronicity <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cuda_mem_cpy_synchronous.html>`_ -* `Setting the Graceful Server Shutdown <https://docs.sqream.com/en/v2022.1.1/configuration_guides/graceful_shutdown.html>`_ -* `Enabling Modification of R&D Flags <https://docs.sqream.com/en/v2022.1.1/configuration_guides/developer_mode.html>`_ -* `Checking for Post-Production CUDA Errors <https://docs.sqream.com/en/v2022.1.1/configuration_guides/enable_device_debug_messages.html>`_ -* `Enabling Modification of clientLogger_debug File <https://docs.sqream.com/en/v2022.1.1/configuration_guides/enable_log_debug.html>`_ -* `Activating the NVidia Profiler Markers <https://docs.sqream.com/en/v2022.1.1/configuration_guides/enable_nv_prof_markers.html>`_ -* `Appending String at End of Log Lines <https://docs.sqream.com/en/v2022.1.1/configuration_guides/end_log_message.html>`_ -* `Monitoring and Printing Pinned Allocation Reports <https://docs.sqream.com/en/v2022.1.1/configuration_guides/gather_mem_stat.html>`_ -* `Increasing Chunk Size to Reduce Query Speed <https://docs.sqream.com/en/v2022.1.1/configuration_guides/increase_chunk_size_before_reduce.html>`_ -* `Adding Rechunker before Expensing Chunk Producer <https://docs.sqream.com/en/v2022.1.1/configuration_guides/increase_mem_factors.html>`_ -* `Setting the Buffer Size <https://docs.sqream.com/en/v2022.1.1/configuration_guides/level_db_write_buffer_size.html>`_ -* `Setting Memory Used to Abort Server <https://docs.sqream.com/en/v2022.1.1/configuration_guides/memory_reset_trigger_mb.html>`_ -* `Splitting Large Reads for Concurrent Execution <https://docs.sqream.com/en/v2022.1.1/configuration_guides/mt_read.html>`_ -* `Setting Worker Amount to Handle Concurrent Reads <https://docs.sqream.com/en/v2022.1.1/configuration_guides/mt_read_workers.html>`_ -* `Setting Implicit Casts in ORC Files <https://docs.sqream.com/en/v2022.1.1/configuration_guides/orc_implicit_casts.html>`_ -* `Setting Timeout Limit for Locking Objects before Executing Statements <https://docs.sqream.com/en/v2022.1.1/configuration_guides/statement_lock_timeout.html>`_ -* `Interpreting Decimal Literals as Double Instead of Numeric <https://docs.sqream.com/en/v2022.1.1/configuration_guides/use_legacy_decimal_literals.html>`_ +* :ref:`Setting Bin Size<bin_sizes>` +* :ref:`Setting CUDA Memory<check_cuda_memory>` +* :ref:`Limiting Runtime to Utility Functions<compiler_gets_only_ufs>` +* :ref:`Enabling High Bin Control Granularity<copy_to_restrict_utf8>` +* :ref:`Reducing CPU Hashtable Sizes<cpu_reduce_hashtable_size>` +* :ref:`Setting Chunk Size for Copying from CPU to GPU<cuda_mem_cpy_max_size_bytes>` +* :ref:`Indicating GPU Synchronicity<cuda_mem_cpy_synchronous>` +* :ref:`Setting the Graceful Server Shutdown<graceful_shutdown>` +* :ref:`Enabling Modification of R&D Flags<developer_mode>` +* :ref:`Checking for Post-Production CUDA Errors<enable_device_debug_messages>` +* :ref:`Enabling Modification of clientLogger_debug File<enable_log_debug>` +* :ref:`Activating the NVidia Profiler Markers<enable_nv_prof_markers>` +* :ref:`Appending String at End of Log Lines<end_log_message>` +* :ref:`Monitoring and Printing Pinned Allocation Reports<gather_mem_stat>` +* :ref:`Increasing Chunk Size to Reduce Query Speed<increase_chunk_size_before_reduce>` +* :ref:`Adding Rechunker before Expensing Chunk Producer<increase_mem_factors>` +* :ref:`Setting the Buffer Size<level_db_write_buffer_size>` +* :ref:`Setting Memory Used to Abort Server<memory_reset_trigger_mb>` +* :ref:`Splitting Large Reads for Concurrent Execution<mt_read>` +* :ref:`Setting Worker Amount to Handle Concurrent Reads<mt_read_workers>` +* :ref:`Setting Implicit Casts in ORC Files<orc_implicit_casts>` +* :ref:`Setting Timeout Limit for Locking Objects before Executing Statements<statement_lock_timeout>` +* :ref:`Interpreting Decimal Literals as Double Instead of Numeric<use_legacy_decimal_literals>` +* :ref:`Using Legacy String Literals<use_legacy_string_literals>` * :ref:`Blocking New VARCHAR Objects<block_new_varchar_objects>` -* `VARCHAR Identifiers <https://docs.sqream.com/en/v2022.1.1/configuration_guides/varchar_identifiers.html>`_ From 38c40f0d43e3c21fb65449b0998bbb258cff017b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 13:32:46 +0200 Subject: [PATCH 0402/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 3f9e9d578..5ca988f19 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -175,10 +175,7 @@ The following is an example of the syntax used to create a table with an identit country TEXT(30) DEFAULT 'Unknown' NOT NULL ); -.. note:: - * Identity columns are supported on ``BIGINT`` columns. - - * Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. +.. note:: Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. Creating a Table from a SELECT Query ----------------------------------------- From b7e2874df711b871058ed78ef6bd273bcda376dd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 14:21:46 +0200 Subject: [PATCH 0403/1892] CEIL --- configuration_guides/current_method_flag_types.rst | 2 +- .../sql/sql_functions/scalar_functions/numeric/ceiling.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index 7908e65d0..93e82e79b 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -13,7 +13,7 @@ The lowest level is Regular, which means that modifying values of Regular flags To see each flag's default value, see one of the following: -* The **Default Value** column in the :ref:`All Configurations<all_configurations>` section. +* The **Default Value** column in the :ref:`All Configurations<current_method_all_configurations>` section. :: diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index 39a63ddab..314c33c02 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -``CEIL`` always returns a ``double`` floating point number. +``CEILING`` and ``CEIL`` always return a ``double`` floating point number. Notes From 5e0e968d9b6f9193468410fd41ab75201f7e8956 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 15 Jan 2023 15:34:18 +0200 Subject: [PATCH 0404/1892] Update char_length.rst --- .../sql_functions/scalar_functions/string/char_length.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index 47d517975..79bbdcdbc 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -1,7 +1,7 @@ .. _char_length: ************************** -CHAR_LENGTH +CHARACTER_LENGTH / CHAR_LENGTH ************************** Calculates the number of characters in a string. @@ -16,6 +16,7 @@ Syntax .. code-block:: postgres CHAR_LEN( text_expr ) --> INT + CHARACTER_LEN( text_expr ) --> INT Arguments ============ @@ -32,7 +33,7 @@ Arguments Returns ============ -Returns an integer containing the number of characters in the string. +Return an integer containing the number of characters in the string. Notes ======= @@ -59,7 +60,7 @@ Length in characters and bytes of strings ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes. -Unlike :ref:`len`, ``CHAR_LENGTH`` preserves the trailing whitespaces. +Unlike :ref:`len`, ``CHARACTER_LENGTH`` and ``CHAR_LENGTH`` preserve the trailing white spaces. .. code-block:: psql From f6a981f95573c5205d9100aae56ee82d7b275b28 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 16 Jan 2023 13:31:56 +0200 Subject: [PATCH 0405/1892] Update spark.rst --- .../client_platforms/spark.rst | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index 823fa5728..6e972a830 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -32,23 +32,22 @@ To use Spark with SQream, you must have the following installed: JDBC ~~~~ -If JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. +If JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for guidance in registring and configuring. -SQream-Spark Connector +Connecting Spark to SQream ~~~~~~~~~~~~~~~~~~~ -The SQream-Spark Connector enables inserting DataFrames into SQream tables and export tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. +The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. - -The SQream-Spark Connector command for Spark Shell: +1. In the Spark Shell, run: .. code-block:: postgres ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} -An example for the SQream-Spark Connector command: +Example: .. code-block:: postgres @@ -72,16 +71,14 @@ The following Spark connection properties are supported by SQream: - Description * - ``url`` - - - The JDBC URL of the form ``jdbc:subprotocol:subname`` to connect to. The source-specific connection properties may be specified in the URL. e.g., ``jdbc:Sqream://localhost/test?user=fred&password=secret``. - * - ``dbtable`` - - - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + The JDBC URL ``jdbc:subprotocol:subname`` establishes the connection between SQream and Spark. Source-specific connection properties may be specified in the URL, such as ``user`` and ``password``, e.g. ``jdbc:Sqream://localhost/test?user=fred&password=secret``. * - ``dbtable`` - - - The JDBC table that should be read from or written into. Note that when using it in the read path anything that is valid in a ``FROM`` clause of a SQL query can be used. For example, instead of a full table you could also use a subquery in parentheses. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + - A JDBC table to read from or write to. When reading from a ``dbtable``, anything that is valid in an SQL ``FROM`` clause may be used. For example, you may use a subquery in parentheses instead of querying a full table. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. * - ``query`` - - - A query that will be used to read data into Spark. The specified query will be parenthesized and used as a subquery in the ``FROM`` clause. Spark will also assign an alias to the subquery clause. As an example, spark will issue a query of the following form to the JDBC Source. ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. Restrictions while using this option: 1. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. 2. It is not allowed to specify ``query`` and ``partitionColumn`` options at the same time. When specifying ``partitionColumn`` option is required, the subquery can be specified using ``dbtable`` option instead and partition columns can be qualified using the subquery alias provided as part of ``dbtable``. Example: ``spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load()`` + - The ``query`` property in Spark is used to read data into the program by specifying a query. This query is used as a subquery in the ``FROM`` clause and Spark will assign an alias to the subquery. For example, when using a JDBC Source, Spark will issue a query in the format of ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. It's important to note that it is not allowed to use both the ``dbtable`` and ``query`` options at the same time, and the ``query`` option cannot be used with the ``partitionColumn`` option. If the ``partitionColumn`` option is needed, it must be specified using the ``dbtable`` option and qualified using the subquery alias provided in ``dbtable``. An example of how to use this option would be: spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load() * - ``driver`` - - The class name of the JDBC driver to use to connect to this URL. From c10da56b17451a8f1d6312caf6b2e760ee7ef08b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Jan 2023 14:57:14 +0200 Subject: [PATCH 0406/1892] flags --- configuration_guides/current_method_configuration_levels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index cb55893b3..ad5143def 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -19,7 +19,7 @@ Worker-Based Configuration -------------- Worker-based configuration lets you modify individual workers using a worker configuration file. Worker-based configuration modifications are persistent. -For more information on making configurations from the worker configuration file, see :ref:`current_method_modification_methods`. +For more information on making configurations from the worker configuration file, see :ref:`previous_configuration_method`. Session-Based Configuration -------------- From 68761dca9011cc2e37cfc9ac6de4bf851bb2a35f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:42:36 +0200 Subject: [PATCH 0407/1892] Update spark.rst --- .../client_platforms/spark.rst | 64 +++++++++---------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst index 6e972a830..f10191b70 100644 --- a/connecting_to_sqream/client_platforms/spark.rst +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -71,8 +71,7 @@ The following Spark connection properties are supported by SQream: - Description * - ``url`` - - - - The JDBC URL ``jdbc:subprotocol:subname`` establishes the connection between SQream and Spark. Source-specific connection properties may be specified in the URL, such as ``user`` and ``password``, e.g. ``jdbc:Sqream://localhost/test?user=fred&password=secret``. + - The JDBC URL ``jdbc:subprotocol:subname`` establishes the connection between SQream and Spark. Source-specific connection properties may be specified in the URL, such as ``user`` and ``password``, e.g. ``jdbc:Sqream://localhost/test?user=fred&password=secret``. * - ``dbtable`` - - A JDBC table to read from or write to. When reading from a ``dbtable``, anything that is valid in an SQL ``FROM`` clause may be used. For example, you may use a subquery in parentheses instead of querying a full table. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. @@ -257,36 +256,33 @@ JAVA .. code-block:: postgres - // Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods - // Loading data from a JDBC source - Dataset<Row> jdbcDF = spark.read() - .format("jdbc") - .option("url", "jdbc:Sqream:dbserver") - .option("dbtable", "schema.tablename") - .option("user", "username") - .option("password", "password") - .load(); - - Properties connectionProperties = new Properties(); - connectionProperties.put("user", "username"); - connectionProperties.put("password", "password"); - Dataset<Row> jdbcDF2 = spark.read() - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); - - // Saving data to a JDBC source - jdbcDF.write() - .format("jdbc") - .option("url", "jdbc:Sqream:dbserver") - .option("dbtable", "schema.tablename") - .option("user", "username") - .option("password", "password") - .save(); - - jdbcDF2.write() - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); - - // Specifying create table column data types on write - jdbcDF.write() - .option("createTableColumnTypes", "name TEXT, comments TEXT") - .jdbc("jdbc:Sqream:dbserver", "schema.tablename", connectionProperties); + import com.sqream.driver.SqreamSession; + import org.apache.spark.sql.Dataset; + import org.apache.spark.sql.Row; + + import java.util.HashMap; + + public class main { + public static void main(String[] args) { + HashMap<String, String> config = new HashMap<>(); + //spark configuration + //optional configuration here: https://spark.apache.org/docs/latest/configuration.html + config.put("spark.master", "local"); + SqreamSession sqreamSession = SqreamSession.getSession(config); + + //spark properties + //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html + HashMap<String, String> props = new HashMap<>(); + + props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); + props.put("dbtable", "test"); + + /*Read from sqream table*/ + Dataset<Row> dataFrame = sqreamSession.read(props); + + /*Added to sqream table*/ + sqreamSession.write(dataFrame, props); + + } + } From fe5e9c2281fb33f9497e0194fe7a1b6459b9ebfe Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Jan 2023 16:21:28 +0200 Subject: [PATCH 0408/1892] Update ldap.rst --- configuration_guides/ldap.rst | 248 +++++++++++++++++++++++++++++++--- 1 file changed, 230 insertions(+), 18 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 56332eea1..657a5c6cd 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,7 +5,7 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service widely use with Microsoft Active Directory. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. +Lightweight Directory Access Protocol (LDAP) is an authentication management service widely used with Microsoft Active Directory. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. Prior to integrating SQream with LDAP, two preconditions must be considered: @@ -15,11 +15,22 @@ Prior to integrating SQream with LDAP, two preconditions must be considered: .. contents:: In this topic: :local: +Before You Begin +================ + +Enable self-signed certificates for OpenLDAP by adding the following line to the ``ldap.conf`` configuration file: + +.. code-block:: postgres + + ``TLS_REQCERT allow`` + Configuring SQream roles ======================== +Follow this procedure if you already have LDAP configured for your environment. + **Procedure** 1. Create a new role: @@ -40,16 +51,39 @@ Configuring SQream roles GRANT CONNECT ON DATABASE <my_database> TO <new_role>; - -You may also wish to :ref:`rename SQream roles<rename_role>`. +You may also wish to :ref:`rename SQream roles<rename_role>` so that they are consistent with existing LDAP user names. Configuring LDAP Authentication =============================== +.. contents:: In this topic: + :local: + +Configuration Methods +--------------------- + +To configure LDAP authentication for SQream, you may choose one of the following configuration methods: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Method + - Description + * - Basic method + - Use a given username in attempt to bind it to a distinguished name. To simplify usage, the ``ldapPrefix`` and ``ldapSuffix`` flags are used to construct a distinguished name built by ``ldapPrefix``, ``username``, or ``ldapSuffix``. + * - Advanced method + - Bind to the LDAP directory using a fixed username and password, which are set in the flags ``ldapBindDn`` and ``ldapBindDnPassword``. In the case that ``ldapBindDn`` and ``ldapBindDnPassword`` are not set, an anonymous bind will be attempted to the directory. A search will be preformed over the subtree set by ``ldapBaseDn``, by searching for an exact match of the given username in the attribute set in the ``ldapSearchAttribute`` flag. Only a single match is allowed in the search result. Once the user has been found in the search, the server disconnects and re-binds to the directory as this user, using the password specified by the client. Follow this procedure if you are configuring LDAP authentication for SQream. + + + +Basic Method +------------ + Flag Attributes ---------------- -To enable LDAP Authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: +~~~~~~~~~~~~~~~ +To enable LDAP Authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: .. list-table:: :widths: auto @@ -59,47 +93,225 @@ To enable LDAP Authentication, configure the following **cluster** flag attribut - Description * - ``authenticationMethod`` - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. - * - ``ldapDomain`` - - Configure users` domain. * - ``ldapIpAddress`` - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. -.. comment:: + * - ``ldapPort`` + - LDAP server port number. + * - ``ldapAdvancedMode`` + - Configure either basic or advanced authentication method. Default is ``false``. + * - ``ldapPrefix`` + - String to prepend to the user name when forming the DN to bind as, when doing simple bind authentication. + * - ``ldapSuffix`` + - String to append to the user name when forming the DN to bind as, when doing simple bind authentication. + -Enabling LDAP Authentication -------------------------------- +Basic Method Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~ -Roles with admin privileges or higher may enable LDAP Authentication. +Only roles with admin privileges and higher may enable LDAP Authentication. **Procedure** -1. Set the ``ldapIpAddress`` attribute: +1. Set the ``authenticationMethod`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET authenticationMethod = 'ldap'; + +2. Set the ``ldapIpAddress`` attribute: .. code-block:: postgres - ALTER SYSTEM SET ldapIpAddress = '<ldaps://192.168.10.20>'; + ALTER SYSTEM SET ldapIpAddress = '<ldaps://...>'; + +3. Set the ``ldapPrefix`` attribute: + +.. code-block:: postgres -2. Set the ``ldapDomain`` attribute: + ALTER SYSTEM SET ldapPrefix = '<DN_binding_string_prefix>='; + +4. Set the ``ldapSuffix`` attribute: .. code-block:: postgres - ALTER SYSTEM SET ldapDomain = '<@sqream.loc>'; + ALTER SYSTEM SET ldapSuffix = '<DN_binding_string_suffix>'; -3. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: +5. To set the ``ldapPort`` attribute (Optional), run: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapPort = <port_number> + +6. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapConnTimeoutSec = <15>; -4. Set the ``authenticationMethod`` attribute: +7. Restart all sqreamd servers. + +Example +~~~~~~~ + +After completing the setup above we can try to bind to a user by a distinguished name. For example if the DN of the user is: + +.. code-block:: postgres + + CN=ElonMusk,OU=Sqream Users,DC=sqream,DC=loc + +We could set the ldapPrefix and ldapSuffix to + +.. code-block:: postgres + + ALTER SYSTEM SET ldapPrefix = 'CN='; + + ALTER SYSTEM SET ldapSuffix = ',OU=Sqream Users,DC=sqream,DC=loc'; + +Logging in will be possible using the username ElonMusk using sqream client + +.. code-block:: postgres + + ./sqream sql --username=ElonMusk --password=sqream123 --databasename=master --port=636 + +Advanced Method +--------------- + +Flag Attributes +~~~~~~~~~~~~~~~ + +To enable LDAP Authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Attribute + - Description + * - ``authenticationMethod`` + - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + * - ``ldapIpAddress`` + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + * - ``ldapConnTimeoutSec`` + - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. + * - ``ldapPort`` + - LDAP server port number. + * - ``ldapAdvancedMode`` + - Configure either basic or advanced authentication method. Default is ``false``. + * - ``ldapBaseDn`` + - Root DN to begin the search for the user in, when doing advanced authentication. + * - ``ldapBindDn`` + - DN of user to bind to the directory with to perform the search when doing advanced authentication. + * - ``ldapBindDnPassword`` + - Password for user to bind to the directory with to perform the search when doing advanced authentication. + * - ``ldapSearchAttribute`` + - Attribute to match against the user name in the search when doing advanced authentication. If no attribute is specified, the ``uid`` attribute will be used. + +Advanced Method Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Only roles with admin privileges and higher may enable LDAP Authentication. + +**Procedure** + +1. Set the ``authenticationMethod`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET authenticationMethod = 'ldap'; + +2. Set the ``ldapAdvancedMode`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapAdvancedMode = true; + +3. Set the ``ldapIpAddress`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapIpAddress = '<ldaps://<IpAddress>'; + +4. Set the ``ldapBindDn`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapBindDn = <binding_user_DN>; + +5. Set the ``ldapBindDnPassword`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapBindDnPassword = '<binding_user_password>'; + +6. Set the ``ldapBaseDn`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapBaseDn = '<search_root_DN>'; + +7. Set the ``ldapSearchAttribute`` attribute: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapSearchAttribute = '<search_attribute>'; + +8. To set the ``ldapPort`` attribute (Optional), run: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapPort = <port_number> + +9. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapConnTimeoutSec = <15>; + +10. Restart all sqreamd servers. + +Example +~~~~~~~ + +After completing the setup above we can try to bind to a user by locating it by one of its unique attributes. + +User DN = + +.. code-block:: postgres + + CN=ElonMusk,OU=Sqream Users,DC=sqream,DC=loc + +User has value of elonm for attribute ``sAMAccountName``. + .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; + + ALTER SYSTEM SET ldapAdvancedMode = true; + + ALTER SYSTEM SET ldapIpAddress = 'ldaps://192.168.10.20'; + + ALTER SYSTEM SET ldapPort = 636 + + ALTER SYSTEM SET ldapBindDn = 'CN=LDAP admin,OU=network admin,DC=sqream,DC=loc'; -5. Restart all sqreamd servers. + ALTER SYSTEM SET ldapBindDnPassword = 'sqream123'; + ALTER SYSTEM SET ldapBaseDn = 'OU=Sqream Users,DC=sqream,DC=loc'; + + ALTER SYSTEM SET ldapSearchAttribute = 'sAMAccountName'; + + ALTER SYSTEM SET ldapConnTimeoutSec = 30; + + +Logging in will be possible using the username elonm using sqream client + +.. code-block:: postgres + + ./sqream sql --username=elonm --password=<elonm_password> --databasename=master --port=636 + Disabling LDAP Authentication ----------------------------- From 27c5c35bb2469cc5c155e9b272c0337e39c9c581 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 22 Jan 2023 12:05:19 +0200 Subject: [PATCH 0409/1892] Kafka --- _static/images/kafka_flow.png | Bin 0 -> 167138 bytes .../client_drivers/kafka/index.rst | 107 +++--------------- 2 files changed, 13 insertions(+), 94 deletions(-) create mode 100644 _static/images/kafka_flow.png diff --git a/_static/images/kafka_flow.png b/_static/images/kafka_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..c5bfc0ff2554e72db941134d9635480663ff610f GIT binary patch literal 167138 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 literal 0 HcmV?d00001 diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index ee8e3e98c..e4c1e3242 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -12,121 +12,40 @@ If you are using Kafka Apache for distributed streaming and wish to use it with :depth: 1 -Installation and Configuration -============= - -.. contents:: - :local: - :depth: 1 - Before You Begin ----------------- +================ * You must have JAVA 11 installed -* Your network bandwidth must be at least X gigabits per second -* Supported data formats for streaming data are: - * JSON - * CSV - * Avro +* You must have `JDBC <java_jdbc>`_ installed +* Your network bandwidth must be at least 100 mega per second +* Supported data formats for streamed data is JSON -Kafka Producer --------------- - -The Kafka Producer requires both the Kafka producer and Zookeeper processes to be running in order to create new topics, read data from existing topics, and load data from files. If Zookeeper is not running, the Kafka producer will not start. +Installation and Configuration +============================== .. contents:: :local: :depth: 1 -Kafka Producer Installation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Kafka Producer is installed on the 192.168.0.125 server. - -Kafka Producer Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Running Zookeeper: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - bin/zookeeper-server-start.sh -daemon config/zookeeper.properties - -Running Kafka producer: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - bin/kafka-server-start.sh -daemon config/server.properties - -Verifying that both Zookeeper and Kafka producer are running: - -1. Log in to your machine. - -2. Run the following string: - - .. code-block:: postgres - - [sqream@metadata-0-125 ~]$ ps -ef |grep java - -The following is an example of an output indicating that both processes are running: - - .. code-block:: postgres - - <JAVA_HOME>/bin/java... org.apache.zookeeper.server.quorum.QuorumPeerMain config/zookeeper.properties - <JAVA_HOME>/bin/java... kafka.Kafka config/server.properties - -Creating a new topic: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - bin/kafka-topics.sh --create --bootstrap-server localhost:2181 --replication-factor 1 --partitions 1 --topic <topic name> - -Reading data from a topic: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - ./kafka-console-consumer.sh --topic <topic name> --from-beginning --bootstrap-server localhost:9092 - -Loading data from a file: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - ./kafka-console-producer.sh --bootstrap-server localhost:9092 --topic <topic name> < <full path to file> - -Terminating the Kafka Producer requires that both the Kafka Producer and Zookeeper be terminated. To avoid data inconsistency and potential data loss, terminate the Kafka Producer before terminating the Zookeeper. - -Terminating the Kafka Producer: - -.. code-block:: postgres - - cd /home/sqream/kafka_2.12-3.2.1/ - bin/kafka-server-stop.sh - -SQream Consumer +Sink Connector --------------- .. contents:: :local: :depth: 1 -The SQream Consumer reads Kafka topics and writes messages into text files in either CSV, JSON, or Avro format. The files are created with the extension ``.tmp`` and stored in the specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file. When the specified number of records is reached, the SQream Consumer closes the file, renames it to the ``sqream.fileExtension``, and then creates a new file. +The Sink Connector reads Kafka topics and writes messages into text files in either CSV, JSON, or Avro format. The files are created with the extension ``.tmp`` and stored in the specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file. When the specified number of records is reached, the Sink Connector closes the file, renames it to the ``sqream.fileExtension``, and then creates a new file. SQream tables must be created according to the columns configured in ``csvorder``. -SQream Consumer Installation +.. figure:: /_static/images/kafka_flow.png + +Sink Connector Installation ~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The SQream Consumer version is located under /home/sqream/kafkaconnect1, machine IP 192.168.0.102 -Credentials: -user = sqream -pass = sqprj2021$ -SQream Consumer Configuration + +Sink Connector Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following parameters require configuration. From b561e7a775f616e35a17e6522069b66d68ea5775 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 22 Jan 2023 13:20:38 +0200 Subject: [PATCH 0410/1892] :ref:`healer_detection_frequency_seconds` --- .../healer_detection_frequency_seconds.rst | 14 ++++++++ ...ealer_max_statement_inactivity_seconds.rst | 2 +- configuration_guides/is_healer_on.rst | 6 ++-- feature_guides/query_healer.rst | 34 ++++++++++++------- releases/2021.2.1.24.rst | 6 +++- 5 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 configuration_guides/healer_detection_frequency_seconds.rst diff --git a/configuration_guides/healer_detection_frequency_seconds.rst b/configuration_guides/healer_detection_frequency_seconds.rst new file mode 100644 index 000000000..9e7805852 --- /dev/null +++ b/configuration_guides/healer_detection_frequency_seconds.rst @@ -0,0 +1,14 @@ +.. _healer_detection_frequency_seconds: + +************************* +Healer Detection Frequency Seconds +************************* +The ``healerDetectionFrequencySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + +The following describes the ``healerDetectionFrequencySeconds`` worker level flag: + +* **Data type** - size_t +* **Default value** - ``1`` +* **Allowed values** - 1-3600 + +For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/configuration_guides/healer_max_statement_inactivity_seconds.rst b/configuration_guides/healer_max_statement_inactivity_seconds.rst index 0de4e68e6..142e76eb7 100644 --- a/configuration_guides/healer_max_statement_inactivity_seconds.rst +++ b/configuration_guides/healer_max_statement_inactivity_seconds.rst @@ -1,7 +1,7 @@ .. _healer_max_statement_inactivity_seconds: ************************* -Configuring the Query Healer +Max Statement Inactivity Seconds ************************* The ``maxStatementInactivitySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst index 8b90654ec..1eb0e6384 100644 --- a/configuration_guides/is_healer_on.rst +++ b/configuration_guides/is_healer_on.rst @@ -1,9 +1,9 @@ .. _is_healer_on: ************************* -Enabling the Query Healer +Is Healer On ************************* -The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. +The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``maxStatementInactivitySeconds`` flag setting. The following describes the ``is_healer_on`` flag: @@ -11,4 +11,4 @@ The following describes the ``is_healer_on`` flag: * **Default value** - ``true`` * **Allowed values** - ``true``, ``false`` -For related flags, see :ref:`healer_max_inactivity_hours`. \ No newline at end of file +For related flags, see :ref:`healer_max_statement_inactivity_seconds`. \ No newline at end of file diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 4c87ec0a9..257de9e32 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -11,7 +11,27 @@ The **Query Healer** page describes the following: Overview ---------- -The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding the ``maxStatementInactivitySeconds`` worker level flag setting. The default setting of the ``maxStatementInactivitySeconds`` is five hours. The ``maxStatementInactivitySeconds`` log frequency is calculated as 5% of the flag setting. When set to five hours (the default setting), the Query Healer triggers an examination every 15 minutes. +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding a defined time period. + +Configuration +------------- +The following **Administration Worker** flags are required to configure the Query Healer: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag + - Description + * - ``is_healer_on`` + - The :ref:`is_healer_on` enables and disables the Query Healer. + * - ``maxStatementInactivitySeconds`` + - The :ref:`healer_max_statement_inactivity_seconds` worker level flag defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The default setting is five hours. + * - ``healerDetectionFrequencySeconds`` + - The :ref:`healer_detection_frequency_seconds` worker level flag triggers the healer to examine the progress of running statements. The default setting is one hour. + +Query Log +--------------- The following is an example of a log record for a query stuck in the query detection phase for more than five hours: @@ -45,14 +65,4 @@ For more information, see the following: :: -* Configuring the :ref:`shutdown_server` flag. - -Configuring the Healer ------------------- -The following **Administration Worker** flags are required to configure the Query Healer: - - * :ref:`is_healer_on` - Enables the Query Healer. - - :: - - * :ref:`healer_max_statement_inactivity_seconds` - Defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. \ No newline at end of file +* Configuring the :ref:`shutdown_server` flag. \ No newline at end of file diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index f1ab492dc..2016dd564 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -65,7 +65,11 @@ The following worker level configuration flags were added: :: - * :ref:`healer_max_statement_inactivity_seconds:` + * :ref:`healer_max_statement_inactivity_seconds` + + :: + + * :ref:`healer_detection_frequency_seconds` Naming Changes ------- From cd600b4caffce534b288d15b3dfa67f06b1a5f8d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 22 Jan 2023 15:38:04 +0200 Subject: [PATCH 0411/1892] Update ldap.rst --- configuration_guides/ldap.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 657a5c6cd..b06081bb7 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -72,9 +72,9 @@ To configure LDAP authentication for SQream, you may choose one of the following * - Method - Description * - Basic method - - Use a given username in attempt to bind it to a distinguished name. To simplify usage, the ``ldapPrefix`` and ``ldapSuffix`` flags are used to construct a distinguished name built by ``ldapPrefix``, ``username``, or ``ldapSuffix``. + - A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given the same level of access to the server. * - Advanced method - - Bind to the LDAP directory using a fixed username and password, which are set in the flags ``ldapBindDn`` and ``ldapBindDnPassword``. In the case that ``ldapBindDn`` and ``ldapBindDnPassword`` are not set, an anonymous bind will be attempted to the directory. A search will be preformed over the subtree set by ``ldapBaseDn``, by searching for an exact match of the given username in the attribute set in the ``ldapSearchAttribute`` flag. Only a single match is allowed in the search result. Once the user has been found in the search, the server disconnects and re-binds to the directory as this user, using the password specified by the client. Follow this procedure if you are configuring LDAP authentication for SQream. + - This approach allows for compartmentalization, which means that users can be grouped into categories, and each category can be assigned different levels of access to the LDAP server. This allows administrators to control access to different parts of the system. From 4ad3547513e37e9f23d21b73c3e0cc572bc77248 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 22 Jan 2023 15:53:19 +0200 Subject: [PATCH 0412/1892] Update ldap.rst --- configuration_guides/ldap.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index b06081bb7..c312b6986 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -173,7 +173,7 @@ Logging in will be possible using the username ElonMusk using sqream client .. code-block:: postgres - ./sqream sql --username=ElonMusk --password=sqream123 --databasename=master --port=636 + ./sqream sql --username=ElonMusk --password=sqream123 --databasename=master --port=5000 Advanced Method --------------- @@ -293,7 +293,7 @@ User has value of elonm for attribute ``sAMAccountName``. ALTER SYSTEM SET ldapIpAddress = 'ldaps://192.168.10.20'; - ALTER SYSTEM SET ldapPort = 636 + ALTER SYSTEM SET ldapPort = 5000 ALTER SYSTEM SET ldapBindDn = 'CN=LDAP admin,OU=network admin,DC=sqream,DC=loc'; @@ -310,7 +310,7 @@ Logging in will be possible using the username elonm using sqream client .. code-block:: postgres - ./sqream sql --username=elonm --password=<elonm_password> --databasename=master --port=636 + ./sqream sql --username=elonm --password=<elonm_password> --databasename=master --port=5000 Disabling LDAP Authentication From fb4c29555495a25ad21e4ec3ac050dca1377631a Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 23 Jan 2023 12:59:31 +0200 Subject: [PATCH 0413/1892] Update ldap.rst --- configuration_guides/ldap.rst | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index c312b6986..9aa8b3d7f 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -5,12 +5,13 @@ Configuring LDAP authentication ************************************* -Lightweight Directory Access Protocol (LDAP) is an authentication management service widely used with Microsoft Active Directory. Once it has been configured to authenticate SQream roles, all existing and newly added roles will be required to be authenticated by an LDAP server, with the exception of the initial system deployment ``sqream`` role, which is granted full control permissions upon deployment. +Lightweight Directory Access Protocol (LDAP) is an authentication management service used with Microsoft Active Directory and other directory services. Once LDAP authentication has been configured for SQream, authorization for all existing and newly added roles must be handled by the LDAP server, except for the initial system deployment ``sqream`` role, which was immediately given full control permissions when SQream was initially deployed. -Prior to integrating SQream with LDAP, two preconditions must be considered: +Before integrating SQream with LDAP consider the following: - * If SQream DB is being installed within an LDAP-integrated environment, it is best practice to ensure that the newly created SQream role names are consistent with existing LDAP user names. - * If LDAP is being integrated with a SQream environment, it is best practice to ensure that the newly created LDAP user names are consistent with existing SQream role names. Note that after LDAP has been successfully integrated, SQream roles that were mistakenly not configured or have conflicting names with LDAP will be recreated in SQream as roles without the ability to log in, without permissions, and without a default schema. +* If SQream DB is being installed within an environment where LDAP is already configured, it is best practice to ensure that the newly created SQream role names are consistent with existing LDAP user names. + +* If SQream DB has been installed and LDAP has not yet been integrated with SQream, it is best practice to ensure that the newly created LDAP user names are consistent with existing SQream role names. Previously existing SQream roles that were mistakenly not configured in LDAP or that have names which are different than in LDAP, will be recreated in SQream as roles that cannot log in, have no permissions, and have no default schema. .. contents:: In this topic: :local: @@ -39,7 +40,7 @@ Follow this procedure if you already have LDAP configured for your environment. CREATE ROLE <new_role>; -2. Grant new role login permission: +2. Grant the new role login permission: .. code-block:: postgres @@ -82,8 +83,13 @@ Basic Method ------------ Flag Attributes +<<<<<<< Updated upstream ~~~~~~~~~~~~~~~ -To enable LDAP Authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +To enable LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +======= +--------------- +To enable LDAP authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: +>>>>>>> Stashed changes .. list-table:: :widths: auto From fa2cfbfbabbb93ed8b67af33bb4009fe6fbe936a Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 23 Jan 2023 13:16:47 +0200 Subject: [PATCH 0414/1892] Update ldap.rst --- configuration_guides/ldap.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 9aa8b3d7f..ddbeae199 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -73,9 +73,9 @@ To configure LDAP authentication for SQream, you may choose one of the following * - Method - Description * - Basic method - - A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given the same level of access to the server. + - A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given access to SQream. * - Advanced method - - This approach allows for compartmentalization, which means that users can be grouped into categories, and each category can be assigned different levels of access to the LDAP server. This allows administrators to control access to different parts of the system. + - This approach allows for compartmentalization, which means that users can be grouped into categories, and each category can be assigned or denied access to SQream. This allows administrators to control access to SQream. @@ -83,13 +83,9 @@ Basic Method ------------ Flag Attributes -<<<<<<< Updated upstream ~~~~~~~~~~~~~~~ + To enable LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: -======= ---------------- -To enable LDAP authentication, configure the following **cluster** flag attributes using the ``ALERT SYSTEM SET`` command: ->>>>>>> Stashed changes .. list-table:: :widths: auto From 1591d73c519f2f09d6283999ee62a2c237701ada Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Mon, 23 Jan 2023 14:04:14 +0200 Subject: [PATCH 0415/1892] Update ldap.rst --- configuration_guides/ldap.rst | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index ddbeae199..ec16f9c69 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -85,7 +85,7 @@ Basic Method Flag Attributes ~~~~~~~~~~~~~~~ -To enable LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +To enable basic LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: .. list-table:: :widths: auto @@ -94,17 +94,17 @@ To enable LDAP authentication, configure the following **Cluster** flag attribut * - Attribute - Description * - ``authenticationMethod`` - - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. * - ``ldapIpAddress`` - - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` - - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. + - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds. * - ``ldapPort`` - LDAP server port number. * - ``ldapAdvancedMode`` - - Configure either basic or advanced authentication method. Default is ``false``. + - Configure either basic or advanced authentication method. Default = ``false``. * - ``ldapPrefix`` - - String to prepend to the user name when forming the DN to bind as, when doing simple bind authentication. + - String to prefix to the user name when forming the DN to bind as, when doing simple bind authentication. * - ``ldapSuffix`` - String to append to the user name when forming the DN to bind as, when doing simple bind authentication. @@ -112,7 +112,7 @@ To enable LDAP authentication, configure the following **Cluster** flag attribut Basic Method Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Only roles with admin privileges and higher may enable LDAP Authentication. +Only roles with admin privileges or higher may enable LDAP Authentication. **Procedure** @@ -157,7 +157,7 @@ Only roles with admin privileges and higher may enable LDAP Authentication. Example ~~~~~~~ -After completing the setup above we can try to bind to a user by a distinguished name. For example if the DN of the user is: +After completing the setup above, we can try to bind to a user by a distinguished name. For example, if the DN of the user is: .. code-block:: postgres @@ -183,7 +183,7 @@ Advanced Method Flag Attributes ~~~~~~~~~~~~~~~ -To enable LDAP Authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +To enable advanced LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: .. list-table:: :widths: auto @@ -192,23 +192,23 @@ To enable LDAP Authentication, configure the following **Cluster** flag attribut * - Attribute - Description * - ``authenticationMethod`` - - Configure an authentication method. Attribute may be set to either ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. * - ``ldapIpAddress`` - - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol. Out of the ``ldap`` and ``ldaps``, we recommend to use the encrypted ``ldaps`` protocol. + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol. * - ``ldapConnTimeoutSec`` - - Configure the LDAP connection timeout threshold (seconds). The default is 30 seconds. + - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds. * - ``ldapPort`` - LDAP server port number. * - ``ldapAdvancedMode`` - - Configure either basic or advanced authentication method. Default is ``false``. + - Set ``ldapAdvancedMode`` = ``true``. * - ``ldapBaseDn`` - Root DN to begin the search for the user in, when doing advanced authentication. * - ``ldapBindDn`` - - DN of user to bind to the directory with to perform the search when doing advanced authentication. + - DN of user with which to bind to the directory to perform the search when doing search + bind authentication. * - ``ldapBindDnPassword`` - - Password for user to bind to the directory with to perform the search when doing advanced authentication. + - Password for user with which to bind to the directory to perform the search when doing search + bind authentication. * - ``ldapSearchAttribute`` - - Attribute to match against the user name in the search when doing advanced authentication. If no attribute is specified, the ``uid`` attribute will be used. + - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used. Advanced Method Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 91ae1721f2f928172f14d82ebef7149454e7a008 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 24 Jan 2023 13:32:21 +0200 Subject: [PATCH 0416/1892] Update compression.rst --- feature_guides/compression.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 74874b980..e6143bc59 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -35,7 +35,7 @@ When loading data, SQream DB automatically decides on the compression schemes fo Compression Methods ------------------------ -In some cases, if SQream finds that the given compression method cannot effectively compress the data, it will return to the default compression type. + The following table shows the supported compression methods: @@ -155,6 +155,8 @@ In other cases, you may want to force SQream to use a specific compression schem ); +However, if SQream finds that the given compression method cannot effectively compress the data, it will return to the default compression type. + Examining Compression Effectiveness -------------------------------------- Queries made on the internal metadata catalog can expose how effective the compression is, as well as what compression schemes were selected. From 988b5f85f7266d5db85ee3f68a9a04a92fc26c46 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 25 Jan 2023 09:51:12 +0200 Subject: [PATCH 0417/1892] Update 4.0.0_index.rst --- releases/4.0.0_index.rst | 57 +++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index 1b962fbdc..c592cf1bd 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -39,33 +39,36 @@ Known Issues Version 4.0.0 resolved Issues ----------------------------- -+---------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+===============+==========================================================================================+ -| SQ-10544 | SQream Studio Worker Panel issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker GPU dependency | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12652 | SQream Studio result panel adjustment | -+---------------+------------------------------------------------------------------------------------------+ ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-10544 | SQream Studio Worker Panel issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12310 | ``DICT`` compression buffer size issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12446 | | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker GPU dependency | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12652 + 12844 | SQream Studio result panel adjustment | ++------------------------+------------------------------------------------------------------------------------------+ + Configuration Changes --------------------- From aa6e2b02af12a0a18d38cb712977d9370b2d9212 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 25 Jan 2023 17:34:50 +0200 Subject: [PATCH 0418/1892] Update index.rst --- .../client_drivers/kafka/index.rst | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index e4c1e3242..63535820e 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -20,6 +20,16 @@ Before You Begin * Your network bandwidth must be at least 100 mega per second * Supported data formats for streamed data is JSON +High Level Workflow +=================== + +1. Install the JDBC Connector. +2. Install kafka_2.12-3.2.1 +3. Run your Kafka Connect API. +4. + + + Installation and Configuration ============================== @@ -30,19 +40,13 @@ Installation and Configuration Sink Connector --------------- -.. contents:: - :local: - :depth: 1 - -The Sink Connector reads Kafka topics and writes messages into text files in either CSV, JSON, or Avro format. The files are created with the extension ``.tmp`` and stored in the specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file. When the specified number of records is reached, the Sink Connector closes the file, renames it to the ``sqream.fileExtension``, and then creates a new file. +The Sink Connector reads JSON format Kafka topics and writes the messages inside each topic into text files. The files are created with the extension ``.tmp`` and stored in a specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file, and when the specified number is reached, the Sink Connector closes the file, renames it to ``sqream.fileExtension``, and then creates a new file. Unlike data streaming, which continuously sends data from the Kafka topic to the database, the Sink Connector only sends the data when the file size reaches a predefined threshold. This means that data will arrive in batches. SQream tables must be created according to the columns configured in ``csvorder``. -.. figure:: /_static/images/kafka_flow.png -Sink Connector Installation -~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. figure:: /_static/images/kafka_flow.png Sink Connector Configuration @@ -116,14 +120,12 @@ SQream Loader SQream Loader Installation ~~~~~~~~~~~~~~~~~~~~~~~~~~ -Sqream loader credentials: -ip machine: 192.168.0.102 -user = sqream -pass = sqprj2021$ + SQream Loader Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Building the SQream Loader: .. code-block:: postgres From aee60e42ade69ef251d679588eb16fe9bd751a3e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 29 Jan 2023 15:14:38 +0200 Subject: [PATCH 0419/1892] -Trino --- .../client_drivers/kafka/index.rst | 90 +++++++---- .../client_platforms/index.rst | 1 - .../client_platforms/trino.rst | 144 ------------------ 3 files changed, 59 insertions(+), 176 deletions(-) delete mode 100644 connecting_to_sqream/client_platforms/trino.rst diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst index 63535820e..983b0b96e 100644 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ b/connecting_to_sqream/client_drivers/kafka/index.rst @@ -33,6 +33,12 @@ High Level Workflow Installation and Configuration ============================== +Before you configure the Kafka Connector, make sure that Kafka and Zookeeper are both running. + +Kafka Connector workflow: + +.. figure:: /_static/images/kafka_flow.png + .. contents:: :local: :depth: 1 @@ -45,12 +51,31 @@ The Sink Connector reads JSON format Kafka topics and writes the messages inside SQream tables must be created according to the columns configured in ``csvorder``. +Sink Connector Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. figure:: /_static/images/kafka_flow.png +Configuration file structure: + .. code-block:: postgres -Sink Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + name=SQReamFileSink + topics=topsqreamtest1 + tasks.max=4 + connector.class=tr.com.entegral.FileSinkConnector + errors.tolerance=all + errors.log.enable=true + errors.log.include.messages=true + value.converter=org.apache.kafka.connect.json.JsonConverter + value.converter.schemas.enable=false + transforms=flatten + transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value + transforms.flatten.delimiter=. + sqream.outputdir=/home/sqream/kafkaconnect/outputs + sqream.batchRecordCount =10 + sqream.fileExtension=csv + sqream.removeNewline =false + sqream.outputType=csv + sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv The following parameters require configuration. @@ -76,31 +101,6 @@ Connection string: vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties -Configuration file structure: - - .. code-block:: postgres - - name=SQReamFileSink - topics=topsqreamtest1 - tasks.max=4 - connector.class=tr.com.entegral.FileSinkConnector - errors.tolerance=all - errors.log.enable=true - errors.log.include.messages=true - value.converter=org.apache.kafka.connect.json.JsonConverter - value.converter.schemas.enable=false - transforms=flatten - transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value - transforms.flatten.delimiter=. - sqream.outputdir=/home/sqream/kafkaconnect/outputs - sqream.batchRecordCount =10 - sqream.fileExtension=csv - sqream.removeNewline =false - sqream.outputType=csv - sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv - - - Running commands: .. code-block:: postgres @@ -110,17 +110,45 @@ Running commands: -SQream Loader +JDBC ------------- +The JDBC connector can be used to ingest data from Kafka, allowing SQream DB to consume the messages directly. This enables efficient and secure data ingestion into SQream DB. + .. contents:: :local: :depth: 1 -SQream Loader Installation -~~~~~~~~~~~~~~~~~~~~~~~~~~ +JDBC Configuration +~~~~~~~~~~~~~~~~~~ +.. code-block:: postgres + vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-jdbcsink.properties + +Example +.. code-block:: postgres + + name=SQReamJDBCSink + topics=demo1 + tasks.max=1 + connector.class=tr.com.entegral.JDBCSinkConnector + errors.tolerance=all + errors.log.enable=true + errors.log.include.messages=true + value.converter=org.apache.kafka.connect.json.JsonConverter + value.converter.schemas.enable=false + transforms=flatten + transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value + transforms.flatten.delimiter=. + sqream.batchRecordCount =3 + #sqream.jdbc.connectionstring=jdbc:sqlserver://localhost;databaseName=TestDB;user=kafka;password=kafka;encrypt=true;trustServerCertificate=true; + sqream.jdbc.connectionstring=jdbc:Sqream://192.168.0.102:5001/kafka;user=sqream;password=sqream;cluster=false + sqream.input.inputfields=intStr,inInt,indateTime,inFloat + sqream.jdbc.tablename=testtable + sqream.jdbc.table.columnnames=colStr,colInt,Coldatetime,ColFloat + sqream.jdbc.table.columntypes=VARCHAR,INTEGER,TIMESTAMP,FLOAT + sqream.jdbc.dateformat=yyyy-MM-dd HH:mm:ss SQream Loader Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 903800b35..e765f56af 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -23,7 +23,6 @@ If you are looking for a tool that is not listed, SQream and our partners can he spark - trino informatica microstrategy pentaho diff --git a/connecting_to_sqream/client_platforms/trino.rst b/connecting_to_sqream/client_platforms/trino.rst deleted file mode 100644 index be1e7e9b7..000000000 --- a/connecting_to_sqream/client_platforms/trino.rst +++ /dev/null @@ -1,144 +0,0 @@ -.. _trino: - -************************* -Connecting to SQream Using Trino -************************* - - -If you are using Trino for distributed SQL query processing and wish to use it to connect to a SQream, follow these instructions. - - -.. contents:: - :local: - :depth: 1 - -Prerequisites -------------- -To use Trino with SQream, you must have the following installed: - -* SQream version 2022.1.8 or later -* Trino version 403 or later -* SQream Trino plugin xxxx -* JDBC version 4.5.6 or later - - - -Installation ------------- - -.. contents:: - :local: - :depth: 1 - -JDBC -~~~~ - -In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. - - -SQream Trino Plugin -~~~~~~~~~~~~~~~~~~~ - -The SQream Trino plugin must be installed on each cluster node dedicated to Trino. - -1. Create a dedicated directory for the SQream Trino plugin. - -2. Download the `SQream Trino Plugin<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: - - -.. code-block:: postgres - - trino-server/ - └── plugin - └── sqream - ├── sqream-jdbc.jar - ├── trino-sqream-services.jar - ├── trino-sqream-SNAPSHOT.jar - └── all dependencies - - - -Connecting to SQream --------------------- - -Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish Trino to have access to more than one SQream database or server, you must create additional catalogs. - -Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. - -The following is an example of a properties file: - -.. code-block:: postgres - - connector.name=<name> - connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] - connection-user=<user> - connection-password=<password> - -Syntax examples ---------------- - -The following is an example of the ``SHOW SCHEMAS FROM`` statement: - -.. code-block:: postgres - - SHOW SCHEMAS FROM sqream; - -The following is an example of the ``SHOW TABLES FROM`` statement: - -.. code-block:: postgres - - SHOW TABLES FROM sqream.public; - -The following is an example of the ``DESCRIBE sqream.public.t`` statement: - -.. code-block:: postgres - - DESCRIBE sqream.public.t; - - -Supported Data Types and Mapping --------------------------------- -Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Trino type - - SQream type - * - ``BOOLEAN`` - - ``BOOL`` - * - ``TINYINT`` - - ``TINYINT`` - * - ``SMALLINT`` - - ``SMALLINT`` - * - ``INT`` - - ``INT`` - * - ``BIGINT`` - - ``BIGINT`` - * - ``REAL`` - - ``REAL`` - * - ``DOUBLE`` - - ``DOUBLE`` - * - ``DATE`` - - ``DATE`` - * - ``TIMESTAMP`` - - ``DATETIME`` - * - ``VARCHAR(N)`` - - ``VARCHAR(N)``. - * - ``VARCHAR`` - - ``TEXT`` - * - ``DECIMAL(P,S)`` - - ``NUMERIC(P,S)`` - -.. note:: ``VARCHAR`` is soon to be deprecated and may not be used in SQream DB. - -Limitations ------------ - -The SQream Trino plugin does not support the following SQL statements: - -* ``GRANT`` -* ``REVOKE`` -* ``SHOW GRANTSHOW ROLES`` -* ``SHOW ROLE GRANTS`` \ No newline at end of file From 9e33de08ea2bc5e242f119d73b93813109acdc1e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 08:58:30 +0200 Subject: [PATCH 0420/1892] Update tibco_spotfire.rst --- .../client_platforms/tibco_spotfire.rst | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst index 4c032ba84..2d85fecf1 100644 --- a/connecting_to_sqream/client_platforms/tibco_spotfire.rst +++ b/connecting_to_sqream/client_platforms/tibco_spotfire.rst @@ -128,52 +128,52 @@ After creating a connection, you can create your SQream data source template. .. code-block:: console <jdbc-type-settings> - <type-name>SQream </type-name> - <driver>com.sqream.jdbc.SQDriver </driver> - <connection-url-pattern>jdbc:Sqream://&lt;host&gt;:&lt;port&gt;/database;user=sqream;password=sqream;cluster=true </connection-url-pattern> - <supports-catalogs>true </supports-catalogs> - <supports-schemas>true </supports-schemas> - <supports-procedures>false </supports-procedures> - <table-types>TABLE,EXTERNAL_TABLE </table-types> + <type-name>SQream</type-name> + <driver>com.sqream.jdbc.SQDriver</driver> + <connection-url-pattern>jdbc:Sqream://&lt;host&gt;:&lt;port&gt;/database;user=sqream;password=sqream;cluster=true</connection-url-pattern> + <supports-catalogs>true</supports-catalogs> + <supports-schemas>true</supports-schemas> + <supports-procedures>false</supports-procedures> + <table-types>TABLE,EXTERNAL_TABLE</table-types> <java-to-sql-type-conversions> <type-mapping> - <from>Bool </from> - <to>Integer </to> + <from>Bool</from> + <to>Integer</to> </type-mapping> <type-mapping> - <from>VARCHAR(2048) </from> - <to>String </to> + <from>VARCHAR(2048)</from> + <to>String</to> </type-mapping> <type-mapping> - <from>INT </from> - <to>Integer </to> + <from>INT</from> + <to>Integer</to> </type-mapping> <type-mapping> - <from>BIGINT </from> - <to>LongInteger </to> + <from>BIGINT</from> + <to>LongInteger</to> </type-mapping> <type-mapping> - <from>Real </from> - <to>Real </to> + <from>Real</from> + <to>Real</to> </type-mapping> <type-mapping> - <from>Decimal </from> - <to>Float </to> + <from>Decimal</from> + <to>Float</to> </type-mapping> <type-mapping> - <from>Numeric </from> - <to>Float </to> + <from>Numeric</from> + <to>Float</to> </type-mapping> <type-mapping> - <from>Date </from> - <to>DATE </to> + <from>Date</from> + <to>DATE</to> </type-mapping> <type-mapping> - <from>DateTime </from> - <to>DateTime </to> + <from>DateTime</from> + <to>DateTime</to> </type-mapping> </java-to-sql-type-conversions> - <ping-command> </ping-command> + <ping-command></ping-command> </jdbc-type-settings> 4. Click **Save configuration**. From f64dc5198708bfb45902a598a757c6338a16e1ea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 09:05:10 +0200 Subject: [PATCH 0421/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index c502f60bf..b8d9691fd 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -58,9 +58,9 @@ An average single-node cluster can be a rackmount server or workstation, contain .. note:: If you are using internal storage, your volumes must be formatted as xfs. -In this system configuration, SQream can store about 200TB of raw data (assuming average compression ratio and ~50TB of usable raw storage). +In this system configuration, SQream can store about 100TB of raw data (assuming average compression ratio and ~30TB of usable raw storage). -If a NAS is used, the 14x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. +If a NAS is used, the 10x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. Multi-Node Cluster Examples ----------------------------------- From 66494b93da7a50cfe3d2db9872c6a0477d5826f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:00:07 +0200 Subject: [PATCH 0422/1892] get_all_roles --- .../get_all_roles_database_ddl.rst | 46 ++++++++++++++++++ .../get_all_roles_global_ddl.rst | 47 +++++++++++++++++++ .../get_role_database_ddl.rst | 4 +- 3 files changed, 95 insertions(+), 2 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst new file mode 100644 index 000000000..bd7856776 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst @@ -0,0 +1,46 @@ +.. _get_all_roles_database_ddl: + +******************** +GET_ALL_ROLES_DATABASE_DDL +******************** +The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all global roles in DDL format. + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: postgres + + select get_all_roles_database_ddl() + +Example +=========== +The following is an example of using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: psql + + select get_all_roles_database_ddl(); + +Output +========== +The following is an example of the output of the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: postgres + + grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl, update to creator_role ; grant select, insert, delete, ddl, update on table "public"."customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."d_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."nation" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."orders" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."part" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."partsupp" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."region" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."supplier" to "sqream" ; alter default schema for "sqream" to "public"; + +Permissions +============= +Using the ``GET_ALL_ROLES_DATABASE_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_all_roles_global_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst new file mode 100644 index 000000000..7a77dd810 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst @@ -0,0 +1,47 @@ +.. _get_all_roles_global_ddl: + +******************** +GET_ALL_ROLES_GLOBAL_DDL +******************** +The ``GET_ALL_ROLES_GLOBAL_DDL`` statement returns the definition of all global roles in DDL format. + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + select get_all_roles_global_ddl() + +Example +=========== +The following is an example of using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: + +.. code-block:: psql + + select get_all_roles_global_ddl(); + + +Output +========== +The following is an example of the output of the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: + +.. code-block:: postgres + + create role "public"; create role "sqream"; grant superuser, login to "sqream" ; + +Permissions +============= +Using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_all_roles_database_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index e6b806244..85db79a4a 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -21,11 +21,11 @@ The following is the correct syntax for using the ``GET_ROLE_DATABASE_DDL`` stat Example =========== -The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: +The following is an example of using the ``GET_ROLE_DATABASE_DDL`` statement: .. code-block:: psql - select get_role_global_ddl('public'); + select get_role_database_ddl('public'); Parameters ============ From a493a8f3ee963a2f4817c634addb00d89d11acdf Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:13:00 +0200 Subject: [PATCH 0423/1892] get_all_roles --- reference/sql/sql_statements/index.rst | 6 +++++- .../utility_commands/get_all_roles_database_ddl.rst | 2 +- .../utility_commands/get_role_database_ddl.rst | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index af6e9f06a..325647bda 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -192,8 +192,12 @@ The following table shows the Access Control commands: - Returns all permissions granted to a role in table format * - :ref:`get_role_global_ddl` - Returns the definition of a global role in DDL format + * - :ref:`get_all_roles_global_ddl` + - Returns the definition of all global roles in DDL format * - :ref:`get_role_database_ddl` - - Returns the definition of a database role in DDL format + - Returns the definition of a role's database in DDL format + * - :ref:`get_all_roles_database_ddl` + - Returns the definition of all role databases in DDL format * - :ref:`get_statement_permissions` - Returns a list of permissions required to run a statement or query * - :ref:`grant` diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst index bd7856776..430ede73e 100644 --- a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst @@ -3,7 +3,7 @@ ******************** GET_ALL_ROLES_DATABASE_DDL ******************** -The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all global roles in DDL format. +The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role databases in DDL format. .. contents:: :local: diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index 85db79a4a..5ff3ecf79 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -3,7 +3,7 @@ ******************** GET_ROLE_DATABASE_DDL ******************** -The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a global role in DDL format. +The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a role's database in DDL format. The ``GET_ROLE_DATABASE_DDL`` page describes the following: From e38e3494d181c77f921cc7f4a890e6833552bf1a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 13:27:20 +0200 Subject: [PATCH 0424/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 940e21822..25e150881 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST(<value> TO <data type>)``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT(30))``. +* ``CAST(<value> TO <data type>)``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT)``. :: @@ -38,11 +38,9 @@ Supported Casts +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | N/A | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **DATE**/**DATETIME** | ✗ | ✗ | ✗ | ✗ | N/A | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ - - :check_mark: \ No newline at end of file From 882f928a4cfca52ff3e3fc29384feebdda745a6f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Jan 2023 17:03:32 +0200 Subject: [PATCH 0425/1892] RN --- releases/4.0.0.rst | 127 +++++++++++++++++++++++++++++++++++++++ releases/4.0.0_index.rst | 127 +++------------------------------------ releases/4.1.0.rst | 127 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+), 120 deletions(-) create mode 100644 releases/4.0.0.rst create mode 100644 releases/4.1.0.rst diff --git a/releases/4.0.0.rst b/releases/4.0.0.rst new file mode 100644 index 000000000..95bfb7aab --- /dev/null +++ b/releases/4.0.0.rst @@ -0,0 +1,127 @@ +.. _4.0.0: + +************************** +Release Notes 4.0.0 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.0.0 release notes were released on xx/xx/20xx and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature + + :: + + * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles + + :: + + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + +SQream Studio Updates and Improvements +-------------------------------------- + + * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. + + :: + +Known Issues +------------ +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + +Version 4.0.0 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-10544 | SQream Studio Worker Panel issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12310 | ``DICT`` compression buffer size issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker GPU dependency | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12652 + 12844 | SQream Studio result panel adjustment | ++------------------------+------------------------------------------------------------------------------------------+ + + +Configuration Changes +--------------------- +No configuration changes were made. + +Naming Changes +-------------- +No relevant naming changes were made. + +Deprecated Features +------------------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to v4.0.0 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst index c592cf1bd..5f072fd35 100644 --- a/releases/4.0.0_index.rst +++ b/releases/4.0.0_index.rst @@ -1,129 +1,16 @@ -.. _4.0.0: +.. _4.0.0_index: ************************** Release Notes 4.0.0 ************************** - -SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. - -The 4.0.0 release notes were released on xx/xx/20xx and describe the following: +The 4.0.0 Release Notes describe the following releases: .. contents:: :local: - :depth: 1 - -New Features ------------- - - * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature - - :: - - * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles - - :: - - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities - -SQream Studio Updates and Improvements --------------------------------------- - - * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. - - :: - -Known Issues ------------- -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 4.0.0 resolved Issues ------------------------------ - -+------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+==========================================================================================+ -| SQ-10544 | SQream Studio Worker Panel issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12446 | | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker GPU dependency | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12652 + 12844 | SQream Studio result panel adjustment | -+------------------------+------------------------------------------------------------------------------------------+ - - -Configuration Changes ---------------------- -No configuration changes were made. - -Naming Changes --------------- -No relevant naming changes were made. - -Deprecated Features -------------------- -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support ---------------- -No End of Support changes were made. - -Upgrading to v4.0.0 -------------------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console + :depth: 1 - $ ./upgrade_storage <levelDB path> +.. toctree:: + :maxdepth: 1 + :glob: - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - + 4.0.0 diff --git a/releases/4.1.0.rst b/releases/4.1.0.rst new file mode 100644 index 000000000..d24ea13a2 --- /dev/null +++ b/releases/4.1.0.rst @@ -0,0 +1,127 @@ +.. _4.1.0: + +************************** +Release Notes 4.1.0 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.0.0 release notes were released on xx/xx/20xx and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature + + :: + + * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles + + :: + + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + +SQream Studio Updates and Improvements +-------------------------------------- + + * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. + + :: + +Known Issues +------------ +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + +Version 4.0.0 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-10544 | SQream Studio Worker Panel issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow ``JOIN`` query | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12310 | ``DICT`` compression buffer size issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker GPU dependency | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12652 + 12844 | SQream Studio result panel adjustment | ++------------------------+------------------------------------------------------------------------------------------+ + + +Configuration Changes +--------------------- +No configuration changes were made. + +Naming Changes +-------------- +No relevant naming changes were made. + +Deprecated Features +------------------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to v4.0.0 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 6acdd029bf0c901c0e39d39d3bfdb1f34877ae57 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 9 Feb 2023 14:02:13 +0200 Subject: [PATCH 0426/1892] 4.1 --- connecting_to_sqream/client_drivers/index.rst | 4 - .../client_drivers/kafka/index.rst | 250 ------------------ releases/2022.1.8.rst | 116 -------- releases/2022.1_index.rst | 1 - releases/4.0.rst | 121 +++++++++ releases/4.0_index.rst | 17 ++ releases/index.rst | 6 +- 7 files changed, 141 insertions(+), 374 deletions(-) delete mode 100644 connecting_to_sqream/client_drivers/kafka/index.rst delete mode 100644 releases/2022.1.8.rst create mode 100644 releases/4.0.rst create mode 100644 releases/4.0_index.rst diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index d35b1662f..a4400e40a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -27,10 +27,6 @@ The following are applicable to all operating systems: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ * :ref:`net` -* **Kafka**: - - * `Kafka download file <>`_ - * :ref:`kafka` .. _python: diff --git a/connecting_to_sqream/client_drivers/kafka/index.rst b/connecting_to_sqream/client_drivers/kafka/index.rst deleted file mode 100644 index 983b0b96e..000000000 --- a/connecting_to_sqream/client_drivers/kafka/index.rst +++ /dev/null @@ -1,250 +0,0 @@ -.. _kafka: - -************************* -Connecting to SQream Using Kafka -************************* - -If you are using Kafka Apache for distributed streaming and wish to use it with SQream, follow these instructions. - - -.. contents:: - :local: - :depth: 1 - - -Before You Begin -================ - -* You must have JAVA 11 installed -* You must have `JDBC <java_jdbc>`_ installed -* Your network bandwidth must be at least 100 mega per second -* Supported data formats for streamed data is JSON - -High Level Workflow -=================== - -1. Install the JDBC Connector. -2. Install kafka_2.12-3.2.1 -3. Run your Kafka Connect API. -4. - - - -Installation and Configuration -============================== - -Before you configure the Kafka Connector, make sure that Kafka and Zookeeper are both running. - -Kafka Connector workflow: - -.. figure:: /_static/images/kafka_flow.png - -.. contents:: - :local: - :depth: 1 - -Sink Connector ---------------- - -The Sink Connector reads JSON format Kafka topics and writes the messages inside each topic into text files. The files are created with the extension ``.tmp`` and stored in a specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file, and when the specified number is reached, the Sink Connector closes the file, renames it to ``sqream.fileExtension``, and then creates a new file. Unlike data streaming, which continuously sends data from the Kafka topic to the database, the Sink Connector only sends the data when the file size reaches a predefined threshold. This means that data will arrive in batches. - -SQream tables must be created according to the columns configured in ``csvorder``. - - -Sink Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Configuration file structure: - - .. code-block:: postgres - - name=SQReamFileSink - topics=topsqreamtest1 - tasks.max=4 - connector.class=tr.com.entegral.FileSinkConnector - errors.tolerance=all - errors.log.enable=true - errors.log.include.messages=true - value.converter=org.apache.kafka.connect.json.JsonConverter - value.converter.schemas.enable=false - transforms=flatten - transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value - transforms.flatten.delimiter=. - sqream.outputdir=/home/sqream/kafkaconnect/outputs - sqream.batchRecordCount =10 - sqream.fileExtension=csv - sqream.removeNewline =false - sqream.outputType=csv - sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv - -The following parameters require configuration. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - Topic - - A category or feed name to which messages are published and subscribed to - * - ``sqream.batchrecordcount`` - - The record count to be written to each file - * - ``outputdir`` - - Copy the ``sqream.outputdir`` path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path - * - ``csvorder`` - - Defines table columns. SQream table columns must align with the ``csvorder`` table columns - - -Connection string: - - .. code-block:: postgres - - vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties - -Running commands: - - .. code-block:: postgres - - export JAVA_HOME=/home/sqream/copy-from-util/jdk-11;export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar;cd /home/sqream/kafkaconnect1/kafka/bin/ && ./connect-standalone.sh /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/connect-standalone.properties /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties & - - - - -JDBC -------------- - -The JDBC connector can be used to ingest data from Kafka, allowing SQream DB to consume the messages directly. This enables efficient and secure data ingestion into SQream DB. - -.. contents:: - :local: - :depth: 1 - -JDBC Configuration -~~~~~~~~~~~~~~~~~~ - -.. code-block:: postgres - vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-jdbcsink.properties - -Example - -.. code-block:: postgres - - name=SQReamJDBCSink - topics=demo1 - tasks.max=1 - connector.class=tr.com.entegral.JDBCSinkConnector - errors.tolerance=all - errors.log.enable=true - errors.log.include.messages=true - value.converter=org.apache.kafka.connect.json.JsonConverter - value.converter.schemas.enable=false - transforms=flatten - transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value - transforms.flatten.delimiter=. - sqream.batchRecordCount =3 - #sqream.jdbc.connectionstring=jdbc:sqlserver://localhost;databaseName=TestDB;user=kafka;password=kafka;encrypt=true;trustServerCertificate=true; - sqream.jdbc.connectionstring=jdbc:Sqream://192.168.0.102:5001/kafka;user=sqream;password=sqream;cluster=false - sqream.input.inputfields=intStr,inInt,indateTime,inFloat - sqream.jdbc.tablename=testtable - sqream.jdbc.table.columnnames=colStr,colInt,Coldatetime,ColFloat - sqream.jdbc.table.columntypes=VARCHAR,INTEGER,TIMESTAMP,FLOAT - sqream.jdbc.dateformat=yyyy-MM-dd HH:mm:ss - -SQream Loader Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -Building the SQream Loader: - - .. code-block:: postgres - - git clone -b develop http://gitlab.sq.l/java/copy-from-util.git - mvn clean package - - -Running the SQream Loader: - - .. code-block:: postgres - - git clone -b develop http://gitlab.sq.l/java/copy-from-util.git - mvn clean package - -What needs to be configured: - -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Parameter - - Description - * - ``root`` - – paste copied path to root - * - ``schema`` - - - * - ``name`` - - - -Configuration file structure: - - .. code-block:: postgres - - #config.yaml - - com: - sqream: - kafka: - common: - root: "/home/sqream/copy_from_root" - readyFileSuffix: ".csv" - connection: - ip: "127.0.0.1" - port: 3108 - database: "master" - cluster: true - user: sqream - pass: sqream - delimiter: "," - tables: - - schema: "public" - name: "t1" - parallel: 5 - - schema: "public" - name: "t2" - parallel: 3 - - schema: "public" - name: "t3" - parallel: 1 - - - - -Running commands: - - .. code-block:: postgres - - /home/sqream/copy-from-util/jdk-11/bin/java -jar /home/sqream/copy-from-util/copy-from-util/target/copy-from-util-0.0.1-SNAPSHOT.jar --spring.config.additional-location=/home/sqream/copy-from-util/config.yaml & - -Logging and Monitoring -======================== - -The following log files are created: - * JAVA application fails (consumer or loader?) - * Files cannot be saved to folder due to -Either - * Folder permission issue -Or - * SQream loader folder is not the same as Kenan folder - -Purging -======= -Ingested files are automatically zipped and archived for 60 days. - -Limitations -=========== - -Latency -Retention - -Examples -========= diff --git a/releases/2022.1.8.rst b/releases/2022.1.8.rst deleted file mode 100644 index c7ea25263..000000000 --- a/releases/2022.1.8.rst +++ /dev/null @@ -1,116 +0,0 @@ -.. _2022.1.8: - -************************** -Release Notes 2022.1.8 -************************** -The 2022.1.8 release notes were released on xx/xx/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ----------- - - * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature - - :: - - * :ref:`Physical deletion performance enhancement<delete>` for file systems with delete parallelism capabilities - - :: - - -Known Issues ---------- -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 2022.1.8 resolved Issues ---------- - -+---------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+===============+==========================================================================================+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12255 | ``COPY TO`` string export error | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+---------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+---------------+------------------------------------------------------------------------------------------+ - - - - - - -Configuration Changes --------- -No configuration changes were made. - -Naming Changes -------- -No relevant naming changes were made. - -Deprecated Features -------- -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support -------- -No End of Support changes were made. - -Upgrading to v2022.1.8 -------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index a41453b32..e63294405 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -13,7 +13,6 @@ The 2022.1 Release Notes describe the following releases: :maxdepth: 1 :glob: - 2022.1.8 2022.1.7 2022.1.6 2022.1.5 diff --git a/releases/4.0.rst b/releases/4.0.rst new file mode 100644 index 000000000..c0b47b5b8 --- /dev/null +++ b/releases/4.0.rst @@ -0,0 +1,121 @@ +.. _4.0: + +************************** +Release Notes 4.0 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.0 release notes were released on 01/25/2023 and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature + + :: + + * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles + + :: + + * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + +SQream Studio Updates and Improvements +-------------------------------------- + + * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. + + :: + + * When editing an **Existing Role**, you are no longer obligated to update the role's password. + +Known Issues +------------ +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + +Version 4.0 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-10544 | SQream Studio dashboard periodic update enhancement | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11772 | Slow query performance when using ``JOIN`` clause | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12446 | SQream Studio group role modification issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker GPU dependency | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12652 | SQream Studio result panel adjustment | ++------------------------+------------------------------------------------------------------------------------------+ + + +Configuration Changes +--------------------- +No configuration changes were made. + +Naming Changes +-------------- +No relevant naming changes were made. + +Deprecated Features +------------------- +SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. + +VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). + +TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to version 4.0 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst new file mode 100644 index 000000000..680957f22 --- /dev/null +++ b/releases/4.0_index.rst @@ -0,0 +1,17 @@ +.. _4.0_index: + +************************** +Release Notes 4.0 +************************** +The 4.0 Release Notes describe the following releases: + +.. contents:: + :local: + :depth: 1 + +.. toctree:: + :maxdepth: 1 + :glob: + + 4.0 + 4.1 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 107f323c8..196502b60 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,8 +12,8 @@ Release Notes * - Version - Release Date - * - :ref:`4.0.0` - - XXXX xx, xxxx + * - :ref:`4.0` + - January 25, 2023 * - :ref:`2022.1` - July 19, 2022 * - :ref:`2021.2` @@ -34,7 +34,7 @@ Release Notes :glob: :hidden: - 4.0.0_index + 4.0_index 2022.1_index 2021.2_index 2021.1_index From c4858bb951b54904e2d06583bab4b539c7643711 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Feb 2023 17:16:38 +0200 Subject: [PATCH 0427/1892] Update generic_regular_flags.rst --- .../generic_regular_flags.rst | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst index 34ff6850c..c262982ec 100644 --- a/configuration_guides/generic_regular_flags.rst +++ b/configuration_guides/generic_regular_flags.rst @@ -6,16 +6,16 @@ Regular Generic Flags The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: -* `Flipping Join Order to Force Equijoins <https://docs.sqream.com/en/v2022.1.1/configuration_guides/flip_join_order.html>`_ -* `Determining Client Level <https://docs.sqream.com/en/v2022.1.1/configuration_guides/log_sys_level.html>`_ -* `Setting CPU to Compress Defined Columns <https://docs.sqream.com/en/v2022.1.1/configuration_guides/max_avg_blob_size_to_compress_on_gpu.html>`_ -* `Setting Query Memory Processing Limit <https://docs.sqream.com/en/v2022.1.1/configuration_guides/limit_query_memory_gb.html>`_ -* `Setting the Spool Memory <https://docs.sqream.com/en/v2022.1.1/configuration_guides/limit_query_memory_gb.html>`_ -* `Setting Cache Partitions <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_partitions.html>`_ -* `Setting Cache Flushing <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_eviction_milliseconds.html>`_ -* `Setting InMemory Spool Memory <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_ram_gb.html>`_ -* `Setting Disk Spool Memory <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_disk_gb.html>`_ -* `Setting Spool Saved File Directory Location <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_disk_dir.html>`_ -* `Setting Data Stored Persistently on Cache <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_persistent_gb.html>`_ -* `Setting Persistent Spool Saved File Directory Location <https://docs.sqream.com/en/v2022.1.1/configuration_guides/cache_persistent_dir.html>`_ -* `Setting Session Tag Name <https://docs.sqream.com/en/v2022.1.1/configuration_guides/session_tag.html>`_ \ No newline at end of file +* :ref:`Flipping Join Order to Force Equijoins<flip_join_order>` +* :ref:`Determining Client Level<log_sys_level>` +* :ref:`Setting CPU to Compress Defined Columns<max_avg_blob_size_to_compress_on_gpu>` +* :ref:`Setting Query Memory Processing Limit<limit_query_memory_gb>` +* :ref:`Setting the Spool Memory<spool_memory_gb>` +* :ref:`Setting Cache Partitions<cache_partitions>` +* :ref:`Setting Cache Flushing<cache_eviction_milliseconds>` +* :ref:`Setting InMemory Spool Memory<cache_ram_gb>` +* :ref:`Setting Disk Spool Memory<cache_disk_gb>` +* :ref:`Setting Spool Saved File Directory Location<cache_disk_dir>` +* :ref:`Setting Data Stored Persistently on Cache<cache_persistent_gb>` +* :ref:`Setting Persistent Spool Saved File Directory Location<cache_persistent_dir>` +* :ref:`Setting Session Tag Name<session_tag>` \ No newline at end of file From aed56a4c5f048fb02712331061ec7c3417da5a0c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 09:01:53 +0200 Subject: [PATCH 0428/1892] Update 4.1.0.rst --- releases/4.1.0.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.1.0.rst b/releases/4.1.0.rst index d24ea13a2..0b279a2bd 100644 --- a/releases/4.1.0.rst +++ b/releases/4.1.0.rst @@ -6,7 +6,7 @@ Release Notes 4.1.0 SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. -The 4.0.0 release notes were released on xx/xx/20xx and describe the following: +The 4.1.0 release notes were released on xx/xx/20xx and describe the following: .. contents:: :local: @@ -36,7 +36,7 @@ Known Issues ------------ :ref:`Percentile<percentile_disc>` is not supported for Window functions. -Version 4.0.0 resolved Issues +Version 4.1.0 resolved Issues ----------------------------- +------------------------+------------------------------------------------------------------------------------------+ @@ -89,7 +89,7 @@ End of Support --------------- No End of Support changes were made. -Upgrading to v4.0.0 +Upgrading to v4.1.0 ------------------- 1. Generate a back-up of the metadata by running the following command: From 8f0908ae0a44adf3b7146e5ba325cc6afdeaac19 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 14:56:21 +0200 Subject: [PATCH 0429/1892] RN --- connecting_to_sqream/client_drivers/index.rst | 10 +- .../client_drivers/trino/index.rst | 144 ++++++++++++++++++ .../client_platforms/index.rst | 2 +- releases/4.1.0.rst | 127 --------------- releases/4.1.rst | 129 ++++++++++++++++ 5 files changed, 282 insertions(+), 130 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/trino/index.rst delete mode 100644 releases/4.1.0.rst create mode 100644 releases/4.1.rst diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index a4400e40a..7ffd95138 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -27,6 +27,12 @@ The following are applicable to all operating systems: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ * :ref:`net` +.. _trino: + +* **Trino**: + + * `Trino connector <>`_ + * :ref:`trino` .. _python: @@ -96,16 +102,16 @@ The following are applicable to Linux: :caption: Client Driver Documentation: :titlesonly: + trino/index jdbc/index python/index - dotnet/index - kafka/index nodejs/index odbc/index dotnet/index + .. rubric:: Need help? If you couldn't find what you're looking for, we're always happy to help. Visit :ref:`information_for_support` for additional support. diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst new file mode 100644 index 000000000..6a8ac9bac --- /dev/null +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -0,0 +1,144 @@ +.. _trino: + +************************* +Connecting to SQream Using Trino +************************* + + +If you are using Trino for distributed SQL query processing and wish to use it to connect to a SQream, follow these instructions. + + +.. contents:: + :local: + :depth: 1 + +Prerequisites +------------- +To use Trino with SQream, you must have the following installed: + +* SQream version 4.1 or later +* Trino version 403 or later +* Trino Connector xxxx +* JDBC version 4.5.6 or later + + + +Installation +------------ + +.. contents:: + :local: + :depth: 1 + +JDBC +~~~~ + +In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. + + +Trino Connector +~~~~~~~~~~~~~~~~~~~ + +The Trino Connector must be installed on each cluster node dedicated to Trino. + +1. Create a dedicated directory for the Trino Connector. + +2. Download the `Trino Connector<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: + + +.. code-block:: postgres + + trino-server/ + └── plugin + └── sqream + ├── sqream-jdbc.jar + ├── trino-sqream-services.jar + ├── trino-sqream-SNAPSHOT.jar + └── all dependencies + + + +Connecting to SQream +-------------------- + +Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish Trino to have access to more than one SQream database or server, you must create additional catalogs. + +Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. + +The following is an example of a properties file: + +.. code-block:: postgres + + connector.name=<name> + connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] + connection-user=<user> + connection-password=<password> + +Syntax examples +--------------- + +The following is an example of the ``SHOW SCHEMAS FROM`` statement: + +.. code-block:: postgres + + SHOW SCHEMAS FROM sqream; + +The following is an example of the ``SHOW TABLES FROM`` statement: + +.. code-block:: postgres + + SHOW TABLES FROM sqream.public; + +The following is an example of the ``DESCRIBE sqream.public.t`` statement: + +.. code-block:: postgres + + DESCRIBE sqream.public.t; + + +Supported Data Types and Mapping +-------------------------------- +Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Trino type + - SQream type + * - ``BOOLEAN`` + - ``BOOL`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``REAL`` + - ``REAL`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``VARCHAR(N)`` + - ``VARCHAR(N)``. + * - ``VARCHAR`` + - ``TEXT`` + * - ``DECIMAL(P,S)`` + - ``NUMERIC(P,S)`` + +.. note:: ``VARCHAR`` is soon to be deprecated and may not be used in SQream DB. + +Limitations +----------- + +The Trino Connector does not support the following SQL statements: + +* ``GRANT`` +* ``REVOKE`` +* ``SHOW GRANTSHOW ROLES`` +* ``SHOW ROLE GRANTS`` \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index e765f56af..5a13fb6f4 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -22,7 +22,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he :titlesonly: - spark + informatica microstrategy pentaho diff --git a/releases/4.1.0.rst b/releases/4.1.0.rst deleted file mode 100644 index 0b279a2bd..000000000 --- a/releases/4.1.0.rst +++ /dev/null @@ -1,127 +0,0 @@ -.. _4.1.0: - -************************** -Release Notes 4.1.0 -************************** - -SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. - -The 4.1.0 release notes were released on xx/xx/20xx and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - - * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature - - :: - - * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles - - :: - - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities - -SQream Studio Updates and Improvements --------------------------------------- - - * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. - - :: - -Known Issues ------------- -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 4.1.0 resolved Issues ------------------------------ - -+------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+==========================================================================================+ -| SQ-10544 | SQream Studio Worker Panel issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker GPU dependency | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12652 + 12844 | SQream Studio result panel adjustment | -+------------------------+------------------------------------------------------------------------------------------+ - - -Configuration Changes ---------------------- -No configuration changes were made. - -Naming Changes --------------- -No relevant naming changes were made. - -Deprecated Features -------------------- -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support ---------------- -No End of Support changes were made. - -Upgrading to v4.1.0 -------------------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/4.1.rst b/releases/4.1.rst new file mode 100644 index 000000000..20d57aaf6 --- /dev/null +++ b/releases/4.1.rst @@ -0,0 +1,129 @@ +.. _4.1: + +************************** +Release Notes 4.1 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.1 release notes were released on xx/xx/20xx and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + * :ref:`Lightweight Directory Access Protocol (LDAP)<ldap>` enhanced management + + :: + + * The :ref:`Trino<trino>` ETL tool may now be used for distributed SQL query processing + + :: + + * A brute-force attack protection locks out user accounts for 15 minutes following 5 consecutive failed login attempts + +SQream Studio Updates and Improvements +-------------------------------------- + +No Studio updates + + :: + +Known Issues +------------ + +No known issues + + +Version 4.1 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-11287 | Function definition SQL UDF parenthesis issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12255 | Text column additional characters when using ``COPY TO`` statement | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12510 | Encryption memory issues | ++------------------------+------------------------------------------------------------------------------------------+ + + +Configuration Changes +--------------------- + +No configuration changes + + +Naming Changes +-------------- +No naming changes + + +Deprecated Features +------------------- + +► Square Brackets ``[]`` + +To facilitate the use of array data types, the ``[]``, which are frequently used to delimit identifiers such as column names, table names, and other database objects, have been deprecated. + +* Support in ``[]`` for delimiting database object identifiers ends at xx/xx/20xx. + +* You may still use double quotes ``""`` to delimit database object identifiers. + +► ``VARCHAR`` + +``VARCHAR`` is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. + +* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3 (September 2022). + +* The ``TEXT`` data type is replacing ``VARCHAR`` and ``NVARCHAR``. + +*Support in ``VARCHAR`` ends at September 30th, 2023. + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to v4.1 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Extract the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From f1d1b34e7d2bb97a8cf9642b7b0fd3c373d6de7a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 14:57:44 +0200 Subject: [PATCH 0430/1892] Update 4.1.rst --- releases/4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 20d57aaf6..0f174e8a9 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -70,7 +70,7 @@ Deprecated Features ► Square Brackets ``[]`` -To facilitate the use of array data types, the ``[]``, which are frequently used to delimit identifiers such as column names, table names, and other database objects, have been deprecated. +To facilitate the use of array data types, the ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, have been deprecated. * Support in ``[]`` for delimiting database object identifiers ends at xx/xx/20xx. From 77351a42a45487120f4982c72189d898d9c52ae1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 14:59:25 +0200 Subject: [PATCH 0431/1892] Update 4.1.rst --- releases/4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 0f174e8a9..0fde2a2cc 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -70,7 +70,7 @@ Deprecated Features ► Square Brackets ``[]`` -To facilitate the use of array data types, the ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, have been deprecated. +To facilitate the use of Array data types, the ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, have been deprecated. * Support in ``[]`` for delimiting database object identifiers ends at xx/xx/20xx. From 142f7a628caf00f68c6fb53e8cb82eed36ae86fb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 17:10:05 +0200 Subject: [PATCH 0432/1892] oracle --- data_ingestion/index.rst | 1 - index.rst | 2 -- 2 files changed, 3 deletions(-) diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index 6e8530710..290e0fce3 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -14,7 +14,6 @@ The **Data Ingestion Sources** page provides information about the following: csv parquet orc - oracle json For information about database tools and interfaces that SQream supports, see `Third Party Tools <https://docs.sqream.com/en/v2022.1.1/connecting_to_sqream/index.html>`_. \ No newline at end of file diff --git a/index.rst b/index.rst index 61e31b593..d09ca5bdd 100644 --- a/index.rst +++ b/index.rst @@ -33,8 +33,6 @@ SQream DB is a columnar analytic SQL database management system. SQream DB suppo +--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`parquet` | :ref:`orc` | | +--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`oracle` | -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | **Connecting to SQream** | +--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | From cf3940b004569215c3164d513c948e932c41acd9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 17:30:05 +0200 Subject: [PATCH 0433/1892] Update 4.1.rst --- releases/4.1.rst | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 0fde2a2cc..bb6f9a290 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -70,21 +70,24 @@ Deprecated Features ► Square Brackets ``[]`` -To facilitate the use of Array data types, the ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, have been deprecated. +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. * Support in ``[]`` for delimiting database object identifiers ends at xx/xx/20xx. -* You may still use double quotes ``""`` to delimit database object identifiers. +* To delimit database object identifiers, you will be able to use double quotes ``""``. + ► ``VARCHAR`` -``VARCHAR`` is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. +The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. + +* Support in the ``VARCHAR`` data type ends at September 30th, 2023. + +* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. -* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3 (September 2022). +* The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. -* The ``TEXT`` data type is replacing ``VARCHAR`` and ``NVARCHAR``. -*Support in ``VARCHAR`` ends at September 30th, 2023. End of Support From 8cdd9ec641933fb7d40dd24b9c971b706e3f5663 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 Feb 2023 17:31:19 +0200 Subject: [PATCH 0434/1892] Update conf.py --- conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index 104b75e03..2fee1f392 100644 --- a/conf.py +++ b/conf.py @@ -21,12 +21,12 @@ # -- Project information ----------------------------------------------------- project = 'SQream DB' -copyright = '2022 SQream' +copyright = '2023 SQream' author = 'SQream Documentation' # The full version, including alpha/beta/rc tags -release = '2022.1.7' +release = '4.1' From 3ba77725ad544bde0899d0d135ed0e622e7baf43 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Feb 2023 09:57:06 +0200 Subject: [PATCH 0435/1892] Transactions --- feature_guides/index.rst | 1 - feature_guides/transactions.rst | 17 ----------------- reference/sql_feature_support.rst | 6 ++---- 3 files changed, 2 insertions(+), 22 deletions(-) delete mode 100644 feature_guides/transactions.rst diff --git a/feature_guides/index.rst b/feature_guides/index.rst index abb975c5d..4fe0652ce 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -17,6 +17,5 @@ This section describes the following features: compression python_functions workload_manager - transactions concurrency_and_locks concurrency_and_scaling_in_sqream \ No newline at end of file diff --git a/feature_guides/transactions.rst b/feature_guides/transactions.rst deleted file mode 100644 index 675957d51..000000000 --- a/feature_guides/transactions.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _transactions: - -*********************** -Transactions -*********************** - -SQream DB supports serializable transactions. This is also called 'ACID compliance'. - -The implementation of transactions means that commit, rollback and recovery are all extremely fast. - -SQream DB has extremely fast bulk insert speed, with minimal slowdown when running concurrent inserts. There is no performance reason to break large inserts up into multiple transactions. - -The phrase "supporting transactions" for a database system sometimes means having good performance for OLTP workloads, SQream DB's transaction system does not have high performance for high concurrency OLTP workloads. - -SQream DB also supports :ref:`transactional DDL<ddl_commands_list>`. - - diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 4443d631a..d940215b0 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -64,10 +64,10 @@ Read more about :ref:`Yes data types<data_types>`. - Can be stored as a text string or as part of a ``DATETIME`` -Contraints +Constraints =============== -.. list-table:: Contraints +.. list-table:: Constraints :widths: auto :header-rows: 1 @@ -92,8 +92,6 @@ SQream DB treats each statement as an auto-commit transaction. Each transaction If a statement fails, the entire transaction is cancelled and rolled back. The database is unchanged. -Read more about :ref:`transactions in SQream DB<transactions>`. - Indexes ============ From 7943c19eeca507cf77d5be9b3e93f1911a234041 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:10:12 +0200 Subject: [PATCH 0436/1892] Kafka --- .../client_drivers/Kafka/index.rst | 257 ++++++++++++++++++ connecting_to_sqream/client_drivers/index.rst | 5 + 2 files changed, 262 insertions(+) create mode 100644 connecting_to_sqream/client_drivers/Kafka/index.rst diff --git a/connecting_to_sqream/client_drivers/Kafka/index.rst b/connecting_to_sqream/client_drivers/Kafka/index.rst new file mode 100644 index 000000000..313a90f28 --- /dev/null +++ b/connecting_to_sqream/client_drivers/Kafka/index.rst @@ -0,0 +1,257 @@ +.. _kafka: + +************************* +Connecting to SQream Using Kafka +************************* + +If you are using Kafka Apache for distributed streaming and wish to use it with SQream, follow these instructions. +We support multi-topic streaming which means that numerous instances are required to be + + +.. contents:: + :local: + :depth: 1 + + +Before You Begin +================ + +* You must have JAVA 11 installed +* You must have `JDBC <java_jdbc>`_ deployed +* Your network bandwidth must be at least 100 mega per second +* Supported data formats for streamed data is JSON - Remove +* Kafka *** + +High Level Workflow +=================== + +1. Deploy the JDBC Connector. +2. Install kafka_2.12-3.2.1 +3. Configure +3. Run your Kafka Connect API. +4. + + + +Installation and Configuration +============================== + +Before you configure the Kafka Connector, make sure that Kafka and Zookeeper are both running. + +Kafka Connector workflow: + +.. figure:: /_static/images/kafka_flow.png + +.. contents:: + :local: + :depth: 1 + +Sink Connector +--------------- + +Download sink connector + +The Sink Connector reads JSON format Kafka topics and writes the messages inside each topic into text files. The files are created with the extension ``.tmp`` and stored in a specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file, and when the specified number is reached, the Sink Connector closes the file, renames it to ``sqream.fileExtension``, and then creates a new file. Unlike data streaming, which continuously sends data from the Kafka topic to the database, the Sink Connector only sends the data when the file size reaches a predefined threshold. This means that data will arrive in batches. + +SQream tables must be created according to the columns configured in ``csvorder``. + + +Sink Connector Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Configuration file structure: + + .. code-block:: postgres + + name=SQReamFileSink + topics=topsqreamtest1 + tasks.max=4 + connector.class=tr.com.entegral.FileSinkConnector + errors.tolerance=all + errors.log.enable=true + errors.log.include.messages=true + value.converter=org.apache.kafka.connect.json.JsonConverter + value.converter.schemas.enable=false + transforms=flatten + transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value + transforms.flatten.delimiter=. + sqream.outputdir=/home/sqream/kafkaconnect/outputs + sqream.batchRecordCount =10 + sqream.fileExtension=csv + sqream.removeNewline =false + sqream.outputType=csv + sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv + +The following parameters require configuration. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - Topic + - A category or feed name to which messages are published and subscribed to + * - ``sqream.batchrecordcount`` + - The record count to be written to each file + * - ``outputdir`` + - Copy the ``sqream.outputdir`` path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path + * - ``csvorder`` + - Defines table columns. SQream table columns must align with the ``csvorder`` table columns + + +Connection string: + + .. code-block:: postgres + + vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties + +Running commands: + + .. code-block:: postgres + + export JAVA_HOME=/home/sqream/copy-from-util/jdk-11;export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar;cd /home/sqream/kafkaconnect1/kafka/bin/ && ./connect-standalone.sh /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/connect-standalone.properties /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties & + + + + +JDBC +------------- + +The JDBC connector can be used to ingest data from Kafka, allowing SQream DB to consume the messages directly. This enables efficient and secure data ingestion into SQream DB. + +.. contents:: + :local: + :depth: 1 + +JDBC Configuration +~~~~~~~~~~~~~~~~~~ + +.. code-block:: postgres + vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-jdbcsink.properties + +Example + +.. code-block:: postgres + + name=SQReamJDBCSink + topics=demo1 + tasks.max=1 + connector.class=tr.com.entegral.JDBCSinkConnector + errors.tolerance=all + errors.log.enable=true + errors.log.include.messages=true + value.converter=org.apache.kafka.connect.json.JsonConverter + value.converter.schemas.enable=false + transforms=flatten + transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value + transforms.flatten.delimiter=. + sqream.batchRecordCount =3 + #sqream.jdbc.connectionstring=jdbc:sqlserver://localhost;databaseName=TestDB;user=kafka;password=kafka;encrypt=true;trustServerCertificate=true; + sqream.jdbc.connectionstring=jdbc:Sqream://192.168.0.102:5001/kafka;user=sqream;password=sqream;cluster=false + sqream.input.inputfields=intStr,inInt,indateTime,inFloat + sqream.jdbc.tablename=testtable + sqream.jdbc.table.columnnames=colStr,colInt,Coldatetime,ColFloat + sqream.jdbc.table.columntypes=VARCHAR,INTEGER,TIMESTAMP,FLOAT + sqream.jdbc.dateformat=yyyy-MM-dd HH:mm:ss + +SQream Loader Configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +Building the SQream Loader: + + .. code-block:: postgres + + git clone -b develop http://gitlab.sq.l/java/copy-from-util.git + mvn clean package + + +Running the SQream Loader: + + .. code-block:: postgres + + git clone -b develop http://gitlab.sq.l/java/copy-from-util.git + mvn clean package + +What needs to be configured: + +.. list-table:: + :widths: auto + :header-rows: 1 + + + * - Parameter + - Description + * - ``root`` + – paste copied path to root + * - ``schema`` + - + * - ``name`` + - + +Configuration file structure: + + .. code-block:: postgres + + #config.yaml + + com: + sqream: + kafka: + common: + root: "/home/sqream/copy_from_root" + readyFileSuffix: ".csv" + connection: + ip: "127.0.0.1" + port: 3108 + database: "master" + cluster: true + user: sqream + pass: sqream + delimiter: "," + tables: + - schema: "public" + name: "t1" + parallel: 5 + - schema: "public" + name: "t2" + parallel: 3 + - schema: "public" + name: "t3" + parallel: 1 + + + + +Running commands: + + .. code-block:: postgres + + /home/sqream/copy-from-util/jdk-11/bin/java -jar /home/sqream/copy-from-util/copy-from-util/target/copy-from-util-0.0.1-SNAPSHOT.jar --spring.config.additional-location=/home/sqream/copy-from-util/config.yaml & + +Logging and Monitoring +======================== + +The following log files are created: + * JAVA application fails (consumer or loader?) + * Files cannot be saved to folder due to +Either + * Folder permission issue +Or + * SQream loader folder is not the same as Kenan folder + +Purging +======= +Ingested files are automatically zipped and archived for 60 days. +User needs to prepare storage. +User may configure archive time. + +Limitations +=========== + +Latency +Retention + +Examples +========= diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 7ffd95138..ff35fed10 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -64,6 +64,11 @@ The following are applicable to all operating systems: * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) * :ref:`power_bi` + +* **Kafka**: + + * :ref:`Kafka<kafka>` + Windows From 47e5fa6c3681de2b394a1b11342cc82c196e549d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Feb 2023 11:16:53 +0200 Subject: [PATCH 0437/1892] Update index.rst --- connecting_to_sqream/client_drivers/Kafka/index.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Kafka/index.rst b/connecting_to_sqream/client_drivers/Kafka/index.rst index 313a90f28..a69b5503f 100644 --- a/connecting_to_sqream/client_drivers/Kafka/index.rst +++ b/connecting_to_sqream/client_drivers/Kafka/index.rst @@ -20,16 +20,17 @@ Before You Begin * You must have `JDBC <java_jdbc>`_ deployed * Your network bandwidth must be at least 100 mega per second * Supported data formats for streamed data is JSON - Remove -* Kafka *** +* Kafka 2.12-3.2.1 High Level Workflow =================== -1. Deploy the JDBC Connector. -2. Install kafka_2.12-3.2.1 -3. Configure -3. Run your Kafka Connect API. -4. +1. Deploy the JDBC Connector +2. Download Sink Connector +3. Configure Sink Connector +4. Download SQream Loader +5. Configure SQream Loader +6. Run your Kafka Connect API From 9d365085aceb0ce7cbf99ab299b6f3c7b0e28d3d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Feb 2023 14:03:37 +0200 Subject: [PATCH 0438/1892] Kafka --- .../client_drivers/Kafka/index.rst | 258 ------------------ connecting_to_sqream/client_drivers/index.rst | 3 - 2 files changed, 261 deletions(-) delete mode 100644 connecting_to_sqream/client_drivers/Kafka/index.rst diff --git a/connecting_to_sqream/client_drivers/Kafka/index.rst b/connecting_to_sqream/client_drivers/Kafka/index.rst deleted file mode 100644 index a69b5503f..000000000 --- a/connecting_to_sqream/client_drivers/Kafka/index.rst +++ /dev/null @@ -1,258 +0,0 @@ -.. _kafka: - -************************* -Connecting to SQream Using Kafka -************************* - -If you are using Kafka Apache for distributed streaming and wish to use it with SQream, follow these instructions. -We support multi-topic streaming which means that numerous instances are required to be - - -.. contents:: - :local: - :depth: 1 - - -Before You Begin -================ - -* You must have JAVA 11 installed -* You must have `JDBC <java_jdbc>`_ deployed -* Your network bandwidth must be at least 100 mega per second -* Supported data formats for streamed data is JSON - Remove -* Kafka 2.12-3.2.1 - -High Level Workflow -=================== - -1. Deploy the JDBC Connector -2. Download Sink Connector -3. Configure Sink Connector -4. Download SQream Loader -5. Configure SQream Loader -6. Run your Kafka Connect API - - - -Installation and Configuration -============================== - -Before you configure the Kafka Connector, make sure that Kafka and Zookeeper are both running. - -Kafka Connector workflow: - -.. figure:: /_static/images/kafka_flow.png - -.. contents:: - :local: - :depth: 1 - -Sink Connector ---------------- - -Download sink connector - -The Sink Connector reads JSON format Kafka topics and writes the messages inside each topic into text files. The files are created with the extension ``.tmp`` and stored in a specified directory. The ``sqream.batchRecordCount`` parameter defines the number of records to be written to each file, and when the specified number is reached, the Sink Connector closes the file, renames it to ``sqream.fileExtension``, and then creates a new file. Unlike data streaming, which continuously sends data from the Kafka topic to the database, the Sink Connector only sends the data when the file size reaches a predefined threshold. This means that data will arrive in batches. - -SQream tables must be created according to the columns configured in ``csvorder``. - - -Sink Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Configuration file structure: - - .. code-block:: postgres - - name=SQReamFileSink - topics=topsqreamtest1 - tasks.max=4 - connector.class=tr.com.entegral.FileSinkConnector - errors.tolerance=all - errors.log.enable=true - errors.log.include.messages=true - value.converter=org.apache.kafka.connect.json.JsonConverter - value.converter.schemas.enable=false - transforms=flatten - transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value - transforms.flatten.delimiter=. - sqream.outputdir=/home/sqream/kafkaconnect/outputs - sqream.batchRecordCount =10 - sqream.fileExtension=csv - sqream.removeNewline =false - sqream.outputType=csv - sqream.csvOrder=receivedTime,equipmentId,asdf,timestamp,intv - -The following parameters require configuration. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - Topic - - A category or feed name to which messages are published and subscribed to - * - ``sqream.batchrecordcount`` - - The record count to be written to each file - * - ``outputdir`` - - Copy the ``sqream.outputdir`` path, from its beginning and until ``outputs``, included, and save it to a known location. It is required to configure SQream loader to use this section of the path - * - ``csvorder`` - - Defines table columns. SQream table columns must align with the ``csvorder`` table columns - - -Connection string: - - .. code-block:: postgres - - vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties - -Running commands: - - .. code-block:: postgres - - export JAVA_HOME=/home/sqream/copy-from-util/jdk-11;export CLASSPATH=.:$JAVA_HOME/jre/lib:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar;cd /home/sqream/kafkaconnect1/kafka/bin/ && ./connect-standalone.sh /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/connect-standalone.properties /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-filesink.properties & - - - - -JDBC -------------- - -The JDBC connector can be used to ingest data from Kafka, allowing SQream DB to consume the messages directly. This enables efficient and secure data ingestion into SQream DB. - -.. contents:: - :local: - :depth: 1 - -JDBC Configuration -~~~~~~~~~~~~~~~~~~ - -.. code-block:: postgres - vi /home/sqream/kafkaconnect1/sqream-kafka-connector/sqream-kafkaconnect/config/sqream-jdbcsink.properties - -Example - -.. code-block:: postgres - - name=SQReamJDBCSink - topics=demo1 - tasks.max=1 - connector.class=tr.com.entegral.JDBCSinkConnector - errors.tolerance=all - errors.log.enable=true - errors.log.include.messages=true - value.converter=org.apache.kafka.connect.json.JsonConverter - value.converter.schemas.enable=false - transforms=flatten - transforms.flatten.type=org.apache.kafka.connect.transforms.Flatten$Value - transforms.flatten.delimiter=. - sqream.batchRecordCount =3 - #sqream.jdbc.connectionstring=jdbc:sqlserver://localhost;databaseName=TestDB;user=kafka;password=kafka;encrypt=true;trustServerCertificate=true; - sqream.jdbc.connectionstring=jdbc:Sqream://192.168.0.102:5001/kafka;user=sqream;password=sqream;cluster=false - sqream.input.inputfields=intStr,inInt,indateTime,inFloat - sqream.jdbc.tablename=testtable - sqream.jdbc.table.columnnames=colStr,colInt,Coldatetime,ColFloat - sqream.jdbc.table.columntypes=VARCHAR,INTEGER,TIMESTAMP,FLOAT - sqream.jdbc.dateformat=yyyy-MM-dd HH:mm:ss - -SQream Loader Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -Building the SQream Loader: - - .. code-block:: postgres - - git clone -b develop http://gitlab.sq.l/java/copy-from-util.git - mvn clean package - - -Running the SQream Loader: - - .. code-block:: postgres - - git clone -b develop http://gitlab.sq.l/java/copy-from-util.git - mvn clean package - -What needs to be configured: - -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Parameter - - Description - * - ``root`` - – paste copied path to root - * - ``schema`` - - - * - ``name`` - - - -Configuration file structure: - - .. code-block:: postgres - - #config.yaml - - com: - sqream: - kafka: - common: - root: "/home/sqream/copy_from_root" - readyFileSuffix: ".csv" - connection: - ip: "127.0.0.1" - port: 3108 - database: "master" - cluster: true - user: sqream - pass: sqream - delimiter: "," - tables: - - schema: "public" - name: "t1" - parallel: 5 - - schema: "public" - name: "t2" - parallel: 3 - - schema: "public" - name: "t3" - parallel: 1 - - - - -Running commands: - - .. code-block:: postgres - - /home/sqream/copy-from-util/jdk-11/bin/java -jar /home/sqream/copy-from-util/copy-from-util/target/copy-from-util-0.0.1-SNAPSHOT.jar --spring.config.additional-location=/home/sqream/copy-from-util/config.yaml & - -Logging and Monitoring -======================== - -The following log files are created: - * JAVA application fails (consumer or loader?) - * Files cannot be saved to folder due to -Either - * Folder permission issue -Or - * SQream loader folder is not the same as Kenan folder - -Purging -======= -Ingested files are automatically zipped and archived for 60 days. -User needs to prepare storage. -User may configure archive time. - -Limitations -=========== - -Latency -Retention - -Examples -========= diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index ff35fed10..6f8f5909a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -65,9 +65,6 @@ The following are applicable to all operating systems: * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) * :ref:`power_bi` -* **Kafka**: - - * :ref:`Kafka<kafka>` From 38db8fc9f8b5c51d42094f15fafb521b9b833007 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Feb 2023 17:22:23 +0200 Subject: [PATCH 0439/1892] Update alter_default_permissions.rst --- .../access_control_commands/alter_default_permissions.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index a49e53f88..d9849602a 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -36,9 +36,7 @@ The following is the syntax for altering default permissions: grant_clause ::= GRANT - { CREATE FUNCTION - | SUPERUSER - | CONNECT + { SUPERUSER | CREATE | USAGE | SELECT @@ -46,7 +44,6 @@ The following is the syntax for altering default permissions: | UPDATE | DELETE | DDL - | EXECUTE | ALL } From 47da8645e21a0d441a813e92cd317679f552f746 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Feb 2023 10:10:14 +0200 Subject: [PATCH 0440/1892] Update get_statement_permissions.rst --- .../get_statement_permissions.rst | 55 ++++++++++++++++++- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst index 0846c5cc4..f83a2efb2 100644 --- a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst @@ -58,9 +58,58 @@ If the statement requires no special permissions, the utility returns an empty r * - ``object_name`` - The object name -.. include:: grant.rst - :start-line: 127 - :end-line: 180 +The following table describes the supported permissions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Permission + - Object + - Description + * - ``LOGIN`` + - Cluster + - Login permissions (with a password) allows a role to be a user and login to a database + * - ``PASSWORD`` + - Cluster + - Sets the password for a user role + * - ``CREATE FUNCTION`` + - Database + - Allows a user to :ref:`create a Python UDF<create_function>` + * - ``SUPERUSER`` + - Cluster, Database, Schema + - The most privileged role, with full control over a cluster, database, or schema + * - ``CONNECT`` + - Database + - Allows a user to connect and use a database + * - ``CREATE`` + - Database, Schema + - For a role to create and manage objects, it needs the ``CREATE`` and ``USAGE`` permissions at the respective level + * - ``USAGE`` + - Schema + - For a role to see tables in a schema, it needs the ``USAGE`` permissions + * - ``SELECT`` + - Table + - Allows a user to run :ref:`select` queries on table contents + * - ``INSERT`` + - Table + - Allows a user to run :ref:`copy_from` and :ref:`insert` statements to load data into a table + * - ``UPDATE`` + - Table + - Allows a user to modify the value of certain columns in existing rows without creating a table + * - ``DELETE`` + - Table + - Allows a user to run :ref:`delete`, :ref:`truncate` statements to delete data from a table + * - ``DDL`` + - Database, Schema, Table, Function + - Allows a user to :ref:`alter tables<alter_table>`, rename columns and tables, etc. + * - ``EXECUTE`` + - Function + - Allows a user to execute UDFs + * - ``ALL`` + - Cluster, Database, Schema, Table, Function + - All of the above permissions at the respective level + Examples =========== From 5372bf05619beab908786abe2eff090a7f4462db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Feb 2023 11:56:40 +0200 Subject: [PATCH 0441/1892] ascii --- reference/sql/sql_functions/index.rst | 2 + .../sql_functions/scalar_functions/index.rst | 3 +- .../scalar_functions/string/decode.rst | 12 ++--- .../scalar_functions/string/select_ascii.rst | 46 +++++++++++++++++++ 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 reference/sql/sql_functions/scalar_functions/string/select_ascii.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index a66760b7f..af0b0e166 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -267,6 +267,8 @@ The following table shows the **string** functions: - Trims whitespaces from an argument * - :ref:`upper` - Converts an argument to an upper-case equivalent + * - :ref:`select_ascii` + - Return the ASCII code value of the leftmost character of a string User-Defined Scalar Functions --------------------- diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index ae70874e3..a3dd88448 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -83,4 +83,5 @@ The **Built-In Scalar Functions** page describes functions that return one value * :ref:`rtrim` * :ref:`substring` * :ref:`trim` - * :ref:`upper` \ No newline at end of file + * :ref:`upper` + * :ref:`select_ascii` \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst index 1ed10e399..a83b027b2 100644 --- a/reference/sql/sql_functions/scalar_functions/string/decode.rst +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -3,7 +3,7 @@ ******************** DECODE ******************** -The **DECODE** function is a PostgreSQL function used for decoding or extracting binary data from a textual input string. +The **DECODE** function is used for decoding or extracting binary data from a textual input string. Syntax ========== @@ -11,7 +11,7 @@ The following shows the correct syntax for the DECODE function: .. code-block:: postgres - decode(string input_text, format type_text) + DECODE(string input_text, format type_text) Parameters ============ @@ -30,18 +30,14 @@ The following table shows the DECODE parameters: Returns ========= -**Comment** - *What does it return?* -Notes -=========== -**Comment** - *Are there any relevant notes?* + Examples =========== -**Comment** - *What does the actual output look like? Can you provide an example?* + Permissions ============= -**Comment** - *Please confirm what permissions the role requires.* The role must have the ``SUPERUSER`` permissions. \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst new file mode 100644 index 000000000..cf9e2c058 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst @@ -0,0 +1,46 @@ +.. _select_ascii: + +******************** +SELECT ASCII +******************** +The **SELECT ASCII** function is used to return the ASCII code value of the leftmost character of a string. + +Syntax +========== +The following shows the syntax for the SELECT ASCII function: + +.. code-block:: postgres + + SELECT ASCII(''); + +Parameters +============ +The following table shows the DECODE parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - + - + * - + - + +Returns +========= + +The SELECT ASCII function returns ``integer``. + +Example +=========== +.. code-block:: postgres + + SELECT ASCII('hello'); + + +Permissions +============= + +The role must have the ``SUPERUSER`` permissions. \ No newline at end of file From 647b0f526d0da53ed2b33387b7998292b7770e28 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Feb 2023 13:47:32 +0200 Subject: [PATCH 0442/1892] ASCII --- .../scalar_functions/string/select_ascii.rst | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst index cf9e2c058..562a7e355 100644 --- a/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst @@ -3,7 +3,7 @@ ******************** SELECT ASCII ******************** -The **SELECT ASCII** function is used to return the ASCII code value of the leftmost character of a string. +The **SELECT ASCII** function is commonly used in combination with other SQL functions for operations such as data transformation, validation, and storing based on ASCII values. Syntax ========== @@ -13,34 +13,13 @@ The following shows the syntax for the SELECT ASCII function: SELECT ASCII(''); -Parameters -============ -The following table shows the DECODE parameters: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - - - - * - - - - Returns ========= -The SELECT ASCII function returns ``integer``. +The SELECT ASCII function returns the ASCII code value of the leftmost character of a string. Example =========== .. code-block:: postgres SELECT ASCII('hello'); - - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. \ No newline at end of file From 30c16898cbf53e2bd66ba28e72075453810a1582 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 26 Feb 2023 09:44:13 +0200 Subject: [PATCH 0443/1892] Update 4.1.rst --- releases/4.1.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index bb6f9a290..6c502e377 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -15,7 +15,7 @@ The 4.1 release notes were released on xx/xx/20xx and describe the following: New Features ------------ - * :ref:`Lightweight Directory Access Protocol (LDAP)<ldap>` enhanced management + * :ref:`Lightweight Directory Access Protocol (LDAP)<ldap>` management enhancement :: @@ -23,7 +23,7 @@ New Features :: - * A brute-force attack protection locks out user accounts for 15 minutes following 5 consecutive failed login attempts + * A new brute-force attack protection mechanism locks out user accounts for 15 minutes following 5 consecutive failed login attempts SQream Studio Updates and Improvements -------------------------------------- From 4e752088785c6ddd9f71f394d49c6413e66e8626 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 26 Feb 2023 11:23:01 +0200 Subject: [PATCH 0444/1892] Update 4.0.rst --- releases/4.0.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/releases/4.0.rst b/releases/4.0.rst index c0b47b5b8..1db6492d2 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -46,6 +46,8 @@ Version 4.0 resolved Issues +========================+==========================================================================================+ | SQ-10544 | SQream Studio dashboard periodic update enhancement | +------------------------+------------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++------------------------+------------------------------------------------------------------------------------------+ | SQ-11772 | Slow query performance when using ``JOIN`` clause | +------------------------+------------------------------------------------------------------------------------------+ | SQ-12318 | JDBC ``insertBuffer`` parameter issue | @@ -58,8 +60,12 @@ Version 4.0 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | SQ-12580 | Server Picker GPU dependency | +------------------------+------------------------------------------------------------------------------------------+ +| SQ-12598 | Executing ``SELECT`` on a foreign table with no valid path produces no error message | ++------------------------+------------------------------------------------------------------------------------------+ | SQ-12652 | SQream Studio result panel adjustment | +------------------------+------------------------------------------------------------------------------------------+ +| SQ-13055 | NULL issue when executing query with pysqream | ++------------------------+------------------------------------------------------------------------------------------+ Configuration Changes From 15110ae5b35b0d019e42d9f3a069c825c45a3428 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 26 Feb 2023 11:53:07 +0200 Subject: [PATCH 0445/1892] Update 4.0.rst --- releases/4.0.rst | 51 ++++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/releases/4.0.rst b/releases/4.0.rst index 1db6492d2..65e8c25f5 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -41,31 +41,32 @@ Known Issues Version 4.0 resolved Issues ----------------------------- -+------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+==========================================================================================+ -| SQ-10544 | SQream Studio dashboard periodic update enhancement | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow query performance when using ``JOIN`` clause | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12446 | SQream Studio group role modification issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker GPU dependency | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12598 | Executing ``SELECT`` on a foreign table with no valid path produces no error message | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12652 | SQream Studio result panel adjustment | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13055 | NULL issue when executing query with pysqream | -+------------------------+------------------------------------------------------------------------------------------+ ++-----------------+---------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++=================+=======================================================================================+ +| SQ-10544 | SQream Studio dashboard periodic update enhancement | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-11296 | Slow catalog queries | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-11772 | Slow query performance when using ``JOIN`` clause | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12318 | JDBC ``insertBuffer`` parameter issue | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12364 | ``GET DDL`` foreign table output issue | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12446 | SQream Studio group role modification issue | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12468 | Internal compiler error | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker GPU dependency | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12598 | Executing ``SELECT`` on a foreign table with no valid path produces no error message | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-12652 | SQream Studio result panel adjustment | ++-----------------+---------------------------------------------------------------------------------------+ +| SQ-13055 | NULL issue when executing query with pysqream | ++-----------------+---------------------------------------------------------------------------------------+ + Configuration Changes From ab2e1f3403eb917c72165be22be2fc981bb47ce4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 26 Feb 2023 13:57:55 +0200 Subject: [PATCH 0446/1892] Update installing_sqream_with_binary.rst --- installation_guides/installing_sqream_with_binary.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index 7a3c7fff8..6a21ee29f 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -272,6 +272,6 @@ For an example of stopping actively running SQream services, see :ref:`Launching 1 row time: 0.050603s -For more information, see the `upgrade_storage <https://docs.sqream.com/en/v2020-1/reference/cli/upgrade_storage.html>`_ command line program. +For more information, see the :ref:`upgrade_storage<upgrade_storage_cli_reference>` command line program. -For more information about installing Studio on a stand-alone server, see `Installing Studio on a Stand-Alone Server <https://docs.sqream.com/en/v2020-1/installation_guides/installing_studio_on_stand_alone_server.html>`_. \ No newline at end of file +For more information about installing Studio on a stand-alone server, see :ref:`Installing Studio on a Stand-Alone Server<installing_studio_on_stand_alone_server>`. \ No newline at end of file From 6bef242d21cec8e544673ea9379e1c020ee94ffe Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 26 Feb 2023 17:34:27 +0200 Subject: [PATCH 0447/1892] SIGN function --- reference/sql/sql_functions/index.rst | 2 + .../sql_functions/scalar_functions/index.rst | 3 +- .../scalar_functions/numeric/sign.rst | 53 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 reference/sql/sql_functions/scalar_functions/numeric/sign.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index af0b0e166..b06a754f7 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -206,6 +206,8 @@ The following table shows the **arithmetic operator** functions: - Calculates the tangent of an argument * - :ref:`trunc` - Rounds a number to its integer representation towards 0 + * - :ref:`sign` + - Returns an integer value of -1, 0, or 1, depending on the sign of the input expression. Strings ^^^^^^^^^^^ diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index a3dd88448..aac74d8e2 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -84,4 +84,5 @@ The **Built-In Scalar Functions** page describes functions that return one value * :ref:`substring` * :ref:`trim` * :ref:`upper` - * :ref:`select_ascii` \ No newline at end of file + * :ref:`select_ascii` + * :ref:`sign` \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst new file mode 100644 index 000000000..1fc32d1b7 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst @@ -0,0 +1,53 @@ +.. _sign: + +************************** +SIGN +************************** + +The SIGN function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL. The function returns an integer value of -1, 0, or 1, depending on the sign of the input expression. + + + +Syntax +========== + +.. code-block:: postgres + + SELECT SIGN (); + +Arguments +========= + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``numeric_expression`` + - Numeric data types + +Returns +============ + +* -1 if the input expression is negative + +* 0 if the input expression is zero + +* 1 if the input expression is positive + + +Example +======= + +.. code-block:: postgres + + SELECT SIGN(-10), SIGN(0), SIGN(5) ; + +Output: + +.. code-block:: postgres + + sign | sign0 | sign1 + -----+------+------- + -1 | 0 | 1 From 88785ce02dc52dd28b5501076ec493954519c9ce Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Feb 2023 13:22:37 +0200 Subject: [PATCH 0448/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 2d8b9bf0e..e0a3efa24 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -11,27 +11,27 @@ The following table displays the access control permissions: +====================+=========================================================================================================================+ | **Object/Layer: All Databases** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``LOGIN`` | use role to log into the system (the role also needs connect permission on the database it is connecting to) | +| ``LOGIN`` | Use role to log into the system (the role also needs connect permission on the database it is connecting to) | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``PASSWORD`` | the password used for logging into the system | +| ``PASSWORD`` | The password used for logging into the system | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SUPERUSER`` | no permission restrictions on any activity | +| ``SUPERUSER`` | No permission restrictions on any activity | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Database** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SUPERUSER`` | no permission restrictions on any activity within that database (this does not include modifying roles or permissions) | +| ``SUPERUSER`` | No permission restrictions on any activity within that database (this does not include modifying roles or permissions) | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CONNECT`` | connect to the database | +| ``CONNECT`` | Connect to the database | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | create schemas in the database | +| ``CREATE`` | Create schemas in the database | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE FUNCTION``| create and drop functions | +| ``CREATE FUNCTION``| Create and drop functions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Schema** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``USAGE`` | allows additional permissions within the schema | +| ``USAGE`` | Grants access to schema objects | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | create tables in the schema | +| ``CREATE`` | Create tables in the schema | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Table** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -43,17 +43,17 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | drop and alter on the table | +| ``DDL`` | Drop and alter on the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | all the table permissions | +| ``ALL`` | All the table permissions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Function** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``EXECUTE`` | use the function | +| ``EXECUTE`` | Use the function | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | drop and alter on the function | +| ``DDL`` | Drop and alter on the function | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | all function permissions | +| ``ALL`` | All function permissions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ From a2b20ecbbe58a00f4ee4d70c3559c2d8084df15f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Feb 2023 17:10:27 +0200 Subject: [PATCH 0449/1892] alter_default_permissions --- .../client_drivers/odbc/index.rst | 4 +- .../scalar_functions/numeric/sqrt.rst | 2 +- .../scalar_functions/string/decode.rst | 19 +++---- .../alter_default_permissions.rst | 50 +++++++++++++++---- 4 files changed, 49 insertions(+), 26 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 691e7e999..4494ef4ec 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -1,7 +1,7 @@ .. _odbc: ************************* -Connecting to SQream Using ODBC +ODBC ************************* .. toctree:: @@ -38,8 +38,6 @@ SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to in Other distributions may also work, but are not officially supported by SQream. -.. contents:: In this topic: - :local: Downloading the ODBC driver ================================== diff --git a/reference/sql/sql_functions/scalar_functions/numeric/sqrt.rst b/reference/sql/sql_functions/scalar_functions/numeric/sqrt.rst index cda10c4e9..41654db67 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/sqrt.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/sqrt.rst @@ -60,7 +60,7 @@ For these examples, consider the following table and contents: 1.4142135623730951 .. note:: - * ``SQRT`` always returns a floating point result. + * Some clients may show fewer digits. See your client settings to change the precision shown. Replacing negative values with ``NULL`` diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst index a83b027b2..9530341b2 100644 --- a/reference/sql/sql_functions/scalar_functions/string/decode.rst +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -3,7 +3,7 @@ ******************** DECODE ******************** -The **DECODE** function is used for decoding or extracting binary data from a textual input string. +The **DECODE** function is used to translate a code value into a corresponding value that is meaningful to humans. This function is typically used in situations where a code needs to be presented to a user in a more understandable format, such as when displaying data in a report or on a user interface. Syntax ========== @@ -11,7 +11,7 @@ The following shows the correct syntax for the DECODE function: .. code-block:: postgres - DECODE(string input_text, format type_text) + DECODE(string input_text, format type_text); Parameters ============ @@ -28,16 +28,9 @@ The following table shows the DECODE parameters: * - ``type_text`` - Defines the format used for decoding the input text. -Returns -========= +Return +====== +Returns the same type as the argument supplied. - -Examples -=========== - - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. \ No newline at end of file + diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index d9849602a..4234267e2 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -3,7 +3,6 @@ ***************************** ALTER DEFAULT PERMISSIONS ***************************** -The **ALTER DEFAULT PERMISSIONS** page describes the following: .. contents:: :local: @@ -28,11 +27,11 @@ The following is the syntax for altering default permissions: .. code-block:: postgres alter_default_permissions_statement ::= - ALTER DEFAULT PERMISSIONS FOR target_role_name + ALTER DEFAULT PERMISSIONS FOR { target_role_name | ALL ROLES } [IN schema_name, ...] FOR { TABLES | SCHEMAS } - { grant_clause | DROP grant_clause} - TO ROLE { role_name | public }; + { grant_clause [, ...] | DROP grant_clause[, ...]} + TO { role_name [, ...] | public }; grant_clause ::= GRANT @@ -45,7 +44,7 @@ The following is the syntax for altering default permissions: | DELETE | DDL | ALL - } + } [, ...] target_role_name ::= identifier @@ -54,13 +53,46 @@ The following is the syntax for altering default permissions: schema_name ::= identifier -.. include:: grant.rst - :start-line: 127 - :end-line: 180 +Supported Permissions +======================= +The following table describes the supported permissions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Permission + - Object + - Description + * - ``SUPERUSER`` + - Cluster, Database, Schema + - The most privileged role, with full control over a cluster, database, or schema + * - ``CREATE`` + - Database, Schema + - For a role to create and manage objects, it needs the ``CREATE`` and ``USAGE`` permissions at the respective level + * - ``USAGE`` + - Schema + - For a role to see tables in a schema, it needs the ``USAGE`` permissions + * - ``SELECT`` + - Table + - Allows a user to run :ref:`select` queries on table contents + * - ``INSERT`` + - Table + - Allows a user to run :ref:`copy_from` and :ref:`insert` statements to load data into a table + * - ``UPDATE`` + - Table + - Allows a user to modify the value of certain columns in existing rows without creating a table + * - ``DELETE`` + - Table + - Allows a user to run :ref:`delete`, :ref:`truncate` statements to delete data from a table + * - ``DDL`` + - Database, Schema, Table, Function + - Allows a user to :ref:`alter tables<alter_table>`, rename columns and tables, etc. + + Examples ============ -This section includes the following examples: .. contents:: :local: From 833e837c74b2257ad42b6e634e4ce089cf1be5d2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 1 Mar 2023 09:20:46 +0200 Subject: [PATCH 0450/1892] 4.1 release finishes --- releases/4.0.0.rst | 127 --------------------------------------- releases/4.0.0_index.rst | 16 ----- releases/4.1.rst | 4 +- releases/index.rst | 2 + 4 files changed, 4 insertions(+), 145 deletions(-) delete mode 100644 releases/4.0.0.rst delete mode 100644 releases/4.0.0_index.rst diff --git a/releases/4.0.0.rst b/releases/4.0.0.rst deleted file mode 100644 index 95bfb7aab..000000000 --- a/releases/4.0.0.rst +++ /dev/null @@ -1,127 +0,0 @@ -.. _4.0.0: - -************************** -Release Notes 4.0.0 -************************** - -SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0.0 version** is a minor version upgrade and does not require considerable preparation. - -The 4.0.0 release notes were released on xx/xx/20xx and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - - * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature - - :: - - * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles - - :: - - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities - -SQream Studio Updates and Improvements --------------------------------------- - - * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. - - :: - -Known Issues ------------- -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 4.0.0 resolved Issues ------------------------------ - -+------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+==========================================================================================+ -| SQ-10544 | SQream Studio Worker Panel issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11199 | AWS S3 internal runtime error when executing ``COPY TO`` statement | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11296 | Slow catalog queries | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11772 | Slow ``JOIN`` query | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-11948 | ``SAVED QUERY`` execution using ``SELECT`` or ``INSERT INTO`` returns error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12228 | ``CREATE AS SELECT`` statement fails when executed with ``UNION ALL`` and ``GROUP BY`` | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12310 | ``DICT`` compression buffer size issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12318 | JDBC ``insertBuffer`` parameter issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12364 | ``GET DDL`` foreign table output issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12468 | Internal compiler error | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker GPU dependency | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-12652 + 12844 | SQream Studio result panel adjustment | -+------------------------+------------------------------------------------------------------------------------------+ - - -Configuration Changes ---------------------- -No configuration changes were made. - -Naming Changes --------------- -No relevant naming changes were made. - -Deprecated Features -------------------- -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support ---------------- -No End of Support changes were made. - -Upgrading to v4.0.0 -------------------- -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - :: - -3. Extract the recently created back-up file. - - :: - -4. Replace your current metadata with the metadata you stored in the back-up file. - - :: - -5. Navigate to the new SQream package bin folder. - - :: - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/4.0.0_index.rst b/releases/4.0.0_index.rst deleted file mode 100644 index 5f072fd35..000000000 --- a/releases/4.0.0_index.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _4.0.0_index: - -************************** -Release Notes 4.0.0 -************************** -The 4.0.0 Release Notes describe the following releases: - -.. contents:: - :local: - :depth: 1 - -.. toctree:: - :maxdepth: 1 - :glob: - - 4.0.0 diff --git a/releases/4.1.rst b/releases/4.1.rst index 6c502e377..e050f762b 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -6,7 +6,7 @@ Release Notes 4.1 SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. -The 4.1 release notes were released on xx/xx/20xx and describe the following: +The 4.1 release notes were released on 03/01/2023 and describe the following: .. contents:: :local: @@ -72,7 +72,7 @@ Deprecated Features The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. -* Support in ``[]`` for delimiting database object identifiers ends at xx/xx/20xx. +* Support in ``[]`` for delimiting database object identifiers ends at 06/01/2023. * To delimit database object identifiers, you will be able to use double quotes ``""``. diff --git a/releases/index.rst b/releases/index.rst index 196502b60..5563bbb7f 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,6 +12,8 @@ Release Notes * - Version - Release Date + * - :ref:`4.1` + - March 01, 2023 * - :ref:`4.0` - January 25, 2023 * - :ref:`2022.1` From 6994cba336ffc8f8460047bb592b8f692609b1f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Mar 2023 09:30:03 +0200 Subject: [PATCH 0451/1892] Update alter_default_permissions.rst --- .../access_control_commands/alter_default_permissions.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 4234267e2..95c5acfd0 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -65,10 +65,10 @@ The following table describes the supported permissions: - Object - Description * - ``SUPERUSER`` - - Cluster, Database, Schema + - Schema - The most privileged role, with full control over a cluster, database, or schema * - ``CREATE`` - - Database, Schema + - Schema - For a role to create and manage objects, it needs the ``CREATE`` and ``USAGE`` permissions at the respective level * - ``USAGE`` - Schema @@ -86,11 +86,12 @@ The following table describes the supported permissions: - Table - Allows a user to run :ref:`delete`, :ref:`truncate` statements to delete data from a table * - ``DDL`` - - Database, Schema, Table, Function + - Schema, Table - Allows a user to :ref:`alter tables<alter_table>`, rename columns and tables, etc. + Examples ============ From c804159f43d85a18f8c0c918e0ca1bf2e737a2eb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Mar 2023 10:08:00 +0200 Subject: [PATCH 0452/1892] Update 4.1.rst --- releases/4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index e050f762b..6954063c4 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -35,7 +35,7 @@ No Studio updates Known Issues ------------ -No known issues +:ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 4.1 resolved Issues From 8ff91182b207054517f98109749b0af744e917d4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Mar 2023 11:05:37 +0200 Subject: [PATCH 0453/1892] SQream support link --- connecting_to_sqream/client_drivers/index.rst | 2 +- connecting_to_sqream/client_drivers/odbc/index.rst | 6 +++--- connecting_to_sqream/client_platforms/index.rst | 2 +- connecting_to_sqream/client_platforms/sas_viya.rst | 2 +- connecting_to_sqream/client_platforms/tableau.rst | 2 +- connecting_to_sqream/index.rst | 2 +- .../installing_sqream_with_kubernetes.rst | 4 ++-- .../installing_studio_on_stand_alone_server.rst | 2 +- .../running_sqream_in_a_docker_container.rst | 6 +++--- troubleshooting/information_for_support.rst | 12 ++++-------- troubleshooting/remedying_slow_queries.rst | 4 ++-- 11 files changed, 20 insertions(+), 24 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 6f8f5909a..08ff79a4f 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -116,7 +116,7 @@ The following are applicable to Linux: .. rubric:: Need help? -If you couldn't find what you're looking for, we're always happy to help. Visit :ref:`information_for_support` for additional support. +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ .. rubric:: Looking for older drivers? diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 4494ef4ec..195bc6897 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -39,10 +39,10 @@ SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to in Other distributions may also work, but are not officially supported by SQream. -Downloading the ODBC driver -================================== +Getting the ODBC driver +======================= -The SQream DB ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <http://support.sqream.com/>`_ or contact your SQream account manager to get the driver. +The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or contact your SQream account manager to get the driver. The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 5a13fb6f4..6cd49667e 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -14,7 +14,7 @@ SQream DB is designed to work with most common database tools and interfaces, al The tools listed have been tested and approved for use with SQream DB. Most 3\ :sup:`rd` party tools that work through JDBC, ODBC, and Python should work. -If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support <http://support.sqream.com/>`_ or contact your SQream account manager for more information. +If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or contact your SQream account manager for more information. .. toctree:: :maxdepth: 4 diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index ef4a338a4..d827fdc40 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -178,7 +178,7 @@ In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the fol 3. Restart SAS Viya. -For more troubleshooting assistance, see the `SQream Support Portal <https://sqream.atlassian.net/servicedesk/customer/portals>`_. +For more troubleshooting assistance, see the `SQream Support Portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Supporting TEXT ~~~~~~~~~~~~~~~~~~ diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 1d2ca17b6..279552c34 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -212,4 +212,4 @@ If Tableau cannot locate the SQream JDBC driver, do the following: .. image:: /_static/images/Third_Party_Connectors/tableau/envrionment_variable_for_classpath.png -If you experience issues after restarting Tableau, see the `SQream support portal <https://support.sqream.com>`_. \ No newline at end of file +If you experience issues after restarting Tableau, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index ecb9e4715..668af4d1e 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -15,4 +15,4 @@ This section provides information about the following third party tools: client_platforms/index client_drivers/index -If you need a tool that SQream does not support, contact SQream Support or your SQream account manager for more information. \ No newline at end of file +If you need a tool that SQream does not support, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or your SQream account manager for more information. \ No newline at end of file diff --git a/installation_guides/installing_sqream_with_kubernetes.rst b/installation_guides/installing_sqream_with_kubernetes.rst index fbf2566ed..0abde10d3 100644 --- a/installation_guides/installing_sqream_with_kubernetes.rst +++ b/installation_guides/installing_sqream_with_kubernetes.rst @@ -1769,7 +1769,7 @@ Before Upgrading Your System ---------------------------- Before upgrading your system you must do the following: -1. Contact SQream support for a new SQream package tarball file. +1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for a new SQream package tarball file. :: @@ -1813,4 +1813,4 @@ If you continue upgrading, all running SQream workers (master and editor) are st 4. When SQream has successfully upgraded, load the SQream console and restart your services. -For questions, contact SQream Support. +For questions, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index ecec67c7f..362828313 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -121,7 +121,7 @@ After installing the Dashboard Data Collector, you can install Studio. **To install Studio:** -1. Copy the SQream Studio package from SQream Artifactory into the target server. For access to the Sqream Studio package, contact SQream Support. +1. Copy the SQream Studio package from SQream Artifactory into the target server. For access to the Sqream Studio package, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. :: diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst index 2a2454164..97fc76476 100644 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ b/installation_guides/running_sqream_in_a_docker_container.rst @@ -807,7 +807,7 @@ After preparing your local environment you must deploy the SQream software. Depl **To deploy the SQream software:** -1. Contact the SQream Support team for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-<arch>.tar.gz** file. +1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-<arch>.tar.gz** file. The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-<arch>.tar.gz** file includes the following parameter values: @@ -1426,7 +1426,7 @@ This section describes how to upgrade your SQream system. **To upgrade your SQream system:** -1. Contact the SQream Support team for access to the new SQream package tarball file. +1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ team for access to the new SQream package tarball file. :: @@ -1466,4 +1466,4 @@ This section describes how to upgrade your SQream system. 7. When the upgrade is complete, load the SQream console and restart your services. - For assistance, contact SQream Support. + For assistance, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. diff --git a/troubleshooting/information_for_support.rst b/troubleshooting/information_for_support.rst index 16dcb4174..fd1cab1fa 100644 --- a/troubleshooting/information_for_support.rst +++ b/troubleshooting/information_for_support.rst @@ -4,18 +4,14 @@ Gathering Information for SQream Support ******************************************* -.. What do we want to look into a performance issue - -.. what about other kinds of issues - -.. what about bug reports - -`SQream Support <https://sqream.atlassian.net/servicedesk/>`_ is ready to answer any questions, and help solve any issues with SQream DB. +.. contents:: + :local: + :depth: 1 Getting Support and Reporting Bugs ======================================= -When contacting `SQream Support <https://sqream.atlassian.net/servicedesk/>`_, we recommend reporting the following information: +When contacting `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_, we recommend reporting the following information: * What is the problem encountered? * What was the expected outcome? diff --git a/troubleshooting/remedying_slow_queries.rst b/troubleshooting/remedying_slow_queries.rst index 9bd05b324..2c18f5278 100644 --- a/troubleshooting/remedying_slow_queries.rst +++ b/troubleshooting/remedying_slow_queries.rst @@ -58,7 +58,7 @@ The following table is a checklist you can use to identify the cause of your slo #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement(<statement id>)``). - If the statement does not stop correctly, contact SQream support. + If the statement does not stop correctly, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. If there are no long running statements or this does not help, continue to step 7. * - 7 @@ -76,4 +76,4 @@ The following table is a checklist you can use to identify the cause of your slo #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`spooling` guide. #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. - If performance does not improve, contact SQream support for more help. \ No newline at end of file + If performance does not improve, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. \ No newline at end of file From 6092e58a1f24547f0376ea8e7252365cb10c2c71 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Mar 2023 14:33:07 +0200 Subject: [PATCH 0454/1892] Update decode.rst --- .../scalar_functions/string/decode.rst | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst index 9530341b2..f2048e2b4 100644 --- a/reference/sql/sql_functions/scalar_functions/string/decode.rst +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -3,7 +3,7 @@ ******************** DECODE ******************** -The **DECODE** function is used to translate a code value into a corresponding value that is meaningful to humans. This function is typically used in situations where a code needs to be presented to a user in a more understandable format, such as when displaying data in a report or on a user interface. +The ``DECODE`` function takes an expression or column and compares it to a series of search values. It returns a result value that corresponds to the first matching search value, or the default value ``NULL`` if no matches are found. Syntax ========== @@ -11,7 +11,7 @@ The following shows the correct syntax for the DECODE function: .. code-block:: postgres - DECODE(string input_text, format type_text); + DECODE( <expr> , <search1> , <result1> [ , <search2> , <result2> ... ] [ , <default> ] ) Parameters ============ @@ -23,14 +23,40 @@ The following table shows the DECODE parameters: * - Parameter - Description - * - ``input_text`` - - Defines the input text string. - * - ``type_text`` - - Defines the format used for decoding the input text. + * - ``expr`` + - The expression to be evaluated. + * - ``search`` + - A value that ``expr`` is compared against. + * - ``result1`` + - A value that is returnd if ``expr`` matches ``search``. Return ====== Returns the same type as the argument supplied. +Example +======= + +.. code-block:: postgres + + CREATE TABLE test1 (european_size int not null); + INSERT INTO test1 values (8),(9),(10),(11); + + SELECT european_size,DECODE(european_size,8,40,9,41,10,42,99) from test1; + + Output: + +---------------+---------+ + |european_size |decode | + +-------------------------+ + |8 |40 | + +---------------+---------+ + |9 |41 | + +-------------------------+ + |10 |42 | + +-------------------------+ + |11 |99 | + +-------------------------+ + + From efb4f64912c45cb916d26ab0356b7d2a91d4bd0d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 5 Mar 2023 09:15:42 +0200 Subject: [PATCH 0455/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 438df0ad7..1929da509 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -1,7 +1,7 @@ .. _java_jdbc: ************************* -Connecting to SQream Using JDBC +JDBC ************************* The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. @@ -35,15 +35,8 @@ The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using O Getting the JAR file --------------------- -SQream provides the JDBC driver as a zipped JAR file, available for download from the :ref:`client drivers download page<client_drivers>`. This JAR file can be integrated into your Java-based applications or projects. +The SQream JDBC driver is available for download from the :ref:`client drivers download page<client_drivers>`. This JAR file can be integrated into your Java-based applications or projects. -Extracting the ZIP Archive -------------------------- -Run the following command to extract the JAR file from the ZIP archive: - -.. code-block:: console - - $ unzip sqream-jdbc-4.3.0.zip Setting Up the Class Path ---------------------------- @@ -82,7 +75,7 @@ The following is the syntax for SQream: .. code-block:: text - jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>;[<optional parameters>; ...] + jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>sqream;[<optional parameters>; ...] Connection Parameters ^^^^^^^^^^^^^^^^^^^^^^^^ From 9bf3a714f923140b65294ac3a30794d01aa90ae3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 5 Mar 2023 15:03:26 +0200 Subject: [PATCH 0456/1892] Update 4.1.rst --- releases/4.1.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 6954063c4..f26308ac2 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -52,7 +52,8 @@ Version 4.1 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | SQ-12510 | Encryption memory issues | +------------------------+------------------------------------------------------------------------------------------+ - +| SQ-13219 | JDBC ``supportsSchemasInDataManipulation()`` method issue | ++------------------------+------------------------------------------------------------------------------------------+ Configuration Changes --------------------- From 68c7881b1ccdfb47fa5e12a011a03604837f1f09 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:29:00 +0200 Subject: [PATCH 0457/1892] Update 4.1.rst --- releases/4.1.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index f26308ac2..9f83d7901 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -25,6 +25,11 @@ New Features * A new brute-force attack protection mechanism locks out user accounts for 15 minutes following 5 consecutive failed login attempts +Storage Version +--------------- + +The storage version presently in effect is version 45. + SQream Studio Updates and Improvements -------------------------------------- @@ -111,7 +116,7 @@ Upgrading to v4.1 :: -3. Extract the recently created back-up file. +3. Copy the recently created back-up file. :: From 051724daa6dce09a1ca8887e4b0147add4c7ab75 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:51:48 +0200 Subject: [PATCH 0458/1892] Storage --- releases/2022.1.1.rst | 42 ++++++++++++++++++++++----------------- releases/2022.1.2.rst | 15 +++++++++++--- releases/2022.1.3.rst | 12 +++++++++++ releases/2022.1.4.rst | 5 +++++ releases/2022.1.5.rst | 5 ++++- releases/2022.1.6.rst | 46 ++++++++++++++++++++++++++----------------- releases/2022.1.7.rst | 4 ++++ releases/2022.1.rst | 11 +++++++++++ releases/4.0.rst | 6 ++++++ 9 files changed, 106 insertions(+), 40 deletions(-) diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 436287c6c..3ba0cb8b6 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -13,7 +13,13 @@ Version Content ---------- The 2022.1.1 Release Notes describes the following: -* Enhanced security features. +* Enhanced security features +* For more information, see `SQream Acceleration Studio 5.4.7 <https://docs.sqream.com/en/v2022.1.1/sqream_studio_5.4.7/index.html>`_. + +Storage Version +--------------- + +The storage version presently in effect is version 40. New Features ---------- @@ -27,29 +33,25 @@ Password Security Compliance ************ In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. -For more information, see :ref:`access_control_password_policy`. +For more information, see `Password Policy <https://docs.sqream.com/en/v2022.1.1/operational_guides/access_control_password_policy.html>`_. Known Issues --------- -The following table lists the known issues for Version 2022.1.1: +There were no known issues in Version 2022.1.1. + +Resolved Issues +--------- +The following table lists the issues that were resolved in Version 2022.1.1: +-------------+------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +=============+================================================================================================+ | SQ-6419 | An internal compiler error occurred when casting Numeric literals in an aggregation function. | +-------------+------------------------------------------------------------------------------------------------+ - -Resolved Issues ---------- -The following table lists the issues that were resolved in Version 2022.1.1: - -+-------------+----------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+========================================================================================+ -| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | -+-------------+----------------------------------------------------------------------------------------+ -| SQ-10892 | An unclear message was displayed when users ran ``UPDATE`` on foreign tables. | -+-------------+----------------------------------------------------------------------------------------+ +| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | ++-------------+------------------------------------------------------------------------------------------------+ +| SQ-10955 | Unneeded reads were occurring when filtering by date. | ++-------------+------------------------------------------------------------------------------------------------+ Operations and Configuration Changes -------- @@ -63,9 +65,7 @@ No relevant naming changes were made. Deprecated Features ------- -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQream, see the `Using Legacy String Literals <https://docs.sqream.com/en/v2022.1/configuration_guides/use_legacy_string_literals.html>`_ configuration flag. +In `SQream Acceleration Studio 5.4.7 <https://docs.sqream.com/en/v2022.1.1/sqream_studio_5.4.7/index.html>`_, the **Configuration** section has been temporarily disabled and will be enabled at a later date. In addition, the **Log Lines** tab in the **Log** section has been removed. End of Support ------- @@ -107,3 +107,9 @@ Upgrading to v2022.1.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 5c007f0ec..cbefa3f00 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -19,6 +19,11 @@ The 2022.1.2 Release Notes describes the following: * Optimized queries on external Parquet tables. +Storage Version +--------------- + +The storage version presently in effect is version 41. + New Features ---------- The 2022.1.2 Release Notes include the following new features: @@ -53,9 +58,7 @@ No relevant naming changes were made. Deprecated Features ------- -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQream, see the `Using Legacy String Literals <https://docs.sqream.com/en/v2022.1/configuration_guides/use_legacy_string_literals.html>`_ configuration flag. +No features were deprecated for Version 2022.1.2. End of Support ------- @@ -97,3 +100,9 @@ Upgrading to v2022.1.2 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1.2/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.2 \ No newline at end of file diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index b88eb78d9..e31c6728f 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -27,6 +27,12 @@ The 2022.1.3 Release Notes describes the following: * Support sub-queries in the UPDATE condition. +Storage Version +--------------- + +The storage version presently in effect is version 42. + + Known Issues --------- The following table lists the issues that are known limitations in Version 2022.1.3: @@ -120,3 +126,9 @@ Upgrading to v2022.1.3 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1.3 \ No newline at end of file diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 338fdf164..30a81b231 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -18,6 +18,11 @@ The 2022.1.4 Release Notes describes the following: :: +Storage Version +--------------- + +The storage version presently in effect is version 42. + Known Issues --------- No relevant Known Issues. diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index d63bf3b7a..2c3149039 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -23,7 +23,10 @@ The 2022.1.5 Release Notes include the following new features: * release_defunct_locks utility function enhancement to receive new optional input parameter to specify timeout - for more details see `Lock Related Issues <../troubleshooting/lock_related_issues.html>`_. - +Storage Version +--------------- + +The storage version presently in effect is version 42. Known Issues diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 67eb46222..efd0a4ab2 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -3,7 +3,7 @@ ************************** Release Notes 2022.1.6 ************************** -The 2022.1.6 release notes were released on 11/29/2022 and describe the following: +The 2022.1.6 release notes were released on 12/11/2022 and describe the following: .. contents:: :local: @@ -16,6 +16,11 @@ New Features :: +Storage Version +--------------- + +The storage version presently in effect is version 42. + Known Issues --------- :ref:`Percentile<percentile_disc>` is not supported for Window functions. @@ -23,26 +28,31 @@ Known Issues Version 2022.1.6 resolved Issues --------- -+--------------------------------+--------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+================================+============================================================================================+ -| SQ-10160 | Spotfire casting issues when reading SQream data | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-12117 | Running TCPH-21 results in out of memory | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | -+--------------------------------+--------------------------------------------------------------------------------------------+ -| SQ-12204 | Possible issue when trying to INSERT Unicode data using .Net client | -+--------------------------------+--------------------------------------------------------------------------------------------+ ++--------------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++================================+==========================================================================================+ +| SQ-10160 | Spotfire casting issues when reading SQream data | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-11975 | Internal runtime error | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-12117 | Running TCPH-21 results in out of memory | ++--------------------------------+------------------------------------------------------------------------------------------+ +| SQ-12204 | Possible issue when trying to INSERT Unicode data using .Net client | ++--------------------------------+------------------------------------------------------------------------------------------+ + + + Configuration Changes -------- No configuration changes were made. diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index b3fda33ff..c5f738eba 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -20,6 +20,10 @@ New Features :: +Storage Version +--------------- + +The storage version presently in effect is version 43. Known Issues --------- diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 6614d6458..be50ab11b 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -17,6 +17,11 @@ The 2022.1 Release Notes describes the following: * New data manipulation command. * Additional data ingestion format. +Storage Version +--------------- + +The storage version presently in effect is version 40. + New Features ---------- The 2022.1 Release Notes include the following new features: @@ -129,3 +134,9 @@ Upgrading to v2022.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 diff --git a/releases/4.0.rst b/releases/4.0.rst index 65e8c25f5..ed6dc628c 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -25,6 +25,12 @@ New Features * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities +Storage Version +--------------- + +The storage version presently in effect is version 45. + + SQream Studio Updates and Improvements -------------------------------------- From acf624d4be38ce087837730971c723a424193334 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:53:39 +0200 Subject: [PATCH 0459/1892] Update 4.1.rst --- releases/4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 9f83d7901..10b249f40 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -33,7 +33,7 @@ The storage version presently in effect is version 45. SQream Studio Updates and Improvements -------------------------------------- -No Studio updates +SQream Studio v5.5.4 has been released. :: From 96bcb30bec812a93bca7faf3c4e98d2d6fa549a7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Mar 2023 16:19:48 +0200 Subject: [PATCH 0460/1892] REAL to DOUBLE --- reference/sql/sql_functions/index.rst | 6 ++---- .../scalar_functions/numeric/atan.rst | 2 +- .../scalar_functions/numeric/atn2.rst | 2 +- .../scalar_functions/numeric/ceiling.rst | 2 +- .../scalar_functions/numeric/cos.rst | 4 ++-- .../scalar_functions/numeric/degrees.rst | 2 +- .../scalar_functions/numeric/exp.rst | 4 ++-- .../scalar_functions/numeric/floor.rst | 2 ++ .../scalar_functions/numeric/log.rst | 2 +- .../scalar_functions/numeric/log10.rst | 2 +- .../scalar_functions/numeric/radians.rst | 2 +- .../scalar_functions/numeric/round.rst | 21 +++++++------------ .../scalar_functions/numeric/square.rst | 2 +- .../scalar_functions/numeric/tan.rst | 2 +- .../scalar_functions/numeric/trunc.rst | 2 ++ 15 files changed, 27 insertions(+), 30 deletions(-) diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index b06a754f7..add12c95d 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -174,8 +174,6 @@ The following table shows the **arithmetic operator** functions: - Calculates the cosine of an argument * - :ref:`cot` - Calculates the cotangent of an argument - * - :ref:`crc64` - - Calculates a CRC-64 hash of an argument * - :ref:`degrees` - Converts a value from radian values to degrees * - :ref:`exp` @@ -206,8 +204,6 @@ The following table shows the **arithmetic operator** functions: - Calculates the tangent of an argument * - :ref:`trunc` - Rounds a number to its integer representation towards 0 - * - :ref:`sign` - - Returns an integer value of -1, 0, or 1, depending on the sign of the input expression. Strings ^^^^^^^^^^^ @@ -225,6 +221,8 @@ The following table shows the **string** functions: - Calculates the position where a string starts inside another string * - :ref:`concat` - Concatenates two strings + * - :ref:`crc64` + - Calculates a CRC-64 hash of an argument * - :ref:`decode` - Decodes or extracts binary data from a textual input string * - :ref:`isprefixof` diff --git a/reference/sql/sql_functions/scalar_functions/numeric/atan.rst b/reference/sql/sql_functions/scalar_functions/numeric/atan.rst index d730e8dfc..6a500383a 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/atan.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/atan.rst @@ -29,7 +29,7 @@ Arguments Returns ============ -Always returns a floating point result of the inverse tangent, in radians. +When using the ``ATAN`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/atn2.rst b/reference/sql/sql_functions/scalar_functions/numeric/atn2.rst index f727a9abe..e7a356338 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/atn2.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/atn2.rst @@ -35,7 +35,7 @@ Arguments Returns ============ -Always returns a floating point result of the inverse tangent, in radians. +When using the ``ATN2`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index 314c33c02..9d91611a6 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -``CEILING`` and ``CEIL`` always return a ``double`` floating point number. +When using the ``CEILING`` and ``CEIL`` floating point number scalar functions, ``real`` arguments are automatically cast to ``double`` precision. Notes diff --git a/reference/sql/sql_functions/scalar_functions/numeric/cos.rst b/reference/sql/sql_functions/scalar_functions/numeric/cos.rst index 5861b7bc8..dbd322488 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/cos.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/cos.rst @@ -4,7 +4,7 @@ COS ************************** -Returns the cosine value of a numeric expression +Returns the cosine value of a numeric expression. Syntax ========== @@ -29,7 +29,7 @@ Arguments Returns ============ -Always returns a floating point result of the cosine. +When using the ``COS`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/degrees.rst b/reference/sql/sql_functions/scalar_functions/numeric/degrees.rst index d1d806792..7ef7b3c2c 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/degrees.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/degrees.rst @@ -30,7 +30,7 @@ Arguments Returns ============ -Always returns a floating point result of the value in degrees. +When using the ``DEGREES`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/exp.rst b/reference/sql/sql_functions/scalar_functions/numeric/exp.rst index 16116614e..abebebbe0 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/exp.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/exp.rst @@ -4,7 +4,7 @@ EXP ************************** -Returns the natural exponent value of a numeric expression (*e*\ :sup:`x`) +Returns the natural exponent value of a numeric expression (*e*\ :sup:`x`). See also :ref:`log`. @@ -30,7 +30,7 @@ Arguments Returns ============ -Always returns a floating point result. +When using the ``EXP`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/floor.rst b/reference/sql/sql_functions/scalar_functions/numeric/floor.rst index 56dcac0a2..e528dcc5d 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/floor.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/floor.rst @@ -32,6 +32,8 @@ Returns Returns the same type as the argument supplied. +When using the ``FLOOR`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. + Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/log.rst b/reference/sql/sql_functions/scalar_functions/numeric/log.rst index 3a1b9156d..4baa0f7a7 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/log.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/log.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -Always returns a floating point result. +When using the ``LOG`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/log10.rst b/reference/sql/sql_functions/scalar_functions/numeric/log10.rst index 99b8311e3..844373aca 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/log10.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/log10.rst @@ -30,7 +30,7 @@ Arguments Returns ============ -Always returns a floating point result. +When using the ``LOG10`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/radians.rst b/reference/sql/sql_functions/scalar_functions/numeric/radians.rst index 4d6859de8..e79b6b20b 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/radians.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/radians.rst @@ -30,7 +30,7 @@ Arguments Returns ============ -Always returns a floating point result of the value in radians. +When using the ``RADIANS`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index 420bd3c0f..462ec606f 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -13,10 +13,8 @@ Syntax .. code-block:: postgres - ROUND( numeric ) -> numeric - ROUND( numeric [, int ] ) -> numeric - ROUND( double ) -> double - + ROUND( expr [, scale ] ) + Arguments ============ @@ -26,23 +24,20 @@ Arguments * - Parameter - Description - * - ``numeric`` - - Stores numeric values such as integers, decimal numbers, and currency values - * - ``int`` - - Stores integer values + * - ``expr`` + - Numeric expression to round + * - ``scale`` + - Number of digits after the decimal point to round to. Defaults to 0 if not specified. Returns ============ -The ``ROUND()`` function returns a ``numeric`` value when used with numeric input types, such as ``integer`` or ``decimal``. When the input is ``double``, the return type is also ``double``. - - -.. note:: ``integer`` data types are automatically cast to ``numeric`` data types. +When using the ``ROUND`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= -If the input value is NULL, the result is NULL. +* If the input value is NULL, the result is NULL. Examples =========== diff --git a/reference/sql/sql_functions/scalar_functions/numeric/square.rst b/reference/sql/sql_functions/scalar_functions/numeric/square.rst index edf7b11ab..d8b7cd585 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/square.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/square.rst @@ -30,7 +30,7 @@ Arguments Returns ============ -Always returns a floating point result +When using the ``SQUARE`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/tan.rst b/reference/sql/sql_functions/scalar_functions/numeric/tan.rst index 7a6915d3b..88e332d5a 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/tan.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/tan.rst @@ -29,7 +29,7 @@ Arguments Returns ============ -Always returns a floating point result of the tangent. +When using the ``TAN`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. Notes ======= diff --git a/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst b/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst index 322b1274b..643bfd6d9 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst @@ -34,6 +34,8 @@ Returns Returns the same type as the argument supplied. +When using the ``TRUNC`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. + Notes ======= From b5c2af503c414f3c53b44821725abdb4aa813202 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 9 Mar 2023 08:48:15 +0200 Subject: [PATCH 0461/1892] Update sql_feature_support.rst --- reference/sql_feature_support.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index d940215b0..0997b72bb 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -182,7 +182,7 @@ Statements - Yes - :ref:`truncate` * - UPDATE - - No + - Yes - * - VALUES - Yes From dd9fc1dbb6b87936bb38b3c58d74d60f7850016a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 09:00:42 +0200 Subject: [PATCH 0462/1892] Update 4.1.rst --- releases/4.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.1.rst b/releases/4.1.rst index 10b249f40..0dcfccef7 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -78,7 +78,7 @@ Deprecated Features The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. -* Support in ``[]`` for delimiting database object identifiers ends at 06/01/2023. +* Support in ``[]`` for delimiting database object identifiers ends on June 1st, 2023. * To delimit database object identifiers, you will be able to use double quotes ``""``. From a1ddeb8ac39096a4bd02f1282c73813e46b70ed8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:16:46 +0200 Subject: [PATCH 0463/1892] RN --- conf.py | 2 +- releases/4.0_index.rst | 3 +- releases/4.2.rst | 140 +++++++++++++++++++++++++++++++++++++++++ releases/index.rst | 15 +---- 4 files changed, 146 insertions(+), 14 deletions(-) create mode 100644 releases/4.2.rst diff --git a/conf.py b/conf.py index 2fee1f392..bee87ebd0 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '4.1' +release = '4.2' diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 680957f22..d61a919f3 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -14,4 +14,5 @@ The 4.0 Release Notes describe the following releases: :glob: 4.0 - 4.1 \ No newline at end of file + 4.1 + 4.2 \ No newline at end of file diff --git a/releases/4.2.rst b/releases/4.2.rst new file mode 100644 index 000000000..b5684eb20 --- /dev/null +++ b/releases/4.2.rst @@ -0,0 +1,140 @@ +.. _4.2: + +************************** +Release Notes 4.2 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.2 release notes were released on xx/xx/2023 and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + +:ref:`Apache Spark<spark>` may now be used for large-scale data processing. + + :: + +:ref:`Physical deletion<delete_guide>` performance enhancement by supporting file systems with parallelism capabilities + + +Connectors +---------- + +Pysqream - Supports Python 9 + +ODBC + +JDBC + +Storage Version +--------------- + +The storage version presently in effect is version xx. + +SQream Studio Updates and Improvements +-------------------------------------- + +SQream Studio v5.5.4 has been released. + + :: + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for Window functions. + + +Version 4.2 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-12598 | External table ``SELECT`` statement issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13055 | Pysqream ``NULL`` value issue | ++------------------------+------------------------------------------------------------------------------------------+ + + +Configuration Changes +--------------------- + +No configuration changes + + +Naming Changes +-------------- +No naming changes + + +Deprecated Features +------------------- + +► Square Brackets ``[]`` + +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. + +* Support in ``[]`` for delimiting database object identifiers ends on June 1st, 2023. + +* To delimit database object identifiers, you will be able to use double quotes ``""``. + + +► ``VARCHAR`` + +The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. + +* Support in the ``VARCHAR`` data type ends at September 30th, 2023. + +* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. + +* The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. + + + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to v4.2 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Copy the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/index.rst b/releases/index.rst index 5563bbb7f..c12430d8a 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,22 +12,13 @@ Release Notes * - Version - Release Date + * - :ref:`4.2` + - March xx, 2023 * - :ref:`4.1` - March 01, 2023 * - :ref:`4.0` - January 25, 2023 - * - :ref:`2022.1` - - July 19, 2022 - * - :ref:`2021.2` - - September 13, 2021 - * - :ref:`2021.1` - - June 13, 2021 - * - :ref:`2020.3` - - October 8, 2020 - * - :ref:`2020.2` - - July 22, 2020 - * - :ref:`2020.1` - - January 15, 2020 + From ade1238fcf179f1e8b7e91d194217b9332b044da Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:27:17 +0200 Subject: [PATCH 0464/1892] Update 4.2.rst --- releases/4.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index b5684eb20..1330a1c81 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -35,7 +35,7 @@ JDBC Storage Version --------------- -The storage version presently in effect is version xx. +The storage version presently in effect is version 46. SQream Studio Updates and Improvements -------------------------------------- From a3bbea5dbcee2951d73ae45338b093435d1c7f94 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 11:44:14 +0200 Subject: [PATCH 0465/1892] Spark --- .../Spark}/spark.rst | 0 connecting_to_sqream/client_drivers/index.rst | 11 +++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) rename connecting_to_sqream/{client_platforms => client_drivers/Spark}/spark.rst (100%) diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_drivers/Spark/spark.rst similarity index 100% rename from connecting_to_sqream/client_platforms/spark.rst rename to connecting_to_sqream/client_drivers/Spark/spark.rst diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 08ff79a4f..0847fbd3b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -31,8 +31,13 @@ The following are applicable to all operating systems: * **Trino**: - * `Trino connector <>`_ + * `Trino Connector <>`_ * :ref:`trino` + +* **Spark**: + + * `Spark Connector <>`_ + * :ref:`spark` .. _python: @@ -41,7 +46,6 @@ The following are applicable to all operating systems: * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.1.3>`_ - pysqream v3.1.3 (.tar.gz) * :ref:`pysqream` - .. _nodejs: * **Node.JS** - Recommended installation via ``npm``: @@ -49,7 +53,6 @@ The following are applicable to all operating systems: * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) * :ref:`nodejs` - .. _tableau_connector: * **Tableau**: @@ -62,7 +65,7 @@ The following are applicable to all operating systems: * **Power BI**: - * `Power BI PowerQuery connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) + * `Power BI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) * :ref:`power_bi` From cba00956bf9f176e790641a3931d65d6e0da3770 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:44:02 +0200 Subject: [PATCH 0466/1892] Spark --- connecting_to_sqream/client_drivers/index.rst | 1 + .../client_platforms/spark.rst | 282 ++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/spark.rst diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 0847fbd3b..7b321d77b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,6 +34,7 @@ The following are applicable to all operating systems: * `Trino Connector <>`_ * :ref:`trino` + * **Spark**: * `Spark Connector <>`_ diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst new file mode 100644 index 000000000..39225a2b4 --- /dev/null +++ b/connecting_to_sqream/client_platforms/spark.rst @@ -0,0 +1,282 @@ +.. _spark: + +************************* +Using Spark With SQream +************************* + + +Spark may be used for large-scale data processing. + + +.. contents:: + :local: + :depth: 1 + +Installation and Configuration +------------------------------ + + +Before You Begin +~~~~~~~~~~~~~~~~ + +To use Spark with SQream, it is essential that you have the following installed: + +* JDBC version 4.5.6 or later +* SQream version 2022.1.8 or later +* Spark version 3.3.1 or later +* Spark Connector 1.0.0 + + +JDBC +~~~~ + +If JDBC is not yet configured, follow the :ref:`JDBC Client Drivers page<java_jdbc>` for guidance in registring and configuring. + + +Connecting Spark to SQream +~~~~~~~~~~~~~~~~~~~ + +The Spark Connector enables inserting Spark DataFrames into SQream tables and exporting tables or queries as Spark DataFrames for compatibility with Spark. DataFrames are data structures within the Spark framework designed for transferring data between disparate data sources. + +1. In the Spark Shell, run: + +.. code-block:: postgres + + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} + + +Example: + +.. code-block:: postgres + + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar + + +Connector Configuration +~~~~~~~~~~~~~~~~~~~~~~~ + +The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. + +SQream supports the following Spark connection properties: + +.. list-table:: + :widths: 1 4 20 + :header-rows: 1 + + + * - Item + - Default + - Description + * - ``url`` + - + - The JDBC URL to connect to the database. + * - ``dbtable`` + - + - The name of the table or view to be queried or written to in a relational database when using the JDBC data source. + * - ``query`` + - + - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. + * - ``driver`` + - + - The fully qualified class name of the JDBC driver to use when connecting to a relational database. + * - ``numPartitions`` + - + - The number of partitions to use when reading data from a data source. + * - ``queryTimeout`` + - 0 + - The maximum time in seconds for a JDBC query to execute before timing out. + * - ``fetchsize`` + - 1 + - The number of rows to fetch in a single JDBC fetch operation. + * - ``batchsize`` + - 1000000 + - The number of rows to write in a single JDBC batch operation when writing to a database. + * - ``sessionInitStatement`` + - + - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. + * - ``truncate`` + - ``false`` + - A boolean value indicating whether to truncate an existing table before writing data to it. + * - ``cascadeTruncate`` + - The default cascading truncate behavior of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect. + - A boolean value indicating whether to recursively truncate child tables when truncating a table. + * - ``createTableOptions`` + - + - Additional options to include when creating a new table in a relational database. + * - ``createTableColumnTypes`` + - + - A map of column names to column data types to use when creating a new table in a relational database. + * - ``customSchema`` + - + - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. + * - ``pushDownPredicate`` + - ``true`` + - A boolean value indicating whether to push down filters to the data source. + * - ``pushDownAggregate`` + - ``false`` + - A boolean value indicating whether to push down aggregations to the data source. + * - ``pushDownLimit`` + - ``false`` + - A boolean value indicating whether to push down limits to the data source. + * - ``c`` + - ``false`` + - A shorthand for specifying connection properties in the JDBC data source. + * - ``connectionProvider`` + - + - A fully qualified class name of a custom connection provider to use when connecting to a data source. + + +Transferring Data From SQream to Spark +------------------------------------- + +#. From the ``SqlContext`` object, use the ``read()`` method to construct a ``DataFrameReader``. + +#. Use the ``format()`` method to specify ``SQREAM_SOURCE_NAME``. + +#. Use either the ``option()`` or ``options()` method to specify the connector options. + +#. Specify one of the following options for reading tables: + + * ``dbtable``: equivalent to the ``SELECT * FROM <table_name>`` command. + + * ``query``: equivalent to the ``SELECT`` statement. + +Examples +~~~~~~~~ + +Reading an entire table: + +.. code-block:: postgres + + val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .load() + +Reading query results: + +.. code-block:: postgres + + val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("query", "<EXECUTED_QUERY> <table_name>") .load() + + +Transferring data From Spark to SQream +-------------------------------------- + +#. Use the ``write()`` method of the ``DataFrame`` to construct a ``DataFrameWriter``. + +#. Specify ``SQREAM_SOURCE_NAME`` using the ``format()`` method. + +#. Use either the ``option()`` or the ``options()` method to specify the connector options. + +#. To specify the table to which data is written, use the ``dbtable`` option. + +#. To specify the content saving mode, use the ``mode()`` method. + +Example +~~~~~~~~ +Read an entire table: + +.. code-block:: postgres + + df.write .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .mode(SaveMode.Overwrite) .save() + + +Supported Data Types and Mapping +-------------------------------- + +SQream data types mapped to Spark + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SQream + - Spark + * - ``BIGINT`` + - ``LONGINT`` + * - ``BOOL`` + - ``BooleanType`` + * - ``DATE`` + - ``DateType`` + * - ``DOUBLE`` + - ``DoubleType`` + * - ``REAL`` + - ``FloateType`` + * - ``DECIMAL`` + - ``DeciamlType`` + * - ``INT`` + - ``Integer`` + * - ``SMALLINT`` + - ``ShortType`` + * - ``TINYINT`` + - ``ShortType`` + * - ``DATETIME`` + - ``TimestampType`` + +Spark data types mapped to SQream + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Spark + - SQream + * - ``BooleanType`` + - ``BOOL`` + * - ``ByteType`` + - ``SMALLINT`` + * - ``DateType`` + - ``DATE`` + * - ``DecimalType`` + - ``DECIMAL`` + * - ``DoubleType`` + - ``DOUBLE`` + * - ``FloatType`` + - ``REAL`` + * - ``IntegerType`` + - ``INT`` + * - ``LongType`` + - ``BIGINT`` + * - ``ShortType`` + - ``SMALLINT`` + * - ``StringType`` + - ``TEXT`` + * - ``TimestampType`` + - ``DATETIME`` + + +Example +------- + +JAVA + +.. code-block:: postgres + + import com.sqream.driver.SqreamSession; + import org.apache.spark.sql.Dataset; + import org.apache.spark.sql.Row; + + import java.util.HashMap; + + public class main { + public static void main(String[] args) { + HashMap<String, String> config = new HashMap<>(); + //spark configuration + //optional configuration here: https://spark.apache.org/docs/latest/configuration.html + config.put("spark.master", "local"); + SqreamSession sqreamSession = SqreamSession.getSession(config); + + //spark properties + //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html + HashMap<String, String> props = new HashMap<>(); + + props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); + props.put("dbtable", "test"); + + /*Read from sqream table*/ + Dataset<Row> dataFrame = sqreamSession.read(props); + + /*Added to sqream table*/ + sqreamSession.write(dataFrame, props); + + } + } + From d0063e4638fd61368945764cdbb619d0b643d246 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 15:41:28 +0200 Subject: [PATCH 0467/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 1929da509..e50648dfa 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -133,6 +133,10 @@ The following table shows the connection string parameters: - Optional - ``true`` - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. + * - ``<idleconnectiontimeout>`` + - Optional + - 0 + - Sets the duration, in seconds, for which a database connection can remain idle before it is terminated. If the parameter is set to its default value, idle connections will not be terminated. The idle connection timer begins counting after the completion of a query execution. Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 631cc72ca851aba0c3342ffc1400b74e8a7ea3f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:06:47 +0200 Subject: [PATCH 0468/1892] Update 4.2.rst --- releases/4.2.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/releases/4.2.rst b/releases/4.2.rst index 1330a1c81..3af086c6c 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -76,6 +76,11 @@ No naming changes Deprecated Features ------------------- +► ``INT96`` + +Due to Parquet's lack of support for the "INT96" data type, SQream has decided to immediately deprecate this data type. + + ► Square Brackets ``[]`` The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. From 91e33c91e67de10648161c6642e501c5582079eb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 09:33:25 +0200 Subject: [PATCH 0469/1892] Update 4.2.rst --- releases/4.2.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 3af086c6c..d4768a0e2 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -23,14 +23,14 @@ New Features :ref:`Physical deletion<delete_guide>` performance enhancement by supporting file systems with parallelism capabilities -Connectors ----------- +Newly Released Connector Drivers +-------------------------------- -Pysqream - Supports Python 9 +Pysqream 3.2.4 - `.tar.gz file <https://github.com/SQream/pysqream/releases>`_ Supports Python 9(??) -ODBC +ODBC 4.4.4 :ref:`Getting the ODBC Driver<odbc>` -JDBC +JDBC 4.5.8 `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ Storage Version --------------- @@ -78,7 +78,7 @@ Deprecated Features ► ``INT96`` -Due to Parquet's lack of support for the "INT96" data type, SQream has decided to immediately deprecate this data type. +Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. ► Square Brackets ``[]`` From 137aec2c0385213c013360cb3d8d485f05ba5f5e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 13:49:39 +0200 Subject: [PATCH 0470/1892] Update 4.1.rst --- releases/4.1.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/releases/4.1.rst b/releases/4.1.rst index 0dcfccef7..a9203569b 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -25,6 +25,11 @@ New Features * A new brute-force attack protection mechanism locks out user accounts for 15 minutes following 5 consecutive failed login attempts +Newly Released Connector Drivers +-------------------------------- + +JDBC 4.5.7 `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.7.jar>`_ + Storage Version --------------- From 43a8043ad918f8f0518f2762506b1cf4b4a98c97 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:38:05 +0200 Subject: [PATCH 0471/1892] Update spark.rst --- .../client_drivers/Spark/spark.rst | 150 ++++++++---------- 1 file changed, 65 insertions(+), 85 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Spark/spark.rst b/connecting_to_sqream/client_drivers/Spark/spark.rst index f10191b70..45109eaa0 100644 --- a/connecting_to_sqream/client_drivers/Spark/spark.rst +++ b/connecting_to_sqream/client_drivers/Spark/spark.rst @@ -5,7 +5,7 @@ Using Spark With SQream ************************* -If you are using Spark for distributed processing and analysis and wish to use it with SQream, follow these instructions. +Spark may be used for large-scale data processing. .. contents:: @@ -15,44 +15,15 @@ If you are using Spark for distributed processing and analysis and wish to use i Installation and Configuration ------------------------------ -.. contents:: - :local: - :depth: 1 - Before You Begin ~~~~~~~~~~~~~~~~ -To use Spark with SQream, you must have the following installed: +To use Spark with SQream, it is essential that you have the following installed: * SQream version 2022.1.8 or later * Spark version 3.3.1 or later * SQream Spark Connector 1.0.0 -* JDBC version 4.5.6 or later - -JDBC -~~~~ - -If JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for guidance in registring and configuring. - - -Connecting Spark to SQream -~~~~~~~~~~~~~~~~~~~ - -The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. - -1. In the Spark Shell, run: - -.. code-block:: postgres - - ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - - -Example: - -.. code-block:: postgres - - ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar - +* :ref:`JDBC<jdbc>` version 4.5.6 or later Connector Configuration ~~~~~~~~~~~~~~~~~~~~~~~ @@ -71,119 +42,125 @@ The following Spark connection properties are supported by SQream: - Description * - ``url`` - - - The JDBC URL ``jdbc:subprotocol:subname`` establishes the connection between SQream and Spark. Source-specific connection properties may be specified in the URL, such as ``user`` and ``password``, e.g. ``jdbc:Sqream://localhost/test?user=fred&password=secret``. + - The JDBC URL to connect to the database. * - ``dbtable`` - - - A JDBC table to read from or write to. When reading from a ``dbtable``, anything that is valid in an SQL ``FROM`` clause may be used. For example, you may use a subquery in parentheses instead of querying a full table. It is not allowed to specify ``dbtable`` and ``query`` options at the same time. + - The JDBC URL to connect to the database. * - ``query`` - - - The ``query`` property in Spark is used to read data into the program by specifying a query. This query is used as a subquery in the ``FROM`` clause and Spark will assign an alias to the subquery. For example, when using a JDBC Source, Spark will issue a query in the format of ``SELECT <columns> FROM (<user_specified_query>) spark_gen_alias``. It's important to note that it is not allowed to use both the ``dbtable`` and ``query`` options at the same time, and the ``query`` option cannot be used with the ``partitionColumn`` option. If the ``partitionColumn`` option is needed, it must be specified using the ``dbtable`` option and qualified using the subquery alias provided in ``dbtable``. An example of how to use this option would be: spark.read.format("jdbc").option("url", jdbcUrl).option("query", "select c1, c2 from t1").load() + - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. * - ``driver`` - - - The class name of the JDBC driver to use to connect to this URL. + - The fully qualified class name of the JDBC driver to use when connecting to a relational database. * - ``numPartitions`` - - - The maximum number of partitions that can be used for parallelism in table reading and writing. This also determines the maximum number of concurrent JDBC connections. If the number of partitions to write exceeds this limit, we decrease it to this limit by calling ``coalesce(numPartitions)`` before writing. + - The number of partitions to use when reading data from a data source. * - ``queryTimeout`` - 0 - - The number of seconds the driver will wait for a Statement object to execute to the given number of seconds. Zero means there is no limit. In the write path, this option depends on how JDBC drivers implement the API ``setQueryTimeout``, e.g., the h2 JDBC driver checks the timeout of each query instead of an entire JDBC batch. + - The maximum time in seconds for a JDBC query to execute before timing out. * - ``fetchsize`` - 1 - - The JDBC fetch size, which determines how many rows to fetch per round trip. This can help performance on JDBC drivers which default to low fetch size (e.g. Oracle with 10 rows). + - The number of rows to fetch in a single JDBC fetch operation. * - ``batchsize`` - 1000000 - - The JDBC batch size, which determines how many rows to insert per round trip. This can help performance on JDBC drivers. This option applies only to writing. + - The number of rows to write in a single JDBC batch operation when writing to a database. * - ``sessionInitStatement`` - - - After each database session is opened to the remote DB and before starting to read data, this option executes a custom SQL statement (or a PL/SQL block). Use this to implement session initialization code. Example: ``option("sessionInitStatement", """BEGIN execute immediate 'alter session set "_serial_direct_read"=true'; END;""")`` + - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. * - ``truncate`` - ``false`` - - This is a JDBC writer related option. When ``SaveMode.Overwrite`` is enabled, this option causes Spark to truncate an existing table instead of dropping and recreating it. This can be more efficient, and prevents the table metadata (e.g., indices) from being removed. However, it will not work in some cases, such as when the new data has a different schema. In case of failures, users should turn off ``truncate`` option to use ``DROP TABLE`` again. Also, due to the different behavior of ``TRUNCATE TABLE`` among DBMS, it's not always safe to use this. MySQLDialect, DB2Dialect, MsSqlServerDialect, DerbyDialect, and OracleDialect supports this while PostgresDialect and default JDBCDirect doesn't. For unknown and unsupported JDBCDirect, the user option ``truncate`` is ignored. + - A boolean value indicating whether to truncate an existing table before writing data to it. * - ``cascadeTruncate`` - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect - - This is a JDBC writer related option. If enabled and supported by the JDBC database (PostgreSQL and Oracle at the moment), this options allows execution of a ``TRUNCATE TABLE t CASCADE`` (in the case of PostgreSQL a TRUNCATE TABLE ONLY t CASCADE is executed to prevent inadvertently truncating descendant tables). This will affect other tables, and thus should be used with care. + - A boolean value indicating whether to recursively truncate child tables when truncating a table. * - ``createTableOptions`` - - - This is a JDBC writer related option. If specified, this option allows setting of database-specific table and partition options when creating a table (e.g., ``CREATE TABLE t (name string) ENGINE=InnoDB.``). + - Additional options to include when creating a new table in a relational database. * - ``createTableColumnTypes`` - - - The database column data types to use instead of the defaults, when creating the table. Data type information should be specified in the same format as CREATE TABLE columns syntax (e.g: ``"name CHAR(64), comments VARCHAR(1024)"``). The specified types should be valid spark sql data types. + - A map of column names to column data types to use when creating a new table in a relational database. * - ``customSchema`` - - - The custom schema to use for reading data from JDBC connectors. For example, ``"id DECIMAL(38, 0), name STRING"``. You can also specify partial fields, and the others use the default type mapping. For example, ``"id DECIMAL(38, 0)"``. The column names should be identical to the corresponding column names of JDBC table. Users can specify the corresponding data types of Spark SQL instead of using the defaults. + - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. * - ``pushDownPredicate`` - ``true`` - - The option to enable or disable predicate push-down into the JDBC data source. The default value is true, in which case Spark will push down filters to the JDBC data source as much as possible. Otherwise, if set to false, no filter will be pushed down to the JDBC data source and thus all filters will be handled by Spark. Predicate push-down is usually turned off when the predicate filtering is performed faster by Spark than by the JDBC data source. + - A boolean value indicating whether to push down filters to the data source. * - ``pushDownAggregate`` - ``false`` - - The option to enable or disable aggregate push-down in V2 JDBC data source. The default value is false, in which case Spark will not push down aggregates to the JDBC data source. Otherwise, if sets to true, aggregates will be pushed down to the JDBC data source. Aggregate push-down is usually turned off when the aggregate is performed faster by Spark than by the JDBC data source. Please note that aggregates can be pushed down if and only if all the aggregate functions and the related filters can be pushed down. If ``numPartitions`` equals to 1 or the group by key is the same as ``partitionColumn``, Spark will push down aggregate to data source completely and not apply a final aggregate over the data source output. Otherwise, Spark will apply a final aggregate over the data source output. + - A boolean value indicating whether to push down aggregations to the data source. * - ``pushDownLimit`` - ``false`` - - The option to enable or disable LIMIT push-down into V2 JDBC data source. The LIMIT push-down also includes LIMIT + SORT , a.k.a. the Top N operator. The default value is false, in which case Spark does not push down LIMIT or LIMIT with SORT to the JDBC data source. Otherwise, if sets to true, LIMIT or LIMIT with SORT is pushed down to the JDBC data source. If ``numPartitions`` is greater than 1, SPARK still applies LIMIT or LIMIT with SORT on the result from data source even if LIMIT or LIMIT with SORT is pushed down. Otherwise, if LIMIT or LIMIT with SORT is pushed down and ``numPartitions`` equals to 1, SPARK will not apply LIMIT or LIMIT with SORT on the result from data source. + - A boolean value indicating whether to push down limits to the data source. * - ``pushDownTableSample`` - ``false`` - - The option to enable or disable TABLESAMPLE push-down into V2 JDBC data source. The default value is false, in which case Spark does not push down TABLESAMPLE to the JDBC data source. Otherwise, if value sets to true, TABLESAMPLE is pushed down to the JDBC data source. + - Used to optimize the performance of SQL queries on large tables by pushing down the sampling operation closer to the data source, reducing the amount of data that needs to be processed. * - ``connectionProvider`` - - - The name of the JDBC connection provider to use to connect to this URL, e.g. ``db2``, ``mssql``. Must be one of the providers loaded with the JDBC data source. Used to disambiguate when more than one provider can handle the specified driver and options. The selected provider must not be disabled by ``spark.sql.sources.disabledJdbcConnProviderList``. - - -Transferring Data From SQream to Spark -------------------------------------- + - A fully qualified class name of a custom connection provider to use when connecting to a data source. + * - ``c`` + - ``false`` + - A shorthand for specifying connection properties in the JDBC data source. + -In the Spark UI, configure Spark to write to the SQream database. -1. From the SqlContext object, use the read() method to construct a DataFrameReader. +Connecting Spark to SQream +-------------------------- -2. Use the format() method to specify SQREAM_SOURCE_NAME. +The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. -3. Use either the option() or options() method to specify the connector options. +1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: -4. Specify one of the following options for reading tables: +.. code-block:: postgres - * dbtable: The name of the table to be read. All columns and records are retrieved (i.e. it is equivalent to ``SELECT * FROM db_table``). + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - * query: The exact query (SELECT statement) to run. - -Examples ---------------- -To read an entire table: +Example: .. code-block:: postgres - val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .load() - -To read query results: - -.. code-block:: postgres + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar - val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("query", "<EXECUTED_QUERY> <table_name>") .load() +2. To create a SQream session, run the following commands in the Spark Shell: +.. code-block:: postgres + + import scala.collection.JavaConverters.mapAsJavaMapConverter + val config = Map("spark.master"->"local").asJava + import com.sqream.driver.SqreamSession; + val sqreamSession=SqreamSession.getSession(config) -Transferring data From Spark to SQream + +Transferring Data From SQream to Spark -------------------------------------- -In the Spark UI, configure Spark to read from the SQream database. +1. Create a mapping of Spark options: + +.. code-block:: postgres -1. Use the write() method of the DataFrame to construct a DataFrameWriter. + val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava -2. Specify SQREAM_SOURCE_NAME using the format() method. +2. Create a Spark DataFrame: -3. Specify the connector options using either the option() or options() method. +.. code-block:: postgres -4. Use the dbtable option to specify the table to which data is written. + val df=sqreamSession.read(options) -5. Use the mode() method to specify the save mode for the content. +Transferring Data From Spark to SQream +-------------------------------------- -Examples ---------------- -To read an entire table: +1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): .. code-block:: postgres - df.write .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .mode(SaveMode.Overwrite) .save() + val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava + +2. Create a Spark DataFrame: + +.. code-block:: postgres + import org.apache.spark.sql.SaveMode + val df=sqreamSession.write((df, options, SaveMode.Overwrite)) Supported Data Types and Mapping -------------------------------- @@ -249,8 +226,8 @@ Spark data types mapped to SQream - ``DATETIME`` -Examples ---------- +Example +------- JAVA @@ -259,6 +236,7 @@ JAVA import com.sqream.driver.SqreamSession; import org.apache.spark.sql.Dataset; import org.apache.spark.sql.Row; + import org.apache.spark.sql.SaveMode; import java.util.HashMap; @@ -282,6 +260,8 @@ JAVA /*Added to sqream table*/ sqreamSession.write(dataFrame, props); + sqreamSession.write(dataFrame, props, SaveMode.Overwrite); + } } From 7128d2925a16381b7cbec9f405fdc438e1412741 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 15:49:13 +0200 Subject: [PATCH 0472/1892] Delete spark.rst --- .../client_drivers/Spark/spark.rst | 268 ------------------ 1 file changed, 268 deletions(-) delete mode 100644 connecting_to_sqream/client_drivers/Spark/spark.rst diff --git a/connecting_to_sqream/client_drivers/Spark/spark.rst b/connecting_to_sqream/client_drivers/Spark/spark.rst deleted file mode 100644 index 45109eaa0..000000000 --- a/connecting_to_sqream/client_drivers/Spark/spark.rst +++ /dev/null @@ -1,268 +0,0 @@ -.. _spark: - -************************* -Using Spark With SQream -************************* - - -Spark may be used for large-scale data processing. - - -.. contents:: - :local: - :depth: 1 - -Installation and Configuration ------------------------------- - -Before You Begin -~~~~~~~~~~~~~~~~ - -To use Spark with SQream, it is essential that you have the following installed: - -* SQream version 2022.1.8 or later -* Spark version 3.3.1 or later -* SQream Spark Connector 1.0.0 -* :ref:`JDBC<jdbc>` version 4.5.6 or later - -Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~ - -The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. - -The following Spark connection properties are supported by SQream: - -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Item - - Default - - Description - * - ``url`` - - - - The JDBC URL to connect to the database. - * - ``dbtable`` - - - - The JDBC URL to connect to the database. - * - ``query`` - - - - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. - * - ``driver`` - - - - The fully qualified class name of the JDBC driver to use when connecting to a relational database. - * - ``numPartitions`` - - - - The number of partitions to use when reading data from a data source. - * - ``queryTimeout`` - - 0 - - The maximum time in seconds for a JDBC query to execute before timing out. - * - ``fetchsize`` - - 1 - - The number of rows to fetch in a single JDBC fetch operation. - * - ``batchsize`` - - 1000000 - - The number of rows to write in a single JDBC batch operation when writing to a database. - * - ``sessionInitStatement`` - - - - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. - * - ``truncate`` - - ``false`` - - A boolean value indicating whether to truncate an existing table before writing data to it. - * - ``cascadeTruncate`` - - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect - - A boolean value indicating whether to recursively truncate child tables when truncating a table. - * - ``createTableOptions`` - - - - Additional options to include when creating a new table in a relational database. - * - ``createTableColumnTypes`` - - - - A map of column names to column data types to use when creating a new table in a relational database. - * - ``customSchema`` - - - - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. - * - ``pushDownPredicate`` - - ``true`` - - A boolean value indicating whether to push down filters to the data source. - * - ``pushDownAggregate`` - - ``false`` - - A boolean value indicating whether to push down aggregations to the data source. - * - ``pushDownLimit`` - - ``false`` - - A boolean value indicating whether to push down limits to the data source. - * - ``pushDownTableSample`` - - ``false`` - - Used to optimize the performance of SQL queries on large tables by pushing down the sampling operation closer to the data source, reducing the amount of data that needs to be processed. - * - ``connectionProvider`` - - - - A fully qualified class name of a custom connection provider to use when connecting to a data source. - * - ``c`` - - ``false`` - - A shorthand for specifying connection properties in the JDBC data source. - - - -Connecting Spark to SQream --------------------------- - -The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. - -1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: - -.. code-block:: postgres - - ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - - -Example: - -.. code-block:: postgres - - ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar - -2. To create a SQream session, run the following commands in the Spark Shell: - -.. code-block:: postgres - - import scala.collection.JavaConverters.mapAsJavaMapConverter - val config = Map("spark.master"->"local").asJava - import com.sqream.driver.SqreamSession; - val sqreamSession=SqreamSession.getSession(config) - - -Transferring Data From SQream to Spark --------------------------------------- - -1. Create a mapping of Spark options: - -.. code-block:: postgres - - val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava - -2. Create a Spark DataFrame: - -.. code-block:: postgres - - val df=sqreamSession.read(options) - -Transferring Data From Spark to SQream --------------------------------------- - -1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): - -.. code-block:: postgres - - val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava - -2. Create a Spark DataFrame: - -.. code-block:: postgres - - import org.apache.spark.sql.SaveMode - val df=sqreamSession.write((df, options, SaveMode.Overwrite)) - -Supported Data Types and Mapping --------------------------------- - -SQream data types mapped to Spark - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - SQream - - Spark - * - ``BIGINT`` - - ``LONGINT`` - * - ``BOOL`` - - ``BooleanType`` - * - ``DATE`` - - ``DateType`` - * - ``DOUBLE`` - - ``DoubleType`` - * - ``REAL`` - - ``FloateType`` - * - ``DECIMAL`` - - ``DeciamlType`` - * - ``INT`` - - ``Integer`` - * - ``SMALLINT`` - - ``ShortType`` - * - ``TINYINT`` - - ``ShortType`` - * - ``DATETIME`` - - ``TimestampType`` - -Spark data types mapped to SQream - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Spark - - SQream - * - ``BooleanType`` - - ``BOOL`` - * - ``ByteType`` - - ``SMALLINT`` - * - ``DateType`` - - ``DATE`` - * - ``DecimalType`` - - ``DECIMAL`` - * - ``DoubleType`` - - ``DOUBLE`` - * - ``FloatType`` - - ``REAL`` - * - ``IntegerType`` - - ``INT`` - * - ``LongType`` - - ``BIGINT`` - * - ``ShortType`` - - ``SMALLINT`` - * - ``StringType`` - - ``TEXT`` - * - ``TimestampType`` - - ``DATETIME`` - - -Example -------- - -JAVA - -.. code-block:: postgres - - import com.sqream.driver.SqreamSession; - import org.apache.spark.sql.Dataset; - import org.apache.spark.sql.Row; - import org.apache.spark.sql.SaveMode; - - import java.util.HashMap; - - public class main { - public static void main(String[] args) { - HashMap<String, String> config = new HashMap<>(); - //spark configuration - //optional configuration here: https://spark.apache.org/docs/latest/configuration.html - config.put("spark.master", "local"); - SqreamSession sqreamSession = SqreamSession.getSession(config); - - //spark properties - //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html - HashMap<String, String> props = new HashMap<>(); - - props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); - props.put("dbtable", "test"); - - /*Read from sqream table*/ - Dataset<Row> dataFrame = sqreamSession.read(props); - - /*Added to sqream table*/ - sqreamSession.write(dataFrame, props); - sqreamSession.write(dataFrame, props, SaveMode.Overwrite); - - - } - } - From d82734b65c51dc3e715e701dd6c91d456c149576 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:05:11 +0200 Subject: [PATCH 0473/1892] Create spark.rst --- .../client_drivers/Spark/spark.rst | 268 ++++++++++++++++++ 1 file changed, 268 insertions(+) create mode 100644 connecting_to_sqream/client_drivers/Spark/spark.rst diff --git a/connecting_to_sqream/client_drivers/Spark/spark.rst b/connecting_to_sqream/client_drivers/Spark/spark.rst new file mode 100644 index 000000000..45109eaa0 --- /dev/null +++ b/connecting_to_sqream/client_drivers/Spark/spark.rst @@ -0,0 +1,268 @@ +.. _spark: + +************************* +Using Spark With SQream +************************* + + +Spark may be used for large-scale data processing. + + +.. contents:: + :local: + :depth: 1 + +Installation and Configuration +------------------------------ + +Before You Begin +~~~~~~~~~~~~~~~~ + +To use Spark with SQream, it is essential that you have the following installed: + +* SQream version 2022.1.8 or later +* Spark version 3.3.1 or later +* SQream Spark Connector 1.0.0 +* :ref:`JDBC<jdbc>` version 4.5.6 or later + +Connector Configuration +~~~~~~~~~~~~~~~~~~~~~~~ + +The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. + +The following Spark connection properties are supported by SQream: + +.. list-table:: + :widths: auto + :header-rows: 1 + + + * - Item + - Default + - Description + * - ``url`` + - + - The JDBC URL to connect to the database. + * - ``dbtable`` + - + - The JDBC URL to connect to the database. + * - ``query`` + - + - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. + * - ``driver`` + - + - The fully qualified class name of the JDBC driver to use when connecting to a relational database. + * - ``numPartitions`` + - + - The number of partitions to use when reading data from a data source. + * - ``queryTimeout`` + - 0 + - The maximum time in seconds for a JDBC query to execute before timing out. + * - ``fetchsize`` + - 1 + - The number of rows to fetch in a single JDBC fetch operation. + * - ``batchsize`` + - 1000000 + - The number of rows to write in a single JDBC batch operation when writing to a database. + * - ``sessionInitStatement`` + - + - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. + * - ``truncate`` + - ``false`` + - A boolean value indicating whether to truncate an existing table before writing data to it. + * - ``cascadeTruncate`` + - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect + - A boolean value indicating whether to recursively truncate child tables when truncating a table. + * - ``createTableOptions`` + - + - Additional options to include when creating a new table in a relational database. + * - ``createTableColumnTypes`` + - + - A map of column names to column data types to use when creating a new table in a relational database. + * - ``customSchema`` + - + - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. + * - ``pushDownPredicate`` + - ``true`` + - A boolean value indicating whether to push down filters to the data source. + * - ``pushDownAggregate`` + - ``false`` + - A boolean value indicating whether to push down aggregations to the data source. + * - ``pushDownLimit`` + - ``false`` + - A boolean value indicating whether to push down limits to the data source. + * - ``pushDownTableSample`` + - ``false`` + - Used to optimize the performance of SQL queries on large tables by pushing down the sampling operation closer to the data source, reducing the amount of data that needs to be processed. + * - ``connectionProvider`` + - + - A fully qualified class name of a custom connection provider to use when connecting to a data source. + * - ``c`` + - ``false`` + - A shorthand for specifying connection properties in the JDBC data source. + + + +Connecting Spark to SQream +-------------------------- + +The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. + +1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: + +.. code-block:: postgres + + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} + + +Example: + +.. code-block:: postgres + + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar + +2. To create a SQream session, run the following commands in the Spark Shell: + +.. code-block:: postgres + + import scala.collection.JavaConverters.mapAsJavaMapConverter + val config = Map("spark.master"->"local").asJava + import com.sqream.driver.SqreamSession; + val sqreamSession=SqreamSession.getSession(config) + + +Transferring Data From SQream to Spark +-------------------------------------- + +1. Create a mapping of Spark options: + +.. code-block:: postgres + + val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava + +2. Create a Spark DataFrame: + +.. code-block:: postgres + + val df=sqreamSession.read(options) + +Transferring Data From Spark to SQream +-------------------------------------- + +1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): + +.. code-block:: postgres + + val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava + +2. Create a Spark DataFrame: + +.. code-block:: postgres + + import org.apache.spark.sql.SaveMode + val df=sqreamSession.write((df, options, SaveMode.Overwrite)) + +Supported Data Types and Mapping +-------------------------------- + +SQream data types mapped to Spark + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SQream + - Spark + * - ``BIGINT`` + - ``LONGINT`` + * - ``BOOL`` + - ``BooleanType`` + * - ``DATE`` + - ``DateType`` + * - ``DOUBLE`` + - ``DoubleType`` + * - ``REAL`` + - ``FloateType`` + * - ``DECIMAL`` + - ``DeciamlType`` + * - ``INT`` + - ``Integer`` + * - ``SMALLINT`` + - ``ShortType`` + * - ``TINYINT`` + - ``ShortType`` + * - ``DATETIME`` + - ``TimestampType`` + +Spark data types mapped to SQream + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Spark + - SQream + * - ``BooleanType`` + - ``BOOL`` + * - ``ByteType`` + - ``SMALLINT`` + * - ``DateType`` + - ``DATE`` + * - ``DecimalType`` + - ``DECIMAL`` + * - ``DoubleType`` + - ``DOUBLE`` + * - ``FloatType`` + - ``REAL`` + * - ``IntegerType`` + - ``INT`` + * - ``LongType`` + - ``BIGINT`` + * - ``ShortType`` + - ``SMALLINT`` + * - ``StringType`` + - ``TEXT`` + * - ``TimestampType`` + - ``DATETIME`` + + +Example +------- + +JAVA + +.. code-block:: postgres + + import com.sqream.driver.SqreamSession; + import org.apache.spark.sql.Dataset; + import org.apache.spark.sql.Row; + import org.apache.spark.sql.SaveMode; + + import java.util.HashMap; + + public class main { + public static void main(String[] args) { + HashMap<String, String> config = new HashMap<>(); + //spark configuration + //optional configuration here: https://spark.apache.org/docs/latest/configuration.html + config.put("spark.master", "local"); + SqreamSession sqreamSession = SqreamSession.getSession(config); + + //spark properties + //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html + HashMap<String, String> props = new HashMap<>(); + + props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); + props.put("dbtable", "test"); + + /*Read from sqream table*/ + Dataset<Row> dataFrame = sqreamSession.read(props); + + /*Added to sqream table*/ + sqreamSession.write(dataFrame, props); + sqreamSession.write(dataFrame, props, SaveMode.Overwrite); + + + } + } + From ee9efc65c4d10c40607979a46adb97624850f067 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:12:45 +0200 Subject: [PATCH 0474/1892] Delete spark.rst --- .../client_platforms/spark.rst | 282 ------------------ 1 file changed, 282 deletions(-) delete mode 100644 connecting_to_sqream/client_platforms/spark.rst diff --git a/connecting_to_sqream/client_platforms/spark.rst b/connecting_to_sqream/client_platforms/spark.rst deleted file mode 100644 index 39225a2b4..000000000 --- a/connecting_to_sqream/client_platforms/spark.rst +++ /dev/null @@ -1,282 +0,0 @@ -.. _spark: - -************************* -Using Spark With SQream -************************* - - -Spark may be used for large-scale data processing. - - -.. contents:: - :local: - :depth: 1 - -Installation and Configuration ------------------------------- - - -Before You Begin -~~~~~~~~~~~~~~~~ - -To use Spark with SQream, it is essential that you have the following installed: - -* JDBC version 4.5.6 or later -* SQream version 2022.1.8 or later -* Spark version 3.3.1 or later -* Spark Connector 1.0.0 - - -JDBC -~~~~ - -If JDBC is not yet configured, follow the :ref:`JDBC Client Drivers page<java_jdbc>` for guidance in registring and configuring. - - -Connecting Spark to SQream -~~~~~~~~~~~~~~~~~~~ - -The Spark Connector enables inserting Spark DataFrames into SQream tables and exporting tables or queries as Spark DataFrames for compatibility with Spark. DataFrames are data structures within the Spark framework designed for transferring data between disparate data sources. - -1. In the Spark Shell, run: - -.. code-block:: postgres - - ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - - -Example: - -.. code-block:: postgres - - ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar - - -Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~ - -The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. - -SQream supports the following Spark connection properties: - -.. list-table:: - :widths: 1 4 20 - :header-rows: 1 - - - * - Item - - Default - - Description - * - ``url`` - - - - The JDBC URL to connect to the database. - * - ``dbtable`` - - - - The name of the table or view to be queried or written to in a relational database when using the JDBC data source. - * - ``query`` - - - - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. - * - ``driver`` - - - - The fully qualified class name of the JDBC driver to use when connecting to a relational database. - * - ``numPartitions`` - - - - The number of partitions to use when reading data from a data source. - * - ``queryTimeout`` - - 0 - - The maximum time in seconds for a JDBC query to execute before timing out. - * - ``fetchsize`` - - 1 - - The number of rows to fetch in a single JDBC fetch operation. - * - ``batchsize`` - - 1000000 - - The number of rows to write in a single JDBC batch operation when writing to a database. - * - ``sessionInitStatement`` - - - - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. - * - ``truncate`` - - ``false`` - - A boolean value indicating whether to truncate an existing table before writing data to it. - * - ``cascadeTruncate`` - - The default cascading truncate behavior of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect. - - A boolean value indicating whether to recursively truncate child tables when truncating a table. - * - ``createTableOptions`` - - - - Additional options to include when creating a new table in a relational database. - * - ``createTableColumnTypes`` - - - - A map of column names to column data types to use when creating a new table in a relational database. - * - ``customSchema`` - - - - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. - * - ``pushDownPredicate`` - - ``true`` - - A boolean value indicating whether to push down filters to the data source. - * - ``pushDownAggregate`` - - ``false`` - - A boolean value indicating whether to push down aggregations to the data source. - * - ``pushDownLimit`` - - ``false`` - - A boolean value indicating whether to push down limits to the data source. - * - ``c`` - - ``false`` - - A shorthand for specifying connection properties in the JDBC data source. - * - ``connectionProvider`` - - - - A fully qualified class name of a custom connection provider to use when connecting to a data source. - - -Transferring Data From SQream to Spark -------------------------------------- - -#. From the ``SqlContext`` object, use the ``read()`` method to construct a ``DataFrameReader``. - -#. Use the ``format()`` method to specify ``SQREAM_SOURCE_NAME``. - -#. Use either the ``option()`` or ``options()` method to specify the connector options. - -#. Specify one of the following options for reading tables: - - * ``dbtable``: equivalent to the ``SELECT * FROM <table_name>`` command. - - * ``query``: equivalent to the ``SELECT`` statement. - -Examples -~~~~~~~~ - -Reading an entire table: - -.. code-block:: postgres - - val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .load() - -Reading query results: - -.. code-block:: postgres - - val df: DataFrame = sqlContext.read .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("query", "<EXECUTED_QUERY> <table_name>") .load() - - -Transferring data From Spark to SQream --------------------------------------- - -#. Use the ``write()`` method of the ``DataFrame`` to construct a ``DataFrameWriter``. - -#. Specify ``SQREAM_SOURCE_NAME`` using the ``format()`` method. - -#. Use either the ``option()`` or the ``options()` method to specify the connector options. - -#. To specify the table to which data is written, use the ``dbtable`` option. - -#. To specify the content saving mode, use the ``mode()`` method. - -Example -~~~~~~~~ -Read an entire table: - -.. code-block:: postgres - - df.write .format(SQREAM_SOURCE_NAME) .options(sfOptions) .option("<sqream_table_name>", "<table_name>") .mode(SaveMode.Overwrite) .save() - - -Supported Data Types and Mapping --------------------------------- - -SQream data types mapped to Spark - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - SQream - - Spark - * - ``BIGINT`` - - ``LONGINT`` - * - ``BOOL`` - - ``BooleanType`` - * - ``DATE`` - - ``DateType`` - * - ``DOUBLE`` - - ``DoubleType`` - * - ``REAL`` - - ``FloateType`` - * - ``DECIMAL`` - - ``DeciamlType`` - * - ``INT`` - - ``Integer`` - * - ``SMALLINT`` - - ``ShortType`` - * - ``TINYINT`` - - ``ShortType`` - * - ``DATETIME`` - - ``TimestampType`` - -Spark data types mapped to SQream - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Spark - - SQream - * - ``BooleanType`` - - ``BOOL`` - * - ``ByteType`` - - ``SMALLINT`` - * - ``DateType`` - - ``DATE`` - * - ``DecimalType`` - - ``DECIMAL`` - * - ``DoubleType`` - - ``DOUBLE`` - * - ``FloatType`` - - ``REAL`` - * - ``IntegerType`` - - ``INT`` - * - ``LongType`` - - ``BIGINT`` - * - ``ShortType`` - - ``SMALLINT`` - * - ``StringType`` - - ``TEXT`` - * - ``TimestampType`` - - ``DATETIME`` - - -Example -------- - -JAVA - -.. code-block:: postgres - - import com.sqream.driver.SqreamSession; - import org.apache.spark.sql.Dataset; - import org.apache.spark.sql.Row; - - import java.util.HashMap; - - public class main { - public static void main(String[] args) { - HashMap<String, String> config = new HashMap<>(); - //spark configuration - //optional configuration here: https://spark.apache.org/docs/latest/configuration.html - config.put("spark.master", "local"); - SqreamSession sqreamSession = SqreamSession.getSession(config); - - //spark properties - //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html - HashMap<String, String> props = new HashMap<>(); - - props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); - props.put("dbtable", "test"); - - /*Read from sqream table*/ - Dataset<Row> dataFrame = sqreamSession.read(props); - - /*Added to sqream table*/ - sqreamSession.write(dataFrame, props); - - } - } - From 782fc155394914e5384c5141c8534bee62a16c13 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:45:59 +0200 Subject: [PATCH 0475/1892] Update spark.rst --- connecting_to_sqream/client_drivers/Spark/spark.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/Spark/spark.rst b/connecting_to_sqream/client_drivers/Spark/spark.rst index 45109eaa0..812cebd75 100644 --- a/connecting_to_sqream/client_drivers/Spark/spark.rst +++ b/connecting_to_sqream/client_drivers/Spark/spark.rst @@ -160,7 +160,7 @@ Transferring Data From Spark to SQream .. code-block:: postgres import org.apache.spark.sql.SaveMode - val df=sqreamSession.write((df, options, SaveMode.Overwrite)) + val df=sqreamSession.write(df, options, SaveMode.Overwrite) Supported Data Types and Mapping -------------------------------- From bf58f7ccea34325c8774ae9643d4f4f6b188c73b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 14 Mar 2023 16:49:25 +0200 Subject: [PATCH 0476/1892] Update index.rst --- connecting_to_sqream/index.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index 668af4d1e..10533b0ac 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -3,9 +3,7 @@ ************************* Connecting to SQream ************************* -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. - -This section provides information about the following third party tools: +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. .. toctree:: :maxdepth: 2 From a32026f367f7cc805112cbab4b69caa015042481 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Mar 2023 09:16:40 +0200 Subject: [PATCH 0477/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 20 +------------------ 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 7b321d77b..c02c37be7 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -44,7 +44,7 @@ The following are applicable to all operating systems: * **Python** - Recommended installation via ``pip``: - * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.1.3>`_ - pysqream v3.1.3 (.tar.gz) + * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.4>`_ - pysqream v3.2.4 (.tar.gz) * :ref:`pysqream` .. _nodejs: @@ -82,24 +82,6 @@ The following are applicable to Windows: * **Net driver** - `SQream .Net driver v3.0.2 <https://sq-ftp-public.s3.amazonaws.com/SqreamNet_net48_3.0.2.zip>`_ - - - -Linux --------------- -The following are applicable to Linux: - -* `SQream SQL (x86_64) <https://sq-ftp-public.s3.amazonaws.com/sqream-sql-v2020.1.1_stable.x86_64.tar.gz>`_ - sqream-sql-v2020.1.1_stable.x86_64.tar.gz -* :ref:`sqream_sql_cli_reference` - Interactive command-line SQL client for Intel-based machines - - :: - -* `SQream SQL*(IBM POWER9) <https://sq-ftp-public.s3.amazonaws.com/sqream-sql-v2020.1.1_stable.ppc64le.tar.gz>`_ - sqream-sql-v2020.1.1_stable.ppc64le.tar.gz -* :ref:`sqream_sql_cli_reference` - Interactive command-line SQL client for IBM POWER9-based machines - - :: - -* ODBC Installer - Please contact your SQream representative for this installer. From 6b172dfda7415286f183a227a0af20aad568eaf8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Mar 2023 14:55:42 +0200 Subject: [PATCH 0478/1892] Update index.rst --- .../client_drivers/python/index.rst | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index f29679bc0..37bcd59a6 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -3,28 +3,22 @@ ************************* Connecting to SQream Using Python (pysqream) ************************* -The **Python** connector page describes the following: + +The Pysqream connector is a set of packages that allows Python programs to connect to SQream DB. It includes ``pysqream`` and ``pysqream-sqlalchemy``. ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``. + +The connector supports Python version 3.9 and newer. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. .. contents:: :local: :depth: 1 -Overview -============= -The SQream Python connector is a set of packages that allows Python programs to connect to SQream DB. - -* ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. - -* ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream`` - -The connector supports Python 3.6.5 and newer. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. - Installing the Python Connector ================================== Prerequisites ---------------- -Installing the Python connector includes the following prerequisites: + +It is essential that you have the following installed: .. contents:: :local: @@ -33,17 +27,20 @@ Installing the Python connector includes the following prerequisites: Python ^^^^^^^^^^^^ -The connector requires Python 3.6.5 or newer. To verify your version of Python: +The connector requires Python 3.9 or newer. + +To see your current Python version, run the following command: .. code-block:: console $ python --version - Python 3.7.3 + + PIP ^^^^^^^^^^^^ -The Python connector is installed via ``pip``, the Python package manager and installer. +The Python connector is installed via ``pip``, the standard package manager for Python, which is used to install, upgrade and manage Python packages (libraries) and their dependencies. We recommend upgrading to the latest version of ``pip`` before installing. To verify that you are on the latest version, run the following command: From c72db066731f82ce83a7e66850c2d627fc847d49 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:04:19 +0200 Subject: [PATCH 0479/1892] Update index.rst --- .../client_drivers/python/index.rst | 88 +++++++++++-------- 1 file changed, 53 insertions(+), 35 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 37bcd59a6..dfd3507ee 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -4,9 +4,10 @@ Connecting to SQream Using Python (pysqream) ************************* -The Pysqream connector is a set of packages that allows Python programs to connect to SQream DB. It includes ``pysqream`` and ``pysqream-sqlalchemy``. ``pysqream`` is a pure Python connector. It can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``. +The Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQream DB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. + +``pysqream`` is a pure Python connector that can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``. -The connector supports Python version 3.9 and newer. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. .. contents:: :local: @@ -16,7 +17,7 @@ Installing the Python Connector ================================== Prerequisites ----------------- +------------- It is essential that you have the following installed: @@ -25,9 +26,9 @@ It is essential that you have the following installed: :depth: 1 Python -^^^^^^^^^^^^ +~~~~~~ -The connector requires Python 3.9 or newer. +The connector requires Python version 3.9 or newer. To see your current Python version, run the following command: @@ -36,89 +37,106 @@ To see your current Python version, run the following command: $ python --version - - PIP -^^^^^^^^^^^^ +~~~ The Python connector is installed via ``pip``, the standard package manager for Python, which is used to install, upgrade and manage Python packages (libraries) and their dependencies. -We recommend upgrading to the latest version of ``pip`` before installing. To verify that you are on the latest version, run the following command: +We recommend upgrading to the latest version of ``pip`` before installing. + +To verify that you have the latest version, run the following command: .. code-block:: console - $ python3 -m pip install --upgrade pip - Collecting pip - Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) - |████████████████████████████████| 1.4MB 1.6MB/s - Installing collected packages: pip - Found existing installation: pip 19.1.1 - Uninstalling pip-19.1.1: - Successfully uninstalled pip-19.1.1 - Successfully installed pip-19.3.1 + $ python3 -m pip install --upgrade pip + Collecting pip + Downloading https://files.pythonhosted.org/packages/00/b6/9cfa56b4081ad13874b0c6f96af8ce16cfbc1cb06bedf8e9164ce5551ec1/pip-19.3.1-py2.py3-none-any.whl (1.4MB) + |████████████████████████████████| 1.4MB 1.6MB/s + Installing collected packages: pip + Found existing installation: pip 19.1.1 + Uninstalling pip-19.1.1: + Successfully uninstalled pip-19.1.1 + Successfully installed pip-19.3.1 + .. note:: * On macOS, you may want to use virtualenv to install Python and the connector, to ensure compatibility with the built-in Python environment * If you encounter an error including ``SSLError`` or ``WARNING: pip is configured with locations that require TLS/SSL, however the ssl module in Python is not available.`` - please be sure to reinstall Python with SSL enabled, or use virtualenv or Anaconda. OpenSSL for Linux -^^^^^^^^^^^^^^^^^^^^^^^^^^ -Some distributions of Python do not include OpenSSL. The Python connector relies on OpenSSL for secure connections to SQream DB. +~~~~~~~~~~~~~~~~~ +The Python connector relies on OpenSSL for secure connections to SQream DB. Some distributions of Python do not include OpenSSL. -* To install OpenSSL on RHEL/CentOS +To install OpenSSL on RHEL/CentOS, run the following command: .. code-block:: console $ sudo yum install -y libffi-devel openssl-devel -* To install OpenSSL on Ubuntu +To install OpenSSL on Ubuntu, run the following command: .. code-block:: console $ sudo apt-get install libssl-dev libffi-dev -y -Installing via PIP ------------------ + +Installing via PIP with an internet connection +---------------------------------------------- The Python connector is available via `PyPi <https://pypi.org/project/pysqream/>`_. -Install the connector with ``pip``: +To install the connector using pip, it is advisable to use the ``-U`` or ``--user`` flags instead of sudo, as it ensures packages are installed per user. However, it is worth noting that the connector can only be accessed under the same user. + +To install ``pysqream`` and ``pysqream-sqlalchemy`` with the ``--user`` flag, run the following command: .. code-block:: console - $ pip3 install pysqream pysqream-sqlalchemy + $ pip3.9 install pysqream pysqream-sqlalchemy --user ``pip3`` will automatically install all necessary libraries and modules. +Installing via PIP without an internet connection +---------------------------------------------- + +#. To get the ``.whl`` package file, contact you SQream support representative. + +#. Run the following command: + +.. code-block:: console + + tar -xf pysqream_connector_3.2.5.tar.gz + cd pysqream_connector_3.2.5 + #Install all packages with --no-index --find-links . + python3 -m pip install *.whl -U --no-index --find-links . + python3.9 -m pip install pysqream-3.2.5.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-sqlalchemy-0.8.zip -U --no-index --find-links . + Upgrading an Existing Installation -------------------------------------- The Python drivers are updated periodically. To upgrade an existing pysqream installation, use pip's ``-U`` flag: .. code-block:: console - $ pip3 install pysqream pysqream-sqlalchemy -U + $ pip3.9 install pysqream pysqream-sqlalchemy -U Validating Your Installation ----------------------------- -This section describes how to validate your installation. - -**To validate your installation**: -1. Create a file called ``sample.py``, containing the following: +#. Create a file called ``sample.py``, containing the following: .. literalinclude:: sample.py :language: python :caption: pysqream Validation Script :linenos: -2. Verify that the parameters in the connection have been replaced with your respective SQream installation parameters. +#. Verify that the parameters in the connection have been replaced with your respective SQream installation parameters. :: -3. Run the sample file to verify that you can connect to SQream: +#. Run the sample file to verify that you can connect to SQream: .. code-block:: console - $ python sample.py - Version: v2020.1 + $ python3.9 sample.py + Version: v2020.1 If the validation was successful, you can build an application using the SQream Python connector. If you receive a connection error, verify the following: From 09c41b120c140acf53a8e55975c1a48a247ec6e6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Mar 2023 17:31:55 +0200 Subject: [PATCH 0480/1892] spark --- .../client_drivers/Spark/{spark.rst => index.rst} | 3 ++- connecting_to_sqream/client_drivers/index.rst | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) rename connecting_to_sqream/client_drivers/Spark/{spark.rst => index.rst} (98%) diff --git a/connecting_to_sqream/client_drivers/Spark/spark.rst b/connecting_to_sqream/client_drivers/Spark/index.rst similarity index 98% rename from connecting_to_sqream/client_drivers/Spark/spark.rst rename to connecting_to_sqream/client_drivers/Spark/index.rst index 812cebd75..d8f583c39 100644 --- a/connecting_to_sqream/client_drivers/Spark/spark.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -1,11 +1,12 @@ .. _spark: + ************************* Using Spark With SQream ************************* -Spark may be used for large-scale data processing. +The Spark connector enables reading and writing data to and from SQreamDB and may be used for large-scale data processing. .. contents:: diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index c02c37be7..87c356a36 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -4,6 +4,8 @@ Client Drivers ************** + + The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. Client Driver Downloads @@ -38,7 +40,7 @@ The following are applicable to all operating systems: * **Spark**: * `Spark Connector <>`_ - * :ref:`spark` + * :ref:`spark` .. _python: From 0d56aaf0cc2c7e91e3890d8c0c3df0d0e5488e30 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Mar 2023 18:17:25 +0200 Subject: [PATCH 0481/1892] Python --- .../client_drivers/Spark/index.rst | 1 - connecting_to_sqream/client_drivers/index.rst | 3 +- .../client_drivers/python/index.rst | 60 +++++-------------- 3 files changed, 16 insertions(+), 48 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index d8f583c39..5f3d6caac 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -1,6 +1,5 @@ .. _spark: - ************************* Using Spark With SQream ************************* diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 87c356a36..fb302e3f0 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -4,8 +4,6 @@ Client Drivers ************** - - The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. Client Driver Downloads @@ -36,6 +34,7 @@ The following are applicable to all operating systems: * `Trino Connector <>`_ * :ref:`trino` +.. _spark: * **Spark**: diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index dfd3507ee..6de634cd8 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -4,7 +4,7 @@ Connecting to SQream Using Python (pysqream) ************************* -The Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQream DB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. +The current Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQream DB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. ``pysqream`` is a pure Python connector that can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``. @@ -163,16 +163,9 @@ Standard Connection Example .. code-block:: python import sqlalchemy as sa - from sqlalchemy.engine.url import URL - - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) + engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" + engine = sa.create_engine(engine_url) res = engine.execute('create or replace table test (ints int, ints2 int)') @@ -189,17 +182,10 @@ The following example is for using a ServerPicker: .. code-block:: python import sqlalchemy as sa - from sqlalchemy.engine.url import URL - - - engine_url = URL('sqream' - , username='dor' - , password='DorBerg123$' - , host='localhost' - , port=3108 - , database='pushlive') - - engine = sa.create_engine(engine_url,connect_args={"clustered": True}) + + engine_url = "sqream://dor:DorBerg123$@localhost:3108/pushlive" + + engine = sa.create_engine(engine_url, connect_args={"clustered": True}) res = engine.execute("create or replace table test100 (dor int);") res = engine.execute('insert into test100 values (5), (6);') @@ -216,20 +202,12 @@ The following example shows how to pull a table in Pandas. This examples uses th import sqlalchemy as sa import pandas as pd - from sqlalchemy.engine.url import URL - - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) + engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" - engine = sa.create_engine(engine_url) - - table_df = pd.read_sql("select * from nba", con=engine) + engine = sa.create_engine(engine_url) + + table_df = pd.read_sql("select * from nba", con=engine) API Examples =============== @@ -421,20 +399,12 @@ This section shows how to use the ORM to create and populate tables from Python .. code-block:: python - import sqlalchemy as sa - import pandas as pd - from sqlalchemy.engine.url import URL - + import sqlalchemy as sa + import pandas as pd - engine_url = URL('sqream' - , username='rhendricks' - , password='secret_passwor" - , host='localhost' - , port=5000 - , database='raviga' - , query={'use_ssl': False}) + engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" - engine = sa.create_engine(engine_url) + engine = sa.create_engine(engine_url) 2. Build a metadata object and bind it: From 78bba0d65967a99c75c1968732cc2100e051d5c9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 19 Mar 2023 09:54:13 +0200 Subject: [PATCH 0482/1892] 4.2 RN --- releases/4.2.rst | 6 ++++-- releases/index.rst | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index d4768a0e2..94e524849 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -6,7 +6,7 @@ Release Notes 4.2 SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. -The 4.2 release notes were released on xx/xx/2023 and describe the following: +The 4.2 release notes were released on 03/19/2023 and describe the following: .. contents:: :local: @@ -47,7 +47,9 @@ SQream Studio v5.5.4 has been released. Known Issues ------------ -:ref:`Percentile<percentile_disc>` is not supported for Window functions. +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. + +Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression. Version 4.2 resolved Issues diff --git a/releases/index.rst b/releases/index.rst index c12430d8a..63eca8c7f 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -13,7 +13,7 @@ Release Notes * - Version - Release Date * - :ref:`4.2` - - March xx, 2023 + - March 19, 2023 * - :ref:`4.1` - March 01, 2023 * - :ref:`4.0` From cc044d2172adf17343467a02a750f7fe875d83fe Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 19 Mar 2023 11:15:16 +0200 Subject: [PATCH 0483/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index fb302e3f0..d9ed6d160 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -97,6 +97,7 @@ The following are applicable to Windows: nodejs/index odbc/index dotnet/index + Spark/index From 3cd9619b5b157f0bbae0f0ebf20f50e340493c8e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 19 Mar 2023 11:38:10 +0200 Subject: [PATCH 0484/1892] Update 4.2.rst --- releases/4.2.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 94e524849..b795b2ec3 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -26,7 +26,7 @@ New Features Newly Released Connector Drivers -------------------------------- -Pysqream 3.2.4 - `.tar.gz file <https://github.com/SQream/pysqream/releases>`_ Supports Python 9(??) +Pysqream 3.2.4 - `.tar.gz file <https://github.com/SQream/pysqream/releases>`_ Supports Python 3.9 ODBC 4.4.4 :ref:`Getting the ODBC Driver<odbc>` @@ -49,7 +49,8 @@ Known Issues :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. -Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression. +Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression + Version 4.2 resolved Issues From 7a45fee70d699d3fba87caa085caca64e14641e9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 11:34:16 +0200 Subject: [PATCH 0485/1892] Update power.rst --- reference/sql/sql_functions/scalar_functions/numeric/power.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/power.rst b/reference/sql/sql_functions/scalar_functions/numeric/power.rst index 2653f5510..27184118d 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/power.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/power.rst @@ -66,7 +66,7 @@ On floating point .. code-block:: psql - numbers=> SELECT POWER(3.0,x) FROM (VALUES (1), (2), (3), (4), (5)) AS t(x); + numbers=> SELECT POWER(3.0::double precision,x) FROM (VALUES (1), (2), (3), (4), (5)) AS t(x); power ----- 3.0 From 9b97e568ffa60e89719b7f4eebe499656116de24 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 12:35:09 +0200 Subject: [PATCH 0486/1892] Update installing_sqream_with_binary.rst --- installation_guides/installing_sqream_with_binary.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index 6a21ee29f..613b4b9fc 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -192,13 +192,14 @@ For an example of stopping actively running SQream services, see :ref:`Launching $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. -3. Replace the old version ``sqream-db-v2020.2``, with the new version ``sqream-db-v2021.1``: +3. Replace the old version ``sqream-db-v2021.1``, with the new version ``sqream-db-v2021.1``: .. code-block:: console $ cd /home/sqream $ mkdir tempfolder $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ cd tempfolder/ $ tar -xf sqream-db-v2021.1.tar.gz $ sudo mv sqream /usr/local/sqream-db-v2021.1 $ cd /usr/local From e490c0c27522c531d40b46be861a9c27e95ce9b2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 14:08:23 +0200 Subject: [PATCH 0487/1892] Update keywords_and_identifiers.rst --- .../sql_syntax/keywords_and_identifiers.rst | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index bc2cb1de6..598b12a17 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -44,29 +44,31 @@ The following table shows a full list of the reserved keywords: +-------------------+---------------------+--------------------+------------------+---------------+ | ``AS`` | ``DESC`` | ``INTERSECT`` | ``OPTION`` | ``TRAILING`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRUE`` | +| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRAN`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``UNION`` | +| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``TRUE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNIQUE`` | +| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNION`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``BOTH`` | ``END`` | ``JOIN`` | ``OVER`` | ``USER`` | +| ``BIGINT`` | ``END`` | ``JOIN`` | ``OVER`` | ``UNIQUE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CASE`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USING`` | +| ``BOTH`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USER`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CAST`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``VARIADIC`` | +| ``CASE`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``USING`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CHECK`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VERBOSE`` | +| ``CAST`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VARIADIC`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLLATE`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``WHEN`` | +| ``CHECK`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``VERBOSE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLUMN`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHERE`` | +| ``COLLATE`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHEN`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONCURRENTLY`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WINDOW`` | +| ``COLUMN`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WHERE`` | +-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONSTRAINT`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WITH`` | +| ``CONCURRENTLY`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WINDOW`` | ++-------------------+---------------------+--------------------+------------------+---------------+ +| ``CONSTRAINT`` | ``FUNCTION`` | ``MERGE`` | ``SELECT`` | ``WITH`` | +-------------------+---------------------+--------------------+------------------+ | -| ``CREATE`` | ``GRANT`` | ``MERGE`` | ``SELECT`` | | -+-------------------+---------------------+--------------------+------------------+ | -| ``CROSS`` | ``GROUP`` | ``NATURAL`` | ``SESSION_USER`` | | +| ``CREATE`` | ``GRANT`` | ``NATURAL`` | ``SESSION_USER`` | | ++-------------------+---------------------+--------------------+------------------+ | +| ``CROSS`` | ``GROUP`` | | | | +-------------------+---------------------+--------------------+------------------+---------------+ From d8567f4159bac827fab50199fbb50d33f0e007d1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 15:52:08 +0200 Subject: [PATCH 0488/1892] Update index.rst --- .../client_drivers/python/index.rst | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 6de634cd8..7db435a3b 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -117,34 +117,7 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins $ pip3.9 install pysqream pysqream-sqlalchemy -U -Validating Your Installation ------------------------------ -#. Create a file called ``sample.py``, containing the following: - -.. literalinclude:: sample.py - :language: python - :caption: pysqream Validation Script - :linenos: - -#. Verify that the parameters in the connection have been replaced with your respective SQream installation parameters. - - :: - -#. Run the sample file to verify that you can connect to SQream: - - .. code-block:: console - - $ python3.9 sample.py - Version: v2020.1 - - If the validation was successful, you can build an application using the SQream Python connector. If you receive a connection error, verify the following: - - * You have access to a running SQream database. - - :: - - * The connection parameters are correct. SQLAlchemy Examples ======================== From 7e1b4cfe92543cc5da7512b9d0ecbe1c9291200b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 15:54:50 +0200 Subject: [PATCH 0489/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index d9ed6d160..662e6fc4b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -45,7 +45,7 @@ The following are applicable to all operating systems: * **Python** - Recommended installation via ``pip``: - * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.4>`_ - pysqream v3.2.4 (.tar.gz) + * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ - pysqream v3.2.5 (.tar.gz) * :ref:`pysqream` .. _nodejs: @@ -97,8 +97,7 @@ The following are applicable to Windows: nodejs/index odbc/index dotnet/index - Spark/index - + spark/index From f5700a3ca2e3d3f724608b6cb9debd80c210c1f3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 17:41:42 +0200 Subject: [PATCH 0490/1892] Update 4.2.rst --- releases/4.2.rst | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index b795b2ec3..f0f357775 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -26,11 +26,17 @@ New Features Newly Released Connector Drivers -------------------------------- -Pysqream 3.2.4 - `.tar.gz file <https://github.com/SQream/pysqream/releases>`_ Supports Python 3.9 +► Pysqream 3.2.5 + * Supports Python version 3.9 and newer + * `.tar.gz file <`Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ + * :ref:`Documentation<pysqream>` -ODBC 4.4.4 :ref:`Getting the ODBC Driver<odbc>` +► ODBC 4.4.4 + * :ref:`Getting the ODBC Driver<odbc>` -JDBC 4.5.8 `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ +► JDBC 4.5.8 + * `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ + * :ref:`Documentation<java_jdbc>` Storage Version --------------- @@ -47,9 +53,9 @@ SQream Studio v5.5.4 has been released. Known Issues ------------ -:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. -Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression +* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression @@ -89,7 +95,6 @@ Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. * Support in ``[]`` for delimiting database object identifiers ends on June 1st, 2023. - * To delimit database object identifiers, you will be able to use double quotes ``""``. @@ -98,9 +103,7 @@ The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_ The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. * Support in the ``VARCHAR`` data type ends at September 30th, 2023. - * ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. - * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. From a6de4c4eae75cb6fef2dd9fa08ee0abf70dbffec Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 Mar 2023 17:43:55 +0200 Subject: [PATCH 0491/1892] Update 4.2.rst --- releases/4.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index f0f357775..457422739 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -28,7 +28,7 @@ Newly Released Connector Drivers ► Pysqream 3.2.5 * Supports Python version 3.9 and newer - * `.tar.gz file <`Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ + * `.tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ * :ref:`Documentation<pysqream>` ► ODBC 4.4.4 From 2c0e604d3205825d47e91c879073c95b683fec59 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 09:41:37 +0200 Subject: [PATCH 0492/1892] Update power.rst --- reference/sql/sql_functions/scalar_functions/numeric/power.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/power.rst b/reference/sql/sql_functions/scalar_functions/numeric/power.rst index 27184118d..66d379c62 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/power.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/power.rst @@ -66,7 +66,7 @@ On floating point .. code-block:: psql - numbers=> SELECT POWER(3.0::double precision,x) FROM (VALUES (1), (2), (3), (4), (5)) AS t(x); + numbers=> SELECT POWER(3.0::double,x) FROM (VALUES (1), (2), (3), (4), (5)) AS t(x); power ----- 3.0 From ebb6c317f227d8b314c3322b3a5b94f4d26eeeac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:51:28 +0200 Subject: [PATCH 0493/1892] Update sign.rst --- .../scalar_functions/numeric/sign.rst | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst index 1fc32d1b7..db2ff7547 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst @@ -4,7 +4,7 @@ SIGN ************************** -The SIGN function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL. The function returns an integer value of -1, 0, or 1, depending on the sign of the input expression. +The ``SIGN`` function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL, and returns an ``INT`` value of -1, 0, or 1, depending on the sign of the input argument. @@ -13,7 +13,7 @@ Syntax .. code-block:: postgres - SELECT SIGN (); + SELECT SIGN(expr); Arguments ========= @@ -27,14 +27,18 @@ Arguments * - ``numeric_expression`` - Numeric data types -Returns -============ +Return +====== +Returns an output of the same data type as the input data type. -* -1 if the input expression is negative +Depending on the sign of the input argument, the return is: -* 0 if the input expression is zero +* -1, if the input expression is negative -* 1 if the input expression is positive +* 0, if the input expression is zero + +* 1, if the input expression is positive + Example From 47fb2564f84471bd830a2354b156440f245b035a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 11:58:49 +0200 Subject: [PATCH 0494/1892] Update joins.rst --- reference/sql/sql_syntax/joins.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index b12b08875..b9d04c589 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -47,7 +47,6 @@ The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres left_side [ INNER ] JOIN left_side ON value_expr - left_side [ INNER ] JOIN left_side USING ( join_column [, ... ] ) Inner joins are the default join type and return rows from the ``left_side`` and ``right_side`` based on a matching condition. @@ -77,7 +76,6 @@ The following shows the correct syntax for creating an **left outer join**: .. code-block:: postgres left_side LEFT [ OUTER ] JOIN right_side ON value_expr - left_side LEFT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) Left outer joins are similar to inner joins, except that for every ``left_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``right_side`` column. @@ -93,7 +91,6 @@ The following shows the correct syntax for creating an **right outer join**: .. code-block:: postgres left_side RIGHT [ OUTER ] JOIN right_side ON value_expr - left_side RIGHT [ OUTER ] JOIN right_side USING ( join_column [, ... ] ) Right outer joins are similar to inner joins, except that for every ``right_side`` row without a matching condition, a ``NULL`` value is returned for the corresponding ``left_side`` column. @@ -161,8 +158,6 @@ For example, the following is displayed when two name columns match: The ``ON`` clause is optional for ``LEFT`` and ``RIGHT`` joins. However, excluding it results in a computationally intensive cross join. -.. tip:: SQream DB does not support the ``USING`` syntax. However, queries can be easily rewritten. ``left_side JOIN right_side using (name)`` is equivalent to ``ON left_side.name = right_side.name`` - Join Type Examples From 898ae7c0b0c05e8ebb91e903835912dae60388ac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 15:43:38 +0200 Subject: [PATCH 0495/1892] Update installing_sqream_with_binary.rst --- installation_guides/installing_sqream_with_binary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index 613b4b9fc..bb26a8180 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -199,7 +199,7 @@ For an example of stopping actively running SQream services, see :ref:`Launching $ cd /home/sqream $ mkdir tempfolder $ mv sqream-db-v2021.1.tar.gz tempfolder/ - $ cd tempfolder/ + $ cd tempfolder/ $ tar -xf sqream-db-v2021.1.tar.gz $ sudo mv sqream /usr/local/sqream-db-v2021.1 $ cd /usr/local From 7e33349d32e15b337673d19e01a58d44a20351fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 16:25:55 +0200 Subject: [PATCH 0496/1892] Update update.rst --- .../sql_statements/dml_commands/update.rst | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 9f1d321b9..07718fc7a 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -144,27 +144,7 @@ The following shows an example of updating tables that contain multi-table expre ELSE 1 END FROM countries c - -Configuring Update Behavior ------------------ -The ``failOnNondeterministicUpdate`` flag is used to configure ``UPDATE`` behavior when updating tables containing multi-table expressions. This flag is needed when you use the ``FROM`` clause along with a set expression containing columns from additional tables. Doing this can cause a match to occur between a row from the target table with multiple rows from the additional tables. - -For instance, the example in the previous section sets the records sold to ``2`` when the country name is Israel. If you were to insert a new entry into this table with Israel spelled in Hebrew (using the same country ID), you would have two rows with identical country ID's. - -When this happens, both rows 5 and 6 in the ``bands`` table match both Israel entries. Because no algorithm exists for determining which entry to use, updating this table may either increase ``records_sold`` by 2 (for Israel in English) or 1 (for Israel in Hebrew). - -You must set the ``failOnNondeterministicUpdate`` flag to ``FALSE`` to prevent an error from occuring. - -Note that a similar ambiguity can occur when the Hebrew spelling is used in the following example: -.. code-block:: postgres - - UPDATE bands - SET record_count = record_count + 1 - FROM countries c - WHERE c.name = 'Israel' - -However, the ``WHERE`` clause above prevents a match with any entry other than the defined one. Because the target table row must match with the ``WHERE`` condition at least once to be included in the UPDATE statment, this scenario does not require configuring the ``failOnNondeterministicUpdate`` flag. Triggering a Clean-Up --------------------------------------- From 85610864dbe42fb261c93f6401a7c514ac1b22a3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Mar 2023 16:26:42 +0200 Subject: [PATCH 0497/1892] Update update.rst --- reference/sql/sql_statements/dml_commands/update.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 07718fc7a..3fa78a1a2 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -35,10 +35,10 @@ The following is the correct syntax for the ``UPDATE`` command: .. code-block:: postgres - UPDATE target_table_name [[AS] alias1] - SET column_name = expression [,...] - [FROM additional_table_name [[AS] alias2][,...]] - [WHERE condition] + UPDATE target_table_name [[AS] alias1] + SET column_name = expression [,...] + [FROM additional_table_name [[AS] alias2][,...]] + [WHERE condition] The following is the correct syntax for triggering a clean-up: From 101bbc228a2d6170611dc7d90672b01375800880 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Mar 2023 09:43:49 +0300 Subject: [PATCH 0498/1892] Update update.rst --- .../sql_statements/dml_commands/update.rst | 138 ++++++++++-------- 1 file changed, 79 insertions(+), 59 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 3fa78a1a2..6ead55166 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -40,12 +40,7 @@ The following is the correct syntax for the ``UPDATE`` command: [FROM additional_table_name [[AS] alias2][,...]] [WHERE condition] -The following is the correct syntax for triggering a clean-up: -.. code-block:: postgres - - SELECT cleanup_chunks('schema_name','table_name'); - SELECT cleanup_extents('schema_name','table_name'); Parameters ============ @@ -65,12 +60,57 @@ The following table describes the ``UPDATE`` parameters: - Additional tables used in the WHERE condition for performing complex joins. * - ``condition`` - Specifies the condition for updating the data. - -.. note:: Similar to a DELETE statement, an UPDATE statement may leave some uncleaned data behind, which requires a cleanup operation. Examples =========== -The **Examples** section includes the following examples: + +The examples section shows how to modify the value of certain columns in existing rows without creating a table. + +To be able to follow the examples, create these two tables: + +**countries** + ++----+--------+--------------+ +| id | name | records_sold | ++====+========+==============+ +| 1 | Israel | null | ++----+--------+--------------+ +| 2 | UK | null | ++----+--------+--------------+ +| 3 | USA | null | ++----+--------+--------------+ +| 4 | Sweden | null | ++----+--------+--------------+ + +**bands** + ++----+-------------+------------+ +| id | name | country_id | ++====+=============+============+ +| 1 | The Beatles | 2 | ++----+-------------+------------+ +| 2 | The Ramones | 3 | ++----+-------------+------------+ +| 3 | ABBA | 4 | ++----+-------------+------------+ +| 4 | Ace of Base | 4 | ++----+-------------+------------+ + +.. code-block:: postgres + + create or replace table countries ( id int, name text, records_sold int); + insert into countries values (1, 'Israel', null); + insert into countries values (2, 'UK', null); + insert into countries values (3, 'USA', null); + insert into countries values (4, 'Sweden', null); + + create or replace table bands ( id int, name text, country_id int); + insert into bands values (1, 'The Beatles', 2); + insert into bands values (2, 'The Ramones', 3); + insert into bands values (3, 'ABBA', 4); + insert into bands values (4, 'Ace of Base', 4); + + .. contents:: :local: @@ -78,27 +118,17 @@ The **Examples** section includes the following examples: Updating an Entire Table ----------------- -The Examples section shows how to modify the value of certain columns in existing rows without creating a table. The examples are based on the following tables: - -.. image:: /_static/images/delete_optimization.png -The following methods for updating an entire table generate the same output, and result with the ``bands`` record set to ``NULL``: +Two different ``UPDATE`` methods for updating an entire table. .. code-block:: postgres - UPDATE bands SET records_sold = 0; + UPDATE countries SET records_sold = 0; .. code-block:: postgres - UPDATE bands SET records_sold = 0 WHERE true; - -.. code-block:: postgres + UPDATE countries SET records_sold = 0 WHERE true; - UPDATE bands SET records_sold = 0 USING countries; - -.. code-block:: postgres - - UPDATE bands SET records_sold = 0 USING countries WHERE 1=1; Performing Simple Updates ----------------- @@ -106,7 +136,7 @@ The following is an example of performing a simple update: .. code-block:: postgres - UPDATE bands SET records_sold = records_sold + 1 WHERE name LIKE 'The %'; + UPDATE countries SET records_sold = records_sold + 1 WHERE name = 'Israel'; Updating Tables that Contain Multi-Table Conditions ----------------- @@ -114,61 +144,51 @@ The following shows an example of updating tables that contain multi-table condi .. code-block:: postgres - UPDATE bands - SET records_sold = records_sold + 1 - WHERE EXISTS ( - SELECT 1 FROM countries - WHERE countries.id=bands.country_id - AND country.name = 'Sweden' - ); - -You can also write the statement above using the FROM clause: + UPDATE countries + SET records_sold = records_sold + 1 + WHERE EXISTS ( + SELECT 1 FROM bands + WHERE bands.country_id = countries.id + AND bands.name = 'ABBA' + ); -.. code-block:: psql - - UPDATE bands - SET records_sold = records_sold + 1 - FROM countries - WHERE countries.id=bands.country_id AND country.name = 'Sweden'; Updating Tables that Contain Multi-Table Expressions ------------------ +---------------------------------------------------- The following shows an example of updating tables that contain multi-table expressions: .. code-block:: postgres - UPDATE bands - SET records_sold = records_sold + - CASE - WHEN c.name = 'Israel' THEN 2 - ELSE 1 - END - FROM countries c - + UPDATE countries + SET records_sold = records_sold + + CASE + WHEN name = 'Israel' THEN 2 + ELSE 1 + END + FROM countries c + ; + +Triggering a Cleanup +--------------------- -Triggering a Clean-Up ---------------------------------------- -The following shows an example of triggering a clean-up: +When an ``UPDATE`` statement is executed, it creates a new table that contains the updated data, while the original table remains intact. As a result, residual data may be left behind, and a cleanup operation is necessary to ensure the database remains in a consistent state. -.. code-block:: psql + +The following is the syntax for triggering a cleanup: - SELECT * FROM sqream_catalog.discarded_chunks; - SELECT cleanup_discarded_chunks('public','t'); +.. code-block:: postgres -The following is an example of the output generated from the above: + SELECT cleanup_chunks('schema_name','table_name'); + SELECT cleanup_extents('schema_name','table_name'); -* **database_name** - _discarded_master -* **table_id** - 24 -* **column_id** - 1 -* **extent_ID** - 0 Permissions -============= +=========== Executing an ``UPDATE`` statement requires the following permissions: * Both ``UPDATE`` and ``SELECT`` permissions on the target table. * The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). Locking and Concurrency -============= +======================= Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file From ba4ff2b52d0600b1173547a1f7833865294bd5c5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Mar 2023 09:46:03 +0300 Subject: [PATCH 0499/1892] Update update.rst --- reference/sql/sql_statements/dml_commands/update.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 6ead55166..3bbeceeef 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -187,7 +187,7 @@ Permissions Executing an ``UPDATE`` statement requires the following permissions: * Both ``UPDATE`` and ``SELECT`` permissions on the target table. -* The ``SELECT`` permission for each additional table you reference in the statement (in ither the ``FROM`` clause or ``WHERE`` subquery section). +* The ``SELECT`` permission for each additional table you reference in the statement (in either the ``FROM`` clause or ``WHERE`` subquery section). Locking and Concurrency ======================= From 6c28dcfcf5d30e12a0372e27f410d3be17e7d099 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Apr 2023 13:55:19 +0300 Subject: [PATCH 0500/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 25e150881..349d4c04d 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -15,7 +15,7 @@ You can rectify this by casting the value to a larger data type, as shown below: SQream supports the following three data conversion types: -* ``CAST(<value> TO <data type>)``, to convert a value from one type to another. For example, ``CAST('1997-01-01' TO DATE)``, ``CAST(3.45 TO SMALLINT)``, ``CAST(some_column TO TEXT)``. +* ``CAST(<value> AS <data type>)``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS TEXT)``. :: From aae27fa8d616cd5552c1b89ac3c41e47f81ec1c6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Apr 2023 17:46:34 +0300 Subject: [PATCH 0501/1892] Update copy_to.rst --- reference/sql/sql_statements/dml_commands/copy_to.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 167f70c23..00264f50d 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -140,9 +140,9 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | ) | Right Parenthesis | 41 | 51 | 29 | 101001 | &#41; | &rpar; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -| * | Asterisk | 42 | 52 | 2A | 101010 | &#42; | &ast; | +| \*\ | Asterisk | 42 | 52 | 2A | 101010 | &#42; | &ast; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -| + | Plus Sign | 43 | 53 | 2B | 101011 | &#43; | &plus; | +| \+\ | Plus Sign | 43 | 53 | 2B | 101011 | &#43; | &plus; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | , | Comma | 44 | 54 | 2C | 101100 | &#44; | &comma; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ @@ -162,7 +162,7 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | [ | Left Square Bracket | 91 | 133 | 5B | 1011011 | &#91; | &lsqb; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -| \ | Backslash | 92 | 134 | 5C | 1011100 | \&\#92\; | &bsol; | +| \\ | Backslash | 92 | 134 | 5C | 1011100 | \&\#92\; | &bsol; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | ] | Right Square Bracket | 93 | 135 | 5D | 1011101 | &#93; | &rsqb; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ @@ -174,7 +174,7 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | { | Left Curly Bracket | 123 | 173 | 7B | 1111011 | &#123; | &lcub; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -| | | Vertical Bar | 124 | 174 | 7C | 1111100 | &#124; | &verbar; | +| \|\ | Vertical Bar | 124 | 174 | 7C | 1111100 | &#124; | &verbar; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | } | Right Curly Bracket | 125 | 175 | 7D | 1111101 | &#125; | &rcub; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ @@ -270,7 +270,7 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 34 | " | Double Quote | 42 | 22 | 100010 | &#34; | &quot; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 45 | - | Minus Sign | 55 | 2D | 101101 | &#45; | &minus; | +| 45 | \-\ | Minus Sign | 55 | 2D | 101101 | &#45; | &minus; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 46 | . | Period | 56 | 2E | 101110 | &#46; | &period; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ From 58d86291ad440e7635c349d89ab8f2dcb1513cc8 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:08:49 +0300 Subject: [PATCH 0502/1892] Update not.rst --- .../scalar_functions/bitwise/not.rst | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst index 20bf60f02..a45495657 100644 --- a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst +++ b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst @@ -1,10 +1,10 @@ .. _bitwise_not: *************************** -``~`` (bitwise ``NOT``) +``~`` (bitwise NOT) *************************** -Returns the bitwise ``NOT`` (negation) of two numeric expressions. This is the bitwise complement. +The bitwise NOT operator (``~``) is a unary operator used to invert the bits of a binary value. It converts each 0 to a 1 and each 1 to a 0, resulting in the ones' complement of the original value. Syntax ========== @@ -32,12 +32,12 @@ Arguments Returns ============ -Returns an integer that is the bitwise ``NOT`` of the input. +Returns an integer that is the bitwise ``NOT`` of the input and preserves the data type of the argument supplied. Notes ======= -* If the value is NULL, the result is NULL. +* If the value is ``NULL``, the result is ``NULL``. Examples =========== @@ -56,21 +56,15 @@ Examples .. code-block:: psql - master=> CREATE TABLE bit(b1 int, b2 int, b3 int); - executed - - master=> INSERT INTO bit VALUES (1,2,3), (2, 4, 6), (4, 2, 6), (2, 8, 16), (null, null, 64), (5, 3, 1), (6, 1, 0); - executed + + master=> CREATE OR REPLACE TABLE t (xtinyInt tinyInt, xsmallInt smallInt, xint int, xbigInt bigInt); + + master=> INSERT INTO t VALUES (1,1,1,1); + + master=> SELECT ~xtinyInt, ~xsmallInt, ~xint, ~xbigInt from t; - SELECT b1, b2, b3, ~b1, ~b2, ~b3 FROM bit; - b1 | b2 | b3 | ?column? | ?column?0 | ?column?1 - ---+----+----+----------+-----------+---------- - 1 | 2 | 3 | -2 | -3 | -4 - 2 | 4 | 6 | -3 | -5 | -7 - 4 | 2 | 6 | -5 | -3 | -7 - 2 | 8 | 16 | -3 | -9 | -17 - | | 64 | | | -65 - 5 | 3 | 1 | -6 | -4 | -2 - 6 | 1 | 0 | -7 | -2 | -1 + ?column? | ?column?0 | ?column?1 | ?column?2 | + ---------+-----------+-----------+-----------+ + 254 | -2 | -2 | -2 | From a8c63278e9821087b614b4d370ccf6c2102813f9 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Apr 2023 13:15:10 +0300 Subject: [PATCH 0503/1892] Update charindex.rst --- .../sql/sql_functions/scalar_functions/string/charindex.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index 3ad4ca1f3..9b00084f5 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -29,7 +29,7 @@ Arguments * - ``haystack_string_expr`` - String to search within * - ``start_location`` - - An integer at which the search starts. This value is optinoal and when not supplied, the search starts at the beggining of ``needle_string_expr`` + - An integer at which the search starts. This value is optional and when not supplied, the search starts at the beggining of ``needle_string_expr`` Returns ============ @@ -73,4 +73,4 @@ Using ``CHARINDEX`` "Beware the Jabberwock, my son! | 9 The jaws that bite, the claws that catch! | 27 Beware the Jubjub bird, and shun | 8 - The frumious Bandersnatch!" | 0 \ No newline at end of file + The frumious Bandersnatch!" | 0 From 0d120ad606400f9a3a72663e0b519b7412b3dde3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Apr 2023 09:59:29 +0300 Subject: [PATCH 0504/1892] Update len.rst --- .../scalar_functions/string/len.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/len.rst b/reference/sql/sql_functions/scalar_functions/string/len.rst index fdd671423..2dee61a61 100644 --- a/reference/sql/sql_functions/scalar_functions/string/len.rst +++ b/reference/sql/sql_functions/scalar_functions/string/len.rst @@ -4,13 +4,13 @@ LEN ************************** -Calculates the number of characters in a string. +The LEN function calculates the number of characters in a string. Keep in mind that SQream DB does not count trailing spaces, but does count leading spaces. For UTF-8 encoded ``TEXT`` strings, multi-byte characters are counted as a single character. To get the length in bytes, see :ref:`octet_length`. To get the length in characters, see :ref:`char_length`. + .. note:: - - * This function is provided for SQL Server compatability. - - * For UTF-8 encoded ``TEXT`` strings, multi-byte characters are counted as a single character. To get the length in bytes, see :ref:`octet_length`. To get the length in characters, see :ref:`char_length`. + + This function is provided for SQL Server compatibility. + Syntax ========== @@ -35,12 +35,12 @@ Arguments Returns ============ -Returns an integer containing the number of characters in the string. +The LEN function returns an integer value representing the length of the input string, which includes any leading spaces but excludes any trailing spaces. Notes ======= -* If the value is NULL, the result is NULL. +* If the value is ``NULL``, the result is ``NULL``. Examples =========== @@ -81,8 +81,6 @@ ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and H Length of an ASCII string ---------------------------- -.. note:: SQream DB does not count trailing spaces, but does keep leading spaces. - .. code-block:: psql t=> SELECT LEN('Trailing spaces are not counted '); From d7b7b60772f22fbee77ce7ac3f7a26c92ac965a2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 11:14:13 +0300 Subject: [PATCH 0505/1892] Update not.rst --- reference/sql/sql_functions/scalar_functions/bitwise/not.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst index a45495657..69d81e1ce 100644 --- a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst +++ b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -Returns an integer that is the bitwise ``NOT`` of the input and preserves the data type of the argument supplied. +Returns an integer that is the bitwise NOT of the input and preserves the data type of the argument supplied. Notes ======= From cf8ab4e65911bc298e487697efab17d078a0ce30 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 13:26:53 +0300 Subject: [PATCH 0506/1892] Update upgrade_storage.rst --- reference/cli/upgrade_storage.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/reference/cli/upgrade_storage.rst b/reference/cli/upgrade_storage.rst index 867df3e03..0747981f7 100644 --- a/reference/cli/upgrade_storage.rst +++ b/reference/cli/upgrade_storage.rst @@ -28,11 +28,17 @@ Command line arguments :header-rows: 1 * - Argument - - Required + - State - Description - * - Storage path - - ✓ - - Full path to a valid storage cluster + * - ``storage_path`` + - Mandatory + - Full path to a valid storage cluster. + * - ``storage_version`` + - Optional + - Displays your current storage version. + * - ``check_predicates=0`` + - Optional + - Allows the upgrade process to proceed even if there are predicates marked for deletion. Results and error codes ======================== From 9550cfd841d7cc7cba92c7f78161f08ced314749 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:32:16 +0300 Subject: [PATCH 0507/1892] Update catalog_reference_examples.rst --- reference/catalog_reference_examples.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst index 4531dfefc..3e605ee05 100644 --- a/reference/catalog_reference_examples.rst +++ b/reference/catalog_reference_examples.rst @@ -28,10 +28,10 @@ Listing All Schemas in a Database .. code-block:: psql master=> SELECT * FROM sqream_catalog.schemas; - schema_id | schema_name | schema_owner | rechunker_ignore - ----------+---------------+--------------+----------------- - 0 | public | sqream | false - 1 | secret_schema | mjordan | false + schema_id | schema_name | rechunker_ignore + ----------+---------------+----------------- + 0 | public | false + 1 | secret_schema | false Listing Columns and Their Types for a Specific Table From 93a5904241dda9e22a67e224a0cb3d227ced28db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 16:48:15 +0300 Subject: [PATCH 0508/1892] Update catalog_reference_catalog_tables.rst --- reference/catalog_reference_catalog_tables.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 4f4d60b76..b62b6c321 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -319,7 +319,9 @@ The ``roles_memberships`` data object identifies the role memberships in the dat * - ``member_role_id`` - Shows the ID of the parent role that this role inherits from. * - ``inherit`` - - Identifies whether permissions are inherited (``1`` - yes, ``0`` - no). + - Identifies whether permissions are inherited (``1`` - yes, ``0`` - no). + * - ``admin`` + - Identifies whether role is admin (``1`` - yes, ``0`` - no). .. _schemas: From 119e84f81a9a692a65f41d449ef648ed8f23efb8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 17:24:30 +0300 Subject: [PATCH 0509/1892] =?UTF-8?q?Altering=20Public=20Role=20Permission?= =?UTF-8?q?s=EF=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- operational_guides/access_control_managing_roles.rst | 2 +- operational_guides/foreign_tables.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index 15729fa53..384a101ba 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -80,7 +80,7 @@ Altering Public Role Permissions There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can ``CREATE``, :ref:`insert`, :ref:`delete`, :ref:`select` and :ref:`UPDATE` from objects in the ``PUBLIC`` schema. +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can :ref:`insert`, :ref:`delete`, :ref:`select`, :ref:`UPDATE` and ``CREATE`` (:ref:`databases<create_database>`, :ref:`schemas<create_schema>`, :ref:`roles<create_role>`, :ref:`functions<create_function>`, :ref:`views<create_view>`, and :ref:`tables<create_table>`) from objects in the ``PUBLIC`` schema. Altering Role Membership (Groups) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index bc8c401a6..557e76c16 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -47,7 +47,7 @@ We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_ Creating a Foreign Table ----------------------------- -Based on the source file structure, we we :ref:`create a foreign table<create_external_table>` with the appropriate structure, and point it to the file. +Based on the source file structure, we :ref:`create a foreign table<create_external_table>` with the appropriate structure, and point it to the file. .. code-block:: postgres From 1cffc5ebe9b4f66dbea088f28f6117257f01ee9a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Apr 2023 17:26:46 +0300 Subject: [PATCH 0510/1892] Update access_control_managing_roles.rst --- operational_guides/access_control_managing_roles.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index 384a101ba..3f032bcd5 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -89,7 +89,7 @@ Altering Role Membership (Groups) Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. To use a role purely as a group, omit granting it ``LOGIN`` and ``PASSWORD`` permissions. - + The ``CONNECT`` permission can be given directly to user roles, and/or to the groups they are part of. .. code-block:: postgres From 017d4a8a35b100c2f7dc62fc86746437111380c4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 09:41:05 +0300 Subject: [PATCH 0511/1892] Update upgrade_storage.rst --- reference/cli/upgrade_storage.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/cli/upgrade_storage.rst b/reference/cli/upgrade_storage.rst index 0747981f7..5b3f60625 100644 --- a/reference/cli/upgrade_storage.rst +++ b/reference/cli/upgrade_storage.rst @@ -21,7 +21,7 @@ Command line arguments .. code-block:: console - $ upgrade_storage <storage path> + $ upgrade_storage <storage path> [option] .. list-table:: :widths: auto @@ -33,10 +33,10 @@ Command line arguments * - ``storage_path`` - Mandatory - Full path to a valid storage cluster. - * - ``storage_version`` + * - ``--storage_version`` - Optional - Displays your current storage version. - * - ``check_predicates=0`` + * - ``--check_predicates=0`` - Optional - Allows the upgrade process to proceed even if there are predicates marked for deletion. From 8382c3c2ead1ee905c7b738316d9035c413693f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 10:05:44 +0300 Subject: [PATCH 0512/1892] Update upgrade_storage.rst --- reference/cli/upgrade_storage.rst | 37 +++++++++++++++++++------------ 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/reference/cli/upgrade_storage.rst b/reference/cli/upgrade_storage.rst index 5b3f60625..669d47c45 100644 --- a/reference/cli/upgrade_storage.rst +++ b/reference/cli/upgrade_storage.rst @@ -14,31 +14,40 @@ Running upgrade_storage ``upgrade_storage`` can be found in the ``bin`` directory of your SQream DB installation. -Command line arguments -========================== - -``upgrade_storage`` contains one positional argument: - -.. code-block:: console - - $ upgrade_storage <storage path> [option] +Command line arguments and options +---------------------------------- .. list-table:: :widths: auto :header-rows: 1 - * - Argument - - State + * - Parameter + - Parameter Type - Description * - ``storage_path`` - - Mandatory + - Argument - Full path to a valid storage cluster. * - ``--storage_version`` - - Optional + - Option - Displays your current storage version. * - ``--check_predicates=0`` - - Optional - - Allows the upgrade process to proceed even if there are predicates marked for deletion. + - Option + - Allows the upgrade process to proceed even if there are predicates marked for deletion. + + +Syntax +------ + +.. code-block:: console + + $ upgrade_storage <storage path> [option] + + +.. code-block:: console + + $ upgrade_storage <storage path> [--storage_version] [--check_predicates=0] + + Results and error codes ======================== From 058e98c103f1c3b5099c9d18eb4810c582c5e141 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 15:11:39 +0300 Subject: [PATCH 0513/1892] 4.2 release --- .../client_drivers/Spark/index.rst | 2 +- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.2.rst | 19 ++++++++++++++----- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index 5f3d6caac..a7b031e53 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -22,7 +22,7 @@ To use Spark with SQream, it is essential that you have the following installed: * SQream version 2022.1.8 or later * Spark version 3.3.1 or later -* SQream Spark Connector 1.0.0 +* `SQream Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`JDBC<jdbc>` version 4.5.6 or later Connector Configuration diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 662e6fc4b..cc6b670c0 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -38,7 +38,7 @@ The following are applicable to all operating systems: * **Spark**: - * `Spark Connector <>`_ + * `Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`spark` .. _python: diff --git a/releases/4.2.rst b/releases/4.2.rst index 457422739..872b2da0f 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -6,7 +6,7 @@ Release Notes 4.2 SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. -The 4.2 release notes were released on 03/19/2023 and describe the following: +The 4.2 release notes were released on 04/23/2023 and describe the following: .. contents:: :local: @@ -38,6 +38,10 @@ Newly Released Connector Drivers * `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ * :ref:`Documentation<java_jdbc>` +► Spark 5.0.0 + * `.jar file <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ + * :ref:`Documentation<spark>` + Storage Version --------------- @@ -65,11 +69,18 @@ Version 4.2 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +========================+==========================================================================================+ -| SQ-12598 | External table ``SELECT`` statement issue | +| SQ-12078 | | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-12598 | Foreign table ``SELECT`` statement issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13018 | | +------------------------+------------------------------------------------------------------------------------------+ | SQ-13055 | Pysqream ``NULL`` value issue | +------------------------+------------------------------------------------------------------------------------------+ - +| SQ-13322 | | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13450 | Storage upgrade issue | ++------------------------+------------------------------------------------------------------------------------------+ Configuration Changes --------------------- @@ -107,8 +118,6 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. - - End of Support --------------- No End of Support changes were made. From 39674aa25c59ac4430a04f8c14d926761400197a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 15:32:22 +0300 Subject: [PATCH 0514/1892] release --- releases/4.2.rst | 2 -- releases/index.rst | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 872b2da0f..578e645aa 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -69,8 +69,6 @@ Version 4.2 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +========================+==========================================================================================+ -| SQ-12078 | | -+------------------------+------------------------------------------------------------------------------------------+ | SQ-12598 | Foreign table ``SELECT`` statement issue | +------------------------+------------------------------------------------------------------------------------------+ | SQ-13018 | | diff --git a/releases/index.rst b/releases/index.rst index 63eca8c7f..a827d375a 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -13,7 +13,7 @@ Release Notes * - Version - Release Date * - :ref:`4.2` - - March 19, 2023 + - April 23, 2023 * - :ref:`4.1` - March 01, 2023 * - :ref:`4.0` From 7bdd63aca488131a10a0addd1fac376aba64cf47 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 16:09:11 +0300 Subject: [PATCH 0515/1892] Update 4.2.rst --- releases/4.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 578e645aa..395c14f0b 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -71,7 +71,7 @@ Version 4.2 resolved Issues +========================+==========================================================================================+ | SQ-12598 | Foreign table ``SELECT`` statement issue | +------------------------+------------------------------------------------------------------------------------------+ -| SQ-13018 | | +| SQ-13018 | `cleanup_extent` operation buffer issue | +------------------------+------------------------------------------------------------------------------------------+ | SQ-13055 | Pysqream ``NULL`` value issue | +------------------------+------------------------------------------------------------------------------------------+ From d4d99f46c73e70146f424d0fbaca3d00b62134cb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Apr 2023 16:57:20 +0300 Subject: [PATCH 0516/1892] LEFT RIGHT --- reference/sql/sql_functions/scalar_functions/string/left.rst | 4 +--- .../sql/sql_functions/scalar_functions/string/right.rst | 5 ++--- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/left.rst b/reference/sql/sql_functions/scalar_functions/string/left.rst index 143c6eeb7..ce76244e9 100644 --- a/reference/sql/sql_functions/scalar_functions/string/left.rst +++ b/reference/sql/sql_functions/scalar_functions/string/left.rst @@ -27,9 +27,7 @@ Arguments * - ``expr`` - String expression * - ``character_count`` - - A positive integer that specifies how many characters to return - * - ``cnt`` - - The number of characters to be returned. If ``cnt <= 0``, an empty string is returned. + - The number of characters to be returned. If ``character_count <= 0``, an empty string is returned. Returns ============ diff --git a/reference/sql/sql_functions/scalar_functions/string/right.rst b/reference/sql/sql_functions/scalar_functions/string/right.rst index 8cf750510..9c3d89838 100644 --- a/reference/sql/sql_functions/scalar_functions/string/right.rst +++ b/reference/sql/sql_functions/scalar_functions/string/right.rst @@ -27,9 +27,8 @@ Arguments * - ``expr`` - String expression * - ``character_count`` - - A positive integer that specifies how many characters to return. - * - ``cnt`` - - The number of characters to be returned. If ``cnt <= 0``, an empty string is returned. + - The number of characters to be returned. If ``character_count <= 0``, an empty string is returned. + Returns ============ From 293121ddf81a51a56e9d5145166516bde93576f9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Apr 2023 14:35:46 +0300 Subject: [PATCH 0517/1892] Update 4.2.rst --- releases/4.2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 395c14f0b..7fe2f2be3 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -75,7 +75,7 @@ Version 4.2 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | SQ-13055 | Pysqream ``NULL`` value issue | +------------------------+------------------------------------------------------------------------------------------+ -| SQ-13322 | | +| SQ-13322 | Clean up process is case sensitive | +------------------------+------------------------------------------------------------------------------------------+ | SQ-13450 | Storage upgrade issue | +------------------------+------------------------------------------------------------------------------------------+ From 8bd41eca57b0c4e0746f91da2ef89394c37572df Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Apr 2023 11:15:56 +0300 Subject: [PATCH 0518/1892] Update delete_guide.rst --- operational_guides/delete_guide.rst | 88 +++++++++++++---------------- 1 file changed, 40 insertions(+), 48 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index 0d6c4a41c..d257f0882 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -31,7 +31,7 @@ Deleting rows occurs in the following two phases: :: -* **Phase 2 - Clean-up** - The rows you marked for deletion in Phase 1 are physically deleted. The clean-up phase is not automated, letting users or DBAs control when to activate it. The files you marked for deletion during Phase 1 are removed from disk, which you do by by sequentially running the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. +* **Phase 2 - Clean-up** - The rows you marked for deletion in Phase 1 are physically deleted. The clean-up phase is not automated, letting users or DBAs control when to activate it. The files you marked for deletion during Phase 1 are removed from disk, which you do by sequentially running the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. .. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? @@ -39,7 +39,6 @@ Deleting rows occurs in the following two phases: Usage Notes ===================== -The **Usage Notes** section includes important information about the DELETE statement: .. contents:: :local: @@ -47,7 +46,6 @@ The **Usage Notes** section includes important information about the DELETE stat General Notes ---------------- -This section describes the general notes applicable when deleting rows: * The :ref:`alter_table` command and other DDL operations are locked on tables that require clean-up. If the estimated clean-up time exceeds the permitted threshold, an error message is displayed describing how to override the threshold limitation. For more information, see :ref:`concurrency_and_locks`. @@ -98,19 +96,22 @@ The following example shows how to delete rows from a table. The following table is displayed: .. code-block:: psql - - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 1 | Dog | 7 + 2 | Possum | 3 + 3 | Cat | 5 + 4 | Elephant | 6500 + 5 | Rhinoceros | 2100 + 6 | NULL | NULL + + 2. Delete rows from the table: .. code-block:: psql - farm=> DELETE FROM cool_animals WHERE weight > 1000; + farm=> DELETE FROM cool_animals WHERE animal_weight > 1000; 3. Display the table: @@ -122,10 +123,12 @@ The following example shows how to delete rows from a table. .. code-block:: psql - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 1 | Dog | 7 + 2 | Possum | 3 + 3 | Cat | 5 + 6 | NULL | NULL Deleting Values Based on Complex Predicates --------------------------------------------------- @@ -141,18 +144,21 @@ The following example shows how to delete values based on complex predicates. .. code-block:: psql - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 4,Elephant ,6500 - 5,Rhinoceros ,2100 - 6,\N,\N + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 1 | Dog | 7 + 2 | Possum | 3 + 3 | Cat | 5 + 4 | Elephant | 6500 + 5 | Rhinoceros | 2100 + 6 | NULL | NULL 2. Delete rows from the table: .. code-block:: psql - farm=> DELETE FROM cool_animals WHERE weight > 1000; + farm=> DELETE FROM cool_animals + WHERE animal_weight < 100 AND animal_name LIKE '%o%'; 3. Display the table: @@ -164,14 +170,14 @@ The following example shows how to delete values based on complex predicates. .. code-block:: psql - 1,Dog ,7 - 2,Possum ,3 - 3,Cat ,5 - 6,\N,\N + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 3 | Cat | 5 + 4 | Elephant | 6500 + 6 | NULL | NULL Identifying and Cleaning Up Tables --------------------------------------- -The **Identifying and Cleaning Up Tables** section includes the following examples: .. contents:: :local: @@ -179,7 +185,6 @@ The **Identifying and Cleaning Up Tables** section includes the following exampl Listing Tables that Have Not Been Cleaned Up ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following example shows how to list tables that have not been cleaned up: .. code-block:: psql @@ -193,7 +198,6 @@ The following example shows how to list tables that have not been cleaned up: Identifying Predicates for Clean-Up ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following example shows how to identify predicates for clean-up: .. code-block:: psql @@ -209,9 +213,8 @@ The following example shows how to identify predicates for clean-up: Triggering a Clean-Up ^^^^^^^^^^^^^^^^^^^^^^ -The following example shows how to trigger a clean-up: -1. Run the chunk ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: +1. Run the ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: .. code-block:: psql @@ -233,30 +236,19 @@ The following example shows how to trigger a clean-up: WHERE t.table_name = 'cool_animals'; Best Practices -===================================== -This section includes the best practices when deleting rows: +============== -* Run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` after running large ``DELETE`` operations. - - :: -* When you delete large segments of data from very large tables, consider running a ``CREATE TABLE AS`` operation instead, renaming, and dropping the original table. +* After running large ``DELETE`` operations, run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` to improve performance and free up space. These commands remove empty chunks and extents, respectively, and can help prevent fragmentation of the table. :: -* Avoid killing ``CLEANUP_EXTENTS`` operations in progress. +* If you need to delete large segments of data from very large tables, consider using a ``CREATE TABLE AS`` operation instead. This involves creating a new table with the desired data and then renaming and dropping the original table. This approach can be faster and more efficient than running a large ``DELETE`` operation, especially if you don't need to preserve any data in the original table. :: -* SQream is optimized for time-based data, which is data naturally ordered according to date or timestamp. Deleting rows based on such columns leads to increased performance. +* Avoid interrupting or killing ``CLEANUP_EXTENTS`` operations that are in progress. These operations can take a while to complete, especially if the table is very large or has a lot of fragmentation, but interrupting them can cause data inconsistencies or other issues. -.. soft update concept - -.. delete cleanup and it's properties. automatic/manual, in transaction or background - -.. automatic background gives fast delete, minimal transaction overhead, -.. small cost to queries until background reorganised - -.. when does delete use the metadata effectively + :: -.. more examples \ No newline at end of file +* SQream is optimized for time-based data, which means that data that is naturally ordered according to date or timestamp fields will generally perform better. If you need to delete rows from such tables, consider using the time-based columns in your ``DELETE`` predicates to improve performance. From 5fb2f2d2aa71ea55350da189fe46dfdf1a98cc4d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Apr 2023 14:11:45 +0300 Subject: [PATCH 0519/1892] Update delete_guide.rst --- operational_guides/delete_guide.rst | 34 ++++++++++------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index d257f0882..618c05a1a 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -11,31 +11,30 @@ The **Deleting Data** page describes how the **Delete** statement works and how Overview ======================================== -Deleting data typically refers to deleting rows, but can refer to deleting other table content as well. The general workflow for deleting data is to delete data followed by triggering a cleanup operation. The cleanup operation reclaims the space occupied by the deleted rows, discussed further below. +When working with a table in a database, deleting data typically involves removing rows, although it can also involve removing columns. The process for deleting data involves first deleting the desired content, followed by a cleanup operation that reclaims the space previously occupied by the deleted data. This process is further explained below. -The **DELETE** statement deletes rows defined by a predicate that you have specified, preventing them from appearing in subsequent queries. - -For example, the predicate below defines and deletes rows containing animals heavier than 1000 weight units: +The ``DELETE`` statement is used to remove rows that match a specified predicate, thereby preventing them from being included in subsequent queries. For example, the following statement deletes all rows in the ``cool_animals`` table where the weight of the animal is greater than 1000 weight units: .. code-block:: psql - farm=> DELETE FROM cool_animals WHERE weight > 1000; + DELETE FROM cool_animals WHERE weight > 1000; + +By using the WHERE clause in the DELETE statement, you can specify a condition or predicate that determines which rows should be deleted from the table. In this example, the predicate "weight > 1000" specifies that only rows with an animal weight greater than 1000 should be deleted. -The major benefit of the DELETE statement is that it deletes transactions simply and quickly. The Deletion Process ========== -Deleting rows occurs in the following two phases: -* **Phase 1 - Deletion** - All rows you mark for deletion are ignored when you run any query. These rows are not deleted until the clean-up phase. +When you delete rows from a SQL database, the actual deletion process occurs in two steps: + +* Marking for Deletion: When you issue a ``DELETE`` statement to remove one or more rows from a table, the database marks these rows for deletion. These rows are not actually removed from the database immediately, but are instead temporarily ignored when you run any query. :: -* **Phase 2 - Clean-up** - The rows you marked for deletion in Phase 1 are physically deleted. The clean-up phase is not automated, letting users or DBAs control when to activate it. The files you marked for deletion during Phase 1 are removed from disk, which you do by sequentially running the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. +* Clean-up: Once the rows have been marked for deletion, you need to trigger a clean-up operation to permanently remove them from the database. During the clean-up process, the database frees up the disk space previously occupied by the deleted rows. To remove all files associated with the deleted rows, you can use the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. These commands should be run sequentially to ensure that these files removed from disk. -.. TODO: isn't the delete cleanup able to complete a certain amount of work transactionally, so that you can do a massive cleanup in stages? +If you want to delete all rows from a table, you can use the :ref:`TRUNCATE<truncate>` command, which deletes all rows in a table and frees up the associated disk space. -.. TODO: our current best practices is to use a cron job with sqream sql to run the delete cleanup. we should document how to do this, we have customers with very different delete schedules so we can give a few extreme examples and when/why you'd use them. Usage Notes ===================== @@ -57,15 +56,6 @@ General Notes set mixedColumnChunksThreshold=XXX; -Deleting Data does not Free Space ------------------------------------------ -With the exception of running a full table delete, deleting data does not free unused disk space. To free unused disk space you must trigger the clean-up process. - -For more information on running a full table delete, see :ref:`TRUNCATE<truncate>`. - - :: - -For more information on freeing disk space, see :ref:`Triggering a Clean-Up<trigger_cleanup>`. Clean-Up Operations Are I/O Intensive ------------------------------- @@ -235,8 +225,8 @@ Triggering a Clean-Up ON dp.table_id = t.table_id WHERE t.table_name = 'cool_animals'; -Best Practices -============== +Best Practice +============= * After running large ``DELETE`` operations, run ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS`` to improve performance and free up space. These commands remove empty chunks and extents, respectively, and can help prevent fragmentation of the table. From 31a8c70cb7f6fb5eefe5192816513fd640d273a0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:27:00 +0300 Subject: [PATCH 0520/1892] clean up --- operational_guides/delete_guide.rst | 173 ++++++++++++++-------------- reference/cli/upgrade_storage.rst | 4 +- 2 files changed, 87 insertions(+), 90 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index 618c05a1a..dae2d02d1 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -3,14 +3,7 @@ *********************** Deleting Data *********************** -The **Deleting Data** page describes how the **Delete** statement works and how to maintain data that you delete: -.. contents:: - :local: - :depth: 1 - -Overview -======================================== When working with a table in a database, deleting data typically involves removing rows, although it can also involve removing columns. The process for deleting data involves first deleting the desired content, followed by a cleanup operation that reclaims the space previously occupied by the deleted data. This process is further explained below. The ``DELETE`` statement is used to remove rows that match a specified predicate, thereby preventing them from being included in subsequent queries. For example, the following statement deletes all rows in the ``cool_animals`` table where the weight of the animal is greater than 1000 weight units: @@ -21,30 +14,29 @@ The ``DELETE`` statement is used to remove rows that match a specified predicate By using the WHERE clause in the DELETE statement, you can specify a condition or predicate that determines which rows should be deleted from the table. In this example, the predicate "weight > 1000" specifies that only rows with an animal weight greater than 1000 should be deleted. +.. contents:: + :local: + :depth: 1 The Deletion Process ========== When you delete rows from a SQL database, the actual deletion process occurs in two steps: -* Marking for Deletion: When you issue a ``DELETE`` statement to remove one or more rows from a table, the database marks these rows for deletion. These rows are not actually removed from the database immediately, but are instead temporarily ignored when you run any query. +* **Marking for Deletion**: When you issue a ``DELETE`` statement to remove one or more rows from a table, the database marks these rows for deletion. These rows are not actually removed from the database immediately, but are instead temporarily ignored when you run any query. :: -* Clean-up: Once the rows have been marked for deletion, you need to trigger a clean-up operation to permanently remove them from the database. During the clean-up process, the database frees up the disk space previously occupied by the deleted rows. To remove all files associated with the deleted rows, you can use the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. These commands should be run sequentially to ensure that these files removed from disk. +* **Clean-up**: Once the rows have been marked for deletion, you need to trigger a clean-up operation to permanently remove them from the database. During the clean-up process, the database frees up the disk space previously occupied by the deleted rows. To remove all files associated with the deleted rows, you can use the utility function commands ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. These commands should be run sequentially to ensure that these files removed from disk. If you want to delete all rows from a table, you can use the :ref:`TRUNCATE<truncate>` command, which deletes all rows in a table and frees up the associated disk space. Usage Notes ===================== - -.. contents:: - :local: - :depth: 1 General Notes ----------------- +------------- * The :ref:`alter_table` command and other DDL operations are locked on tables that require clean-up. If the estimated clean-up time exceeds the permitted threshold, an error message is displayed describing how to override the threshold limitation. For more information, see :ref:`concurrency_and_locks`. @@ -58,7 +50,7 @@ General Notes Clean-Up Operations Are I/O Intensive -------------------------------- +------------------------------------- The clean-up process reduces table size by removing all unused space from column chunks. While this reduces query time, it is a time-costly operation occupying disk space for the new copy of the table until the operation is complete. .. tip:: Because clean-up operations can create significant I/O load on your database, consider using them sparingly during ideal times. @@ -66,27 +58,39 @@ The clean-up process reduces table size by removing all unused space from column If this is an issue with your environment, consider using ``CREATE TABLE AS`` to create a new table and then rename and drop the old table. Examples -============= -The **Examples** section includes the following examples: +======== -.. contents:: - :local: - :depth: 1 +To follow the examples section, create the following table: + + .. code-block:: psql -Deleting Rows from a Table ------------------------------- -The following example shows how to delete rows from a table. + CREATE OR REPLACE TABLE cool_animals ( + animal_id INT, + animal_name TEXT, + animal_weight FLOAT + ); -1. Display the table: +Insert the following content: .. code-block:: psql - - farm=> SELECT * FROM cool_animals; - The following table is displayed: + INSERT INTO cool_animals (animal_id, animal_name, animal_weight) + VALUES + (1, 'Dog', 7), + (2, 'Possum', 3), + (3, 'Cat', 5), + (4, 'Elephant', 6500), + (5, 'Rhinoceros', 2100), + (6, NULL, NULL); - .. code-block:: psql +View table content: + +.. code-block:: psql + farm=> SELECT * FROM cool_animals; + + Return: + animal_id | animal_name | animal_weight ------------+------------------+-------------------- 1 | Dog | 7 @@ -96,85 +100,65 @@ The following example shows how to delete rows from a table. 5 | Rhinoceros | 2100 6 | NULL | NULL +Now you may use the following examples for: -2. Delete rows from the table: +.. contents:: + :local: + :depth: 1 + +Deleting Rows from a Table +-------------------------- - .. code-block:: psql +1. Delete rows from the table: - farm=> DELETE FROM cool_animals WHERE animal_weight > 1000; +.. code-block:: psql + + farm=> DELETE FROM cool_animals WHERE animal_weight > 1000; -3. Display the table: +2. Display the table: - .. code-block:: psql +.. code-block:: psql - farm=> SELECT * FROM cool_animals; + farm=> SELECT * FROM cool_animals; - The following table is displayed: - - .. code-block:: psql + Return - animal_id | animal_name | animal_weight - ------------+------------------+-------------------- - 1 | Dog | 7 - 2 | Possum | 3 - 3 | Cat | 5 - 6 | NULL | NULL + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 1 | Dog | 7 + 2 | Possum | 3 + 3 | Cat | 5 + 6 | NULL | NULL + Deleting Values Based on Complex Predicates --------------------------------------------------- -The following example shows how to delete values based on complex predicates. - -1. Display the table: - - .. code-block:: psql - - farm=> SELECT * FROM cool_animals; - The following table is displayed: +1. Delete rows from the table: - .. code-block:: psql - - animal_id | animal_name | animal_weight - ------------+------------------+-------------------- - 1 | Dog | 7 - 2 | Possum | 3 - 3 | Cat | 5 - 4 | Elephant | 6500 - 5 | Rhinoceros | 2100 - 6 | NULL | NULL - -2. Delete rows from the table: - - .. code-block:: psql +.. code-block:: psql - farm=> DELETE FROM cool_animals - WHERE animal_weight < 100 AND animal_name LIKE '%o%'; + farm=> DELETE FROM cool_animals + WHERE animal_weight < 100 AND animal_name LIKE '%o%'; -3. Display the table: +2. Display the table: - .. code-block:: psql +.. code-block:: psql - farm=> SELECT * FROM cool_animals; - - The following table is displayed: - - .. code-block:: psql + farm=> SELECT * FROM cool_animals; - animal_id | animal_name | animal_weight - ------------+------------------+-------------------- - 3 | Cat | 5 - 4 | Elephant | 6500 - 6 | NULL | NULL + Return + + animal_id | animal_name | animal_weight + ------------+------------------+-------------------- + 3 | Cat | 5 + 4 | Elephant | 6500 + 6 | NULL | NULL Identifying and Cleaning Up Tables --------------------------------------- - -.. contents:: - :local: - :depth: 1 Listing Tables that Have Not Been Cleaned Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: psql @@ -187,7 +171,6 @@ Listing Tables that Have Not Been Cleaned Up 1 row Identifying Predicates for Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: psql @@ -204,19 +187,33 @@ Identifying Predicates for Clean-Up Triggering a Clean-Up ^^^^^^^^^^^^^^^^^^^^^^ +When running the clean-up operation, you need to specify two parameters: ``schema_name`` and ``table_name``. However, it's important to note that the second parameter is case-sensitive for both ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. By default, both operations will accept lowercase table names. + 1. Run the ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: .. code-block:: psql - farm=> SELECT CLEANUP_CHUNKS('public','cool_animals'); + farm=> SELECT CLEANUP_CHUNKS('<schema_name>','<table_name>'); 2. Run the ``CLEANUP_EXTENTS`` command (also known as ``VACUUM``) to delete the leftover files: .. code-block:: psql - farm=> SELECT CLEANUP_EXTENTS('public','cool_animals'); + farm=> SELECT CLEANUP_EXTENTS('<schema_name>','<table_name>'); + + +If you need to run a clean-up operation for a table name that contains uppercase letters, you can use the ``false`` flag to convert the uppercase letters to lowercase, such as in the following examples: + + .. code-block:: psql + + farm=> SELECT CLEANUP_CHUNKS('<schema_name>','<table_name>', false); + + .. code-block:: psql + + farm=> SELECT CLEANUP_EXTENTS('<schema_name>','<table_name>', false); + -3. Display the table: +To display the table: .. code-block:: psql diff --git a/reference/cli/upgrade_storage.rst b/reference/cli/upgrade_storage.rst index 669d47c45..bf9e8554f 100644 --- a/reference/cli/upgrade_storage.rst +++ b/reference/cli/upgrade_storage.rst @@ -40,12 +40,12 @@ Syntax .. code-block:: console - $ upgrade_storage <storage path> [option] + $ upgrade_storage <storage path> [--check_predicates=0] .. code-block:: console - $ upgrade_storage <storage path> [--storage_version] [--check_predicates=0] + $ upgrade_storage <storage path> [--storage_version] From af77e0d930bb85e352f1095f6d905ed8b623acc4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:51:31 +0300 Subject: [PATCH 0521/1892] release --- releases/4.0_index.rst | 3 ++- releases/index.rst | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index d61a919f3..1413bd07b 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -15,4 +15,5 @@ The 4.0 Release Notes describe the following releases: 4.0 4.1 - 4.2 \ No newline at end of file + 4.2 + 4.3 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index a827d375a..abb8ab7a9 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,6 +12,8 @@ Release Notes * - Version - Release Date + * - :ref:`4.3` + - xxxxxxxxx * - :ref:`4.2` - April 23, 2023 * - :ref:`4.1` From 3f3bcd58f15c95400fe7bfd8350be1f026187ce4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Apr 2023 16:53:09 +0300 Subject: [PATCH 0522/1892] Create 4.3.rst --- releases/4.3.rst | 158 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 releases/4.3.rst diff --git a/releases/4.3.rst b/releases/4.3.rst new file mode 100644 index 000000000..08322f63a --- /dev/null +++ b/releases/4.3.rst @@ -0,0 +1,158 @@ +.. _4.3: + +************************** +Release Notes 4.3 +************************** + +SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. + +The 4.3 release notes were released on xx/xx/xxxx and describe the following: + +.. contents:: + :local: + :depth: 1 + +New Features +------------ + + +:ref:`Apache Spark<spark>` may now be used for large-scale data processing. + + :: + +:ref:`Physical deletion<delete_guide>` performance enhancement by supporting file systems with parallelism capabilities + + +Newly Released Connector Drivers +-------------------------------- + +► Pysqream 3.2.5 + * Supports Python version 3.9 and newer + * `.tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ + * :ref:`Documentation<pysqream>` + +► ODBC 4.4.4 + * :ref:`Getting the ODBC Driver<odbc>` + +► JDBC 4.5.8 + * `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ + * :ref:`Documentation<java_jdbc>` + +► Spark 5.0.0 + * `.jar file <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ + * :ref:`Documentation<spark>` + +Storage Version +--------------- + +The storage version presently in effect is version 46. + +SQream Studio Updates and Improvements +-------------------------------------- + +SQream Studio v5.5.4 has been released. + + :: + +Known Issues +------------ + +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. + +* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression + + + +Version 4.3 resolved Issues +----------------------------- + ++------------------------+------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+==========================================================================================+ +| SQ-12598 | Foreign table ``SELECT`` statement issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13018 | `cleanup_extent` operation buffer issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13055 | Pysqream ``NULL`` value issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13322 | Clean up process is case sensitive | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13450 | Storage upgrade issue | ++------------------------+------------------------------------------------------------------------------------------+ + +Configuration Changes +--------------------- + +No configuration changes + + +Naming Changes +-------------- +No naming changes + + +Deprecated Features +------------------- + +► ``INT96`` + +Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. + + +► Square Brackets ``[]`` + +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. + +* Support in ``[]`` for delimiting database object identifiers ends on June 1st, 2023. +* To delimit database object identifiers, you will be able to use double quotes ``""``. + + +► ``VARCHAR`` + +The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. + +* Support in the ``VARCHAR`` data type ends at September 30th, 2023. +* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. +* The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. + + +End of Support +--------------- +No End of Support changes were made. + +Upgrading to v4.2 +------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + + :: + +3. Copy the recently created back-up file. + + :: + +4. Replace your current metadata with the metadata you stored in the back-up file. + + :: + +5. Navigate to the new SQream package bin folder. + + :: + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 5fb20dedc788df8d9dc7781ad4772dcb55ac3ff8 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Apr 2023 13:47:56 +0300 Subject: [PATCH 0523/1892] Update delete_guide.rst --- operational_guides/delete_guide.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index dae2d02d1..abd6faf9d 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -187,22 +187,22 @@ Identifying Predicates for Clean-Up Triggering a Clean-Up ^^^^^^^^^^^^^^^^^^^^^^ -When running the clean-up operation, you need to specify two parameters: ``schema_name`` and ``table_name``. However, it's important to note that the second parameter is case-sensitive for both ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. By default, both operations will accept lowercase table names. +When running the clean-up operation, you need to specify two parameters: ``schema_name`` and ``table_name``. However, it's important to note that the second parameter is case-sensitive for both ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. -1. Run the ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: +Running a ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: .. code-block:: psql farm=> SELECT CLEANUP_CHUNKS('<schema_name>','<table_name>'); -2. Run the ``CLEANUP_EXTENTS`` command (also known as ``VACUUM``) to delete the leftover files: +Running a ``CLEANUP_EXTENTS`` command (also known as ``VACUUM``) to delete the leftover files: .. code-block:: psql farm=> SELECT CLEANUP_EXTENTS('<schema_name>','<table_name>'); -If you need to run a clean-up operation for a table name that contains uppercase letters, you can use the ``false`` flag to convert the uppercase letters to lowercase, such as in the following examples: +If you should want to run a clean-up operation without worrying about uppercase and lowercase letters, you can use the ``false`` flag to enable lowercase letters for both lowercase and uppercase table and schema names, such as in the following examples: .. code-block:: psql From b5af45ad43ce26be06950f1d059682f50af5418c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:22:22 +0300 Subject: [PATCH 0524/1892] Update delete_guide.rst --- operational_guides/delete_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index abd6faf9d..abf99a0b4 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -220,7 +220,7 @@ To display the table: farm=> SELECT delete_predicate FROM sqream_catalog.delete_predicates dp JOIN sqream_catalog.tables t ON dp.table_id = t.table_id - WHERE t.table_name = 'cool_animals'; + WHERE t.table_name = '<table_name>'; Best Practice ============= From e961c5f0414418af88d8cc4051d33c2252d39935 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 09:51:43 +0300 Subject: [PATCH 0525/1892] Update 4.3.rst --- releases/4.3.rst | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 08322f63a..86568d66e 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -16,11 +16,11 @@ New Features ------------ -:ref:`Apache Spark<spark>` may now be used for large-scale data processing. +:ref:`<>` :: -:ref:`Physical deletion<delete_guide>` performance enhancement by supporting file systems with parallelism capabilities +:ref:`<>` Newly Released Connector Drivers @@ -34,7 +34,7 @@ Newly Released Connector Drivers ► ODBC 4.4.4 * :ref:`Getting the ODBC Driver<odbc>` -► JDBC 4.5.8 +► JDBC 5.0.0 * `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ * :ref:`Documentation<java_jdbc>` @@ -69,16 +69,8 @@ Version 4.3 resolved Issues +------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +========================+==========================================================================================+ -| SQ-12598 | Foreign table ``SELECT`` statement issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13018 | `cleanup_extent` operation buffer issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13055 | Pysqream ``NULL`` value issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13322 | Clean up process is case sensitive | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13450 | Storage upgrade issue | -+------------------------+------------------------------------------------------------------------------------------+ +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++------------------------+------------------------------------------------------------------------------------------+ Configuration Changes --------------------- From 881158000928d17ffbe9951a7d2ff0e663357c23 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 10:58:37 +0300 Subject: [PATCH 0526/1892] metadata server --- reference/cli/metadata_server.rst | 34 ++++++++++++++++++++++++++++--- releases/4.3.rst | 2 +- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 716237c11..933bf1407 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -10,8 +10,36 @@ In general, you should not need to run ``metadata_server`` manually, but it is s This page serves as a reference for the options and parameters. -Positional command line arguments -=================================== +Command Line Arguments +====================== + +The ``metadata_server`` supports the following command line arguments: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Argument + - Default + - Description + * - ``--log_path`` + - ``./metadata_server_log`` + - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. + * - ``--log4_config`` + - None + - Specifies the location of the configuration file for the ``Log4cxx`` logging library. + * - ``--num_deleters`` + - 1 + - Specifies the number of threads to use for the file reaper in a system or program. + * - ``--metadata_path`` + - ``<...sqreamd/leveldb>`` + - Specifies the path to the directory where metadata files are stored for a system or program. + * - ``--help`` + - + - Used to display a help message or documentation for a particular program or command. + +Positional Command Line Arguments +--------------------------------- .. code-block:: console @@ -39,7 +67,7 @@ Starting temporarily .. code-block:: console - $ nohup metadata_server & + $ nohup metadata_server -config ~/.sqream/metadata_server_config.json & $ MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. diff --git a/releases/4.3.rst b/releases/4.3.rst index 86568d66e..e98b6868f 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -75,7 +75,7 @@ Version 4.3 resolved Issues Configuration Changes --------------------- -No configuration changes +You may now configure the ``metadata_server`` using the ``metadata_server_config.json`` :ref:`configuration file<metadata_server>`. Naming Changes From 4ba53e08851e0b759e7f4e44125d78b53c7d4693 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 11:41:35 +0300 Subject: [PATCH 0527/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 933bf1407..76caf3d13 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -35,7 +35,7 @@ The ``metadata_server`` supports the following command line arguments: - ``<...sqreamd/leveldb>`` - Specifies the path to the directory where metadata files are stored for a system or program. * - ``--help`` - - + - None - Used to display a help message or documentation for a particular program or command. Positional Command Line Arguments From aabc2c4d4e832115a70842a075ab89f699e1387a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:05:08 +0300 Subject: [PATCH 0528/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 76caf3d13..6bd58d821 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -38,26 +38,6 @@ The ``metadata_server`` supports the following command line arguments: - None - Used to display a help message or documentation for a particular program or command. -Positional Command Line Arguments ---------------------------------- - -.. code-block:: console - - $ metadata_server [ <logging path> [ <listen port> ] ] - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Argument - - Default - - Description - * - Logging path - - Current directory - - Path to store metadata logs into - * - Listen port - - ``3105`` - - TCP listen port. If used, log path must be specified beforehand. Starting metadata server ============================ @@ -83,7 +63,7 @@ To use a non-default port, specify the logging path as well. .. code-block:: console - $ nohup metadata_server /home/rhendricks/metadata_logs 9241 & + $ nohup metadata_server --log_path=/home/rhendricks/metadata_logs 9241 & $ MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. From a5b8003141d0d465979665d0e451f83b3f9a312d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 12:12:31 +0300 Subject: [PATCH 0529/1892] Update 4.3.rst --- releases/4.3.rst | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index e98b6868f..63c3d2111 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -26,21 +26,7 @@ New Features Newly Released Connector Drivers -------------------------------- -► Pysqream 3.2.5 - * Supports Python version 3.9 and newer - * `.tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ - * :ref:`Documentation<pysqream>` -► ODBC 4.4.4 - * :ref:`Getting the ODBC Driver<odbc>` - -► JDBC 5.0.0 - * `.jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.8.jar>`_ - * :ref:`Documentation<java_jdbc>` - -► Spark 5.0.0 - * `.jar file <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ - * :ref:`Documentation<spark>` Storage Version --------------- From aa9780f326a3e101867f9604b38549f34ed6d2a7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Apr 2023 14:45:43 +0300 Subject: [PATCH 0530/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 34 ++++++++++++------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 6bd58d821..d39924684 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -10,10 +10,12 @@ In general, you should not need to run ``metadata_server`` manually, but it is s This page serves as a reference for the options and parameters. -Command Line Arguments -====================== +Positional command line arguments +=================================== -The ``metadata_server`` supports the following command line arguments: +.. code-block:: console + + $ metadata_server [ <logging path> [ <listen port> ] ] .. list-table:: :widths: auto @@ -22,22 +24,12 @@ The ``metadata_server`` supports the following command line arguments: * - Argument - Default - Description - * - ``--log_path`` - - ``./metadata_server_log`` - - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. - * - ``--log4_config`` - - None - - Specifies the location of the configuration file for the ``Log4cxx`` logging library. - * - ``--num_deleters`` - - 1 - - Specifies the number of threads to use for the file reaper in a system or program. - * - ``--metadata_path`` - - ``<...sqreamd/leveldb>`` - - Specifies the path to the directory where metadata files are stored for a system or program. - * - ``--help`` - - None - - Used to display a help message or documentation for a particular program or command. - + * - Logging path + - Current directory + - Path to store metadata logs into + * - Listen port + - ``3105`` + - TCP listen port. If used, log path must be specified beforehand. Starting metadata server ============================ @@ -47,7 +39,7 @@ Starting temporarily .. code-block:: console - $ nohup metadata_server -config ~/.sqream/metadata_server_config.json & + $ nohup metadata_server & $ MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. @@ -63,7 +55,7 @@ To use a non-default port, specify the logging path as well. .. code-block:: console - $ nohup metadata_server --log_path=/home/rhendricks/metadata_logs 9241 & + nohup metadata_server --log_path=/home/rhendricks/metadata_logs --port=9241 & $ MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. From 9d74995bd16c6b569c126fa4500a9cef2eb28697 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 09:39:56 +0300 Subject: [PATCH 0531/1892] Enabling High Bin Control Granularity --- configuration_guides/copy_to_restrict_utf8.rst | 4 ++-- configuration_guides/cpu_reduce_hashtable_size.rst | 11 ----------- 2 files changed, 2 insertions(+), 13 deletions(-) delete mode 100644 configuration_guides/cpu_reduce_hashtable_size.rst diff --git a/configuration_guides/copy_to_restrict_utf8.rst b/configuration_guides/copy_to_restrict_utf8.rst index 5d5990243..869de3bea 100644 --- a/configuration_guides/copy_to_restrict_utf8.rst +++ b/configuration_guides/copy_to_restrict_utf8.rst @@ -3,10 +3,10 @@ ************************* Enabling High Bin Control Granularity ************************* -The ``copyToRestrictUtf8`` flag sets sets the custom bin size in the cache to enable high bin control granularity. +The ``copyToRestrictUtf8`` flag sets the custom bin size in the cache to enable high bin control granularity. The following describes the ``copyToRestrictUtf8`` flag: * **Data type** - boolean * **Default value** - ``false`` -* **Allowed values** - ``true``, ``false`` \ No newline at end of file +* **Allowed values** - ``true``, ``false`` diff --git a/configuration_guides/cpu_reduce_hashtable_size.rst b/configuration_guides/cpu_reduce_hashtable_size.rst deleted file mode 100644 index c2b01604c..000000000 --- a/configuration_guides/cpu_reduce_hashtable_size.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. _cpu_reduce_hashtable_size: - -************************* -Enabling High Bin Control Granularity -************************* -The ``copyToRestrictUtf8`` flag sets the custom bin size in the cache to enable high bin control granularity. - -The following describes the ``checkCudaMemory`` flag: - -* **Data type** - boolean -* **Default value** - ``FALSE`` \ No newline at end of file From c3cbd34723057d5401c0855881ac7e1576d03d97 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 10:08:31 +0300 Subject: [PATCH 0532/1892] Update trunc.rst --- .../sql_functions/scalar_functions/date_and_time/trunc.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index 1e888cfe5..e3511281f 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -1,7 +1,7 @@ .. _date_trunc: ************************** -TRUNC +Date and Time TRUNC ************************** Truncates a ``DATE`` or ``DATETIME`` value to a specified resolution. @@ -104,7 +104,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') From fca1920d0327330978f4ce68d77eecaab294d4ed Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 15:41:39 +0300 Subject: [PATCH 0533/1892] Update 4.2.rst --- releases/4.2.rst | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index 7fe2f2be3..cdf623084 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -42,10 +42,31 @@ Newly Released Connector Drivers * `.jar file <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`Documentation<spark>` -Storage Version ---------------- - -The storage version presently in effect is version 46. +System Requirements +------------------- + ++-----------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=======================+========================================================================+ +| Prerequisites version | 4.16 | ++-----------------------+------------------------------------------------------------------------+ +| OS support | * CentOS / REHL - 7.6 - 7.9 | +| | * IBM RedHat 7.6 | ++-----------------------+------------------------------------------------------------------------+ +| Nvidia driver | CUDA version 10.1 and 11.4.3 | ++-----------------------+------------------------------------------------------------------------+ +| Storage version | 46 | ++-----------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.3 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | ++-----------------------+------------------------------------------------------------------------+ + +Protocol +-------- +The client-server protocol version in this release is 8. SQream Studio Updates and Improvements -------------------------------------- @@ -63,7 +84,7 @@ Known Issues -Version 4.2 resolved Issues +Version 4.2 Resolved Issues ----------------------------- +------------------------+------------------------------------------------------------------------------------------+ From 541b91314a747f14e4c9e1debfedf8431f3ab651 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 15:42:17 +0300 Subject: [PATCH 0534/1892] Update 4.3.rst --- releases/4.3.rst | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 63c3d2111..e951cc345 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -26,12 +26,31 @@ New Features Newly Released Connector Drivers -------------------------------- - +System Requirements +------------------- -Storage Version ---------------- - -The storage version presently in effect is version 46. ++-----------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=======================+========================================================================+ +| Prerequisites version | 4.16 | ++-----------------------+------------------------------------------------------------------------+ +| OS support | * CentOS / REHL - 7.6 - 7.9 | +| | * IBM RedHat 7.6 | ++-----------------------+------------------------------------------------------------------------+ +| Nvidia driver | CUDA version 10.1 and 11.4.3 | ++-----------------------+------------------------------------------------------------------------+ +| Storage version | 46 | ++-----------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.3 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | ++-----------------------+------------------------------------------------------------------------+ + +Protocol +-------- +The client-server protocol version in this release is 8. SQream Studio Updates and Improvements -------------------------------------- From 9cae9c32e70d503fd75a6a2f009d62e566820ced Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 16:37:18 +0300 Subject: [PATCH 0535/1892] Update 4.2.rst --- releases/4.2.rst | 49 ++++++++++++++++++++++++------------------------ 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index cdf623084..d941f2076 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -42,31 +42,32 @@ Newly Released Connector Drivers * `.jar file <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`Documentation<spark>` -System Requirements -------------------- +Compatibility Matrix +-------------------- -+-----------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=======================+========================================================================+ -| Prerequisites version | 4.16 | -+-----------------------+------------------------------------------------------------------------+ -| OS support | * CentOS / REHL - 7.6 - 7.9 | -| | * IBM RedHat 7.6 | -+-----------------------+------------------------------------------------------------------------+ -| Nvidia driver | CUDA version 10.1 and 11.4.3 | -+-----------------------+------------------------------------------------------------------------+ -| Storage version | 46 | -+-----------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 4.5.3 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | -| | * Pysqream 3.2.5 | -+-----------------------+------------------------------------------------------------------------+ - -Protocol --------- -The client-server protocol version in this release is 8. ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS / REHL - 7.6 - 7.9 | +| | * IBM RedHat 7.6 | ++-------------------------+------------------------------------------------------------------------+ +| Prerequisites version | 4.16 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 46 | ++-------------------------+------------------------------------------------------------------------+ +| Connection Protocol | The client-server protocol version in this release is 8 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.8 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | +| | * Spark | ++-------------------------+------------------------------------------------------------------------+ + + SQream Studio Updates and Improvements -------------------------------------- From b457712d30fe7b4d4083985814f1dddb2aa15f4e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 May 2023 16:37:45 +0300 Subject: [PATCH 0536/1892] Update 4.3.rst --- releases/4.3.rst | 47 +++++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index e951cc345..19d032b84 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -26,31 +26,30 @@ New Features Newly Released Connector Drivers -------------------------------- -System Requirements -------------------- +Compatibility Matrix +-------------------- -+-----------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=======================+========================================================================+ -| Prerequisites version | 4.16 | -+-----------------------+------------------------------------------------------------------------+ -| OS support | * CentOS / REHL - 7.6 - 7.9 | -| | * IBM RedHat 7.6 | -+-----------------------+------------------------------------------------------------------------+ -| Nvidia driver | CUDA version 10.1 and 11.4.3 | -+-----------------------+------------------------------------------------------------------------+ -| Storage version | 46 | -+-----------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 4.5.3 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | -| | * Pysqream 3.2.5 | -+-----------------------+------------------------------------------------------------------------+ - -Protocol --------- -The client-server protocol version in this release is 8. ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS / REHL - 7.6 - 7.9 | +| | * IBM RedHat 7.6 | ++-------------------------+------------------------------------------------------------------------+ +| Prerequisites version | 4.16 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 46 | ++-------------------------+------------------------------------------------------------------------+ +| Connection Protocol | The client-server protocol version in this release is 8 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.8 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | +| | * Spark | ++-------------------------+------------------------------------------------------------------------+ SQream Studio Updates and Improvements -------------------------------------- From a41c4ce72534f425c91a6281285fb56536c8b54f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 May 2023 09:43:22 +0300 Subject: [PATCH 0537/1892] release --- releases/4.2.rst | 4 ---- releases/4.3.rst | 4 ---- 2 files changed, 8 deletions(-) diff --git a/releases/4.2.rst b/releases/4.2.rst index d941f2076..87f266740 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -51,14 +51,10 @@ Compatibility Matrix | Supported OS | * CentOS / REHL - 7.6 - 7.9 | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ -| Prerequisites version | 4.16 | -+-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 46 | +-------------------------+------------------------------------------------------------------------+ -| Connection Protocol | The client-server protocol version in this release is 8 | -+-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 4.5.8 | | | * ODBC 4.4.4 | | | * NodeJS | diff --git a/releases/4.3.rst b/releases/4.3.rst index 19d032b84..35403320c 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -35,14 +35,10 @@ Compatibility Matrix | Supported OS | * CentOS / REHL - 7.6 - 7.9 | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ -| Prerequisites version | 4.16 | -+-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 46 | +-------------------------+------------------------------------------------------------------------+ -| Connection Protocol | The client-server protocol version in this release is 8 | -+-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 4.5.8 | | | * ODBC 4.4.4 | | | * NodeJS | From 82e46f731921e326fe665893ba8c809fab7e2dc9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 09:16:13 +0300 Subject: [PATCH 0538/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index afc735ad1..5889307ff 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -51,21 +51,16 @@ The following table shows the supported data types. - 8 bytes - ``0.000003`` - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT [(n)]`` + * - ``TEXT (n)`` - Variable length string - UTF-8 unicode - - Up to ``4*n`` bytes - - ``'キウイは楽しい鳥です'`` + - Up to ``4`` bytes + - ``'Kiwis have tiny wings, but cannot fly.'`` - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR`` * - ``NUMERIC`` - 38 digits - 16 bytes - ``0.123245678901234567890123456789012345678`` - ``DECIMAL`` - * - ``TEXT (n)`` - - Variable length string - ASCII only - - ``n`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``SQL VARIANT`` * - ``DATE`` - Date - 4 bytes From c2e12b8ac57e01f4524f5376676f31880bb1553c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 10:57:11 +0300 Subject: [PATCH 0539/1892] Update index.rst --- .../sql/sql_functions/scalar_functions/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index aac74d8e2..cb749a8b6 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -8,12 +8,12 @@ The **Built-In Scalar Functions** page describes functions that return one value .. hlist:: :columns: 5 - * `AND <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/and.html>`_ - * `NOT <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/not.html>`_ - * `OR <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/or.html>`_ - * `SHIFT_LEFT <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/shift_left.html>`_ - * `SHIFT_RIGHT <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/shift_right.html>`_ - * `XOR <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/scalar_functions/bitwise/xor.html>`_ + * :ref:`bitwise_and` + * :ref:`bitwise_not` + * :ref:`bitwise_or` + * :ref:`bitwise_shift_left` + * :ref:`bitwise_shift_right` + * :ref:`bitwise_xor` * :ref:`between` * :ref:`case` * :ref:`coalesce` From e6b418aa82c746d8040f74deba3dfc15f239b1ca Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 10:57:11 +0300 Subject: [PATCH 0540/1892] Update index.rst From ec3dd3c15adc80fb9881bf79b585c003d7f59407 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 12:22:34 +0300 Subject: [PATCH 0541/1892] Tableau Connector --- .../client_drivers/jdbc/index.rst | 2 - .../client_platforms/tableau.rst | 102 +++++++----------- 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index e50648dfa..3f625759c 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -5,8 +5,6 @@ JDBC ************************* The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. -The JDBC page includes the following sections: - .. contents:: :local: :depth: 1 diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 279552c34..bd21a756a 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -4,91 +4,69 @@ Connecting to SQream Using Tableau ************************* -Overview -===================== -SQream's Tableau connector plugin, based on standard JDBC, enables storing and fast querying large volumes of data. +SQream's Tableau connector, based on standard JDBC, enables storing and fast querying large volumes of data. This connector is useful for users who want to integrate and analyze data from various sources within the Tableau platform. With the Tableau connector, users can easily connect to databases and cloud applications and perform high-speed queries on large datasets. Additionally, the connector allows for seamless integration with Tableau, enabling users to visualize their data. -The **Connecting to SQream Using Tableau** page is a Quick Start Guide that describes how install Tableau and the JDBC driver and connect to SQream for data analysis. It also describes using best practices and troubleshoot issues that may occur while installing Tableau. SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. +SQream supports both Tableau Desktop and Tableau Server on Windows, MacOS, and Linux distributions. -For more information on SQream's integration with Tableau, see `Tableau's Extension Gallery <https://extensiongallery.tableau.com/connectors?version=2019.4>`_. - -The Connecting to SQream Using Tableau page describes the following: +For more information on SQream's integration with Tableau, see `Tableau Connectors <https://extensiongallery.tableau.com/connectors?version=2019.4>`_. .. contents:: :local: :depth: 1 -Installing the JDBC Driver and Tableau Connector Plugin -------------------- -This section describes how to install the JDBC driver using the fully-integrated Tableau connector plugin (Tableau Connector, or **.taco** file). SQream has been tested with Tableau versions 9.2 and newer. - -You can connect to SQream using Tableau by doing one of the following: +Prerequisites +------------- - * **For MacOS or Linux** - See :ref:`Installing the JDBC Driver <tableau_jdbc_installer>`. - -.. _tableau_jdbc_installer: - -Installing the JDBC Driver -------------------- -If you are using MacOS, Linux, or the Tableau server, after installing the Tableau Desktop application you can install the JDBC driver manually. When the driver is installed, you can connect to SQream. +It is essential that you have the following installed: -**To install the JDBC driver:** - -1. Download the JDBC installer and SQream Tableau connector (.taco) file from the :ref:`from the client drivers page<client_drivers>`. - - :: +* :ref:`JDBC <java_jdbc>` +* Tableau version 9.2 or newer -2. Based on your operating system, your Tableau driver directory is located in one of the following places: +Installing the Tableau Connector +-------------------------------- - * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - - :: - - * **Tableau Desktop on Windows:** *C:\\Program Files\\Tableau\\Drivers* - - :: - - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - - Note the following when installing the JDBC driver: +#. Download the :ref:`Tableau Connector <client_drivers>` ``SQreamDB.taco`` file. - * You must have read permissions on the .jar file. - - :: - - * Tableau requires a JDBC 4.0 or later driver. - - :: - - * Tableau requires a Type 4 JDBC driver. + Based on your operating system, you may find the Tableau driver directory here: - :: - - * The latest 64-bit version of Java 8 is installed. - -3. Install the **SQreamDB.taco** file by moving the SQreamDB.taco file into the Tableau connectors directory. + * Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` + * Tableau Desktop on Windows: ``C:\Program Files\Tableau\Drivers`` + * Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` - Based on the installation method that you used, your Tableau driver directory is located in one of the following places: +#. Based on the installation method that you used for installing Tableau, place the Tableau Connector ``SQreamDB.taco`` file in the Tableau connector directory: - * **Tableau Desktop on Windows:** *C:\\Users\\<your user>\\My Tableau Repository\\Connectors* +.. list-table:: + :widths: auto + :header-rows: 1 - :: - - * **Tableau Desktop on MacOS:** *~/My Tableau Repository/Connectors* + * - Product / Platform + - Path + * - Tableau Desktop for Windows + - ``C:\Users[user]\Documents\My Tableau Repository\Connectors`` + * - Tableau Desktop for Mac + - ``/Users/[user]/Documents/My Tableau Repository/Connectors`` + * - Tableau Prep for Windows + - ``C:\Users[user]\Documents\My Tableau Prep Repository\Connectors`` + * - Tableau Prep for Mac + - ``/Users/[user]/Documents/My Tableau Prep Repository/Connectors`` + * - Flow web authoring on Tableau Server + - ``/data/tabsvc/flowqueryservice/Connectors`` + * - Tableau Prep Conductor on Tableau Server + - ``/data/tabsvc/flowprocessor/Connectors`` + * - Tableau Server + - ``C:\ProgramData\Tableau\Tableau Server\data\tabsvc\vizqlserver\Connectors`` -You can now restart Tableau Desktop or Server to begin using the SQream driver by connecting to SQream as described in the section below. +3. Restart Tableau Desktop or Tableau server. Connecting to SQream --------------------- -After installing the JDBC driver you can connect to SQream. -**To connect to SQream:** #. Start Tableau Desktop. :: -#. In the **Connect** menu, in the **To a Server** sub-menu, click **More...**. +#. In the **Connect** menu, click **More** in the To a Server sub-menu. More connection options are displayed. @@ -102,6 +80,8 @@ After installing the JDBC driver you can connect to SQream. #. In the New Connection dialog box, fill in the fields and click **Sign In**. + The connection is established, and the data source page is displayed. + The following table describes the fields: .. list-table:: @@ -133,10 +113,6 @@ After installing the JDBC driver you can connect to SQream. - Sets SSL as a requirement for establishing this connection. - -The connection is established and the data source page is displayed. - -.. _set_up_sqream_tables_as_data_sources: - Setting Up SQream Tables as Data Sources ---------------- After connecting to SQream you must set up the SQream tables as data sources. From ea0b065b2b7d73b832d2a3584df1e9e4cc2b73d0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 15:02:18 +0300 Subject: [PATCH 0542/1892] Update tableau.rst --- .../client_platforms/tableau.rst | 103 +++--------------- 1 file changed, 17 insertions(+), 86 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index bd21a756a..7e4e92509 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -19,19 +19,24 @@ Prerequisites It is essential that you have the following installed: -* :ref:`JDBC <java_jdbc>` * Tableau version 9.2 or newer -Installing the Tableau Connector --------------------------------- +Setting Up JDBC +---------------- -#. Download the :ref:`Tableau Connector <client_drivers>` ``SQreamDB.taco`` file. +#. Download the SQream JDBC Connector :ref:`.jar file <client_drivers>`. +#. Place the JDBC .jar file in the Tableau driver directory. - Based on your operating system, you may find the Tableau driver directory here: + Based on your operating system, you may find the Tableau driver directory in one of the following locations: * Tableau Desktop on MacOS: ``~/Library/Tableau/Drivers`` * Tableau Desktop on Windows: ``C:\Program Files\Tableau\Drivers`` * Tableau on Linux: ``/opt/tableau/tableau_driver/jdbc`` + +Installing the Tableau Connector +-------------------------------- + +#. Download the :ref:`Tableau Connector <client_drivers>` ``SQreamDB.taco`` file. #. Based on the installation method that you used for installing Tableau, place the Tableau Connector ``SQreamDB.taco`` file in the Tableau connector directory: @@ -66,29 +71,29 @@ Connecting to SQream :: -#. In the **Connect** menu, click **More** in the To a Server sub-menu. +#. In the **Connect** menu, under the **To a Server** option , click **More**. - More connection options are displayed. + Additional connection options are displayed. :: #. Select **SQream DB by SQream Technologies**. - The **New Connection** dialog box is displayed. + The connection dialog box is displayed. :: -#. In the New Connection dialog box, fill in the fields and click **Sign In**. +#. In the connection dialog box, fill in the fields and click **Sign In**. The connection is established, and the data source page is displayed. - The following table describes the fields: +Information about step 4 fields: .. list-table:: :widths: 15 38 38 :header-rows: 1 - * - Item + * - Field name - Description - Example * - Server @@ -109,83 +114,9 @@ Connecting to SQream * - Password - Specifies the password of the selected role. - ``Tr0ub4dor&3`` - * - Require SSL (recommended) + * - Require SSL - Sets SSL as a requirement for establishing this connection. - -Setting Up SQream Tables as Data Sources ----------------- -After connecting to SQream you must set up the SQream tables as data sources. - -**To set up SQream tables as data sources:** - -1. From the **Table** menu, select the desired database and schema. - - SQream's default schema is **public**. - - :: - -#. Drag the desired tables into the main area (labeled **Drag tables here**). - - This area is also used for specifying joins and data source filters. - - :: - -#. Open a new sheet to analyze data. - -Tableau Best Practices and Troubleshooting ---------------- -This section describes the following best practices and troubleshooting procedures when connecting to SQream using Tableau: - -.. contents:: - :local: - -Using Tableau's Table Query Syntax -~~~~~~~~~~~~~~~~~~~ -Dragging your desired tables into the main area in Tableau builds queries based on its own syntax. This helps ensure increased performance, while using views or custom SQL may degrade performance. In addition, SQream recommends using the :ref:`create_view` to create pre-optimized views, which your datasources point to. - -Creating a Separate Service for Tableau -~~~~~~~~~~~~~~~~~~~ -SQream recommends creating a separate service for Tableau with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. - -Troubleshooting Workbook Performance Before Deploying to the Tableau Server -~~~~~~~~~~~~~~~~~~~ -Tableau has a built-in `performance recorder <https://help.tableau.com/current/pro/desktop/en-us/perf_record_create_desktop.htm>`_ that shows how time is being spent. If you're seeing slow performance, this could be the result of a misconfiguration such as setting concurrency too low. - -Use the Tableau Performance Recorder for viewing the performance of queries run by Tableau. You can use this information to identify queries that can be optimized by using views. - -Troubleshooting Error Codes -~~~~~~~~~~~~~~~~~~~ -Tableau may be unable to locate the SQream JDBC driver. The following message is displayed when Tableau cannot locate the driver: - -.. code-block:: console - - Error Code: 37CE01A3, No suitable driver installed or the URL is incorrect - -**To troubleshoot error codes:** - -If Tableau cannot locate the SQream JDBC driver, do the following: - - 1. Verify that the JDBC driver is located in the correct directory: - - * **Tableau Desktop on Windows:** *C:\Program Files\Tableau\Drivers* - - :: - - * **Tableau Desktop on MacOS:** *~/Library/Tableau/Drivers* - - :: - - * **Tableau on Linux**: */opt/tableau/tableau_driver/jdbc* - - 2. Find the file path for the JDBC driver and add it to the Java classpath: - - * **For Linux** - ``export CLASSPATH=<absolute path of SQream DB JDBC driver>;$CLASSPATH`` - - :: - - * **For Windows** - add an environment variable for the classpath: - .. image:: /_static/images/Third_Party_Connectors/tableau/envrionment_variable_for_classpath.png -If you experience issues after restarting Tableau, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file From 0f2646b9229fdef476d0e00475fd95b8c18f8a6d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 15:04:55 +0300 Subject: [PATCH 0543/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index cc6b670c0..d32b9684b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -17,7 +17,7 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.3 (.jar) + * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.6 (.jar) * :ref:`java_jdbc` .. _.net: From 6527df050608b4dbd380be9e319e688bb9ed8fb5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 May 2023 15:07:39 +0300 Subject: [PATCH 0544/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index b8d9691fd..ace6734cf 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -95,7 +95,7 @@ The following table shows SQream's recommended hardware specifications: * - External Storage - * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high speed network card minimum 40G compatible to customer’s infrastructure - * 50 TB (NAS connected over GPFS, Lustre, or NFS) GPFS recommended + * 50 TB (NAS connected over GPFS, Lustre, Weka, or VAST) GPFS recommended * - GPU - 2x A100 NVIDIA * - Operating System @@ -126,7 +126,7 @@ The following table shows SQream's recommended metadata server specifications: * - Operating System - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux -.. note:: With a NAS connected over GPFS, Lustre, or NFS, each SQream worker can read data at up to 5GB/s. +.. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at up to 5GB/s. SQream Studio Server Example ----------------------------------- From 0328263fcb33ed501934fb61c19cab492b9d6d31 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 May 2023 10:40:30 +0300 Subject: [PATCH 0545/1892] GET TOTAL CHUNKS SIZE --- reference/sql/sql_statements/index.rst | 2 + .../get_all_roles_database_ddl.rst | 52 ++++++++++++------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 325647bda..db8241ec8 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -122,6 +122,8 @@ The following table shows the Utility commands: - View the ``CREATE TABLE`` statement for a table * - :ref:`SELECT GET_FUNCTION_DDL<get_function_ddl>` - View the ``CREATE FUNCTION`` statement for a UDF + * - :ref:`SELECT GET_TOTAL_CHUNKS_SIZE<get_total_chunks_size>` + - Shows the total size of all data chunks saved in the system in both compressed and uncompressed formats * - :ref:`SELECT GET_VIEW_DDL<get_view_ddl>` - View the ``CREATE VIEW`` statement for a view * - :ref:`SELECT RECOMPILE_VIEW<recompile_view>` diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst index 430ede73e..b6c8ad141 100644 --- a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst @@ -1,9 +1,9 @@ -.. _get_all_roles_database_ddl: +.. _get_total_chunks_size: ******************** -GET_ALL_ROLES_DATABASE_DDL +GET TOTAL CHUNKS SIZE ******************** -The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role databases in DDL format. +The ``get_total_chunks_size`` function returns the total size of all data chunks saved in the system in both compressed and uncompressed formats. .. contents:: :local: @@ -11,36 +11,52 @@ The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role Syntax ========== -The following is the correct syntax for using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: .. code-block:: postgres - select get_all_roles_database_ddl() + SELECT get_total_chunks_size(<OUTPUT_UNITS>, [DATABASE_NAME], [SCHEMA_NAME, [TABLE_NAME]]) + +Parameters +============ +The following table shows the ``SELECT get_total_chunks_size`` parameters: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Description + * - ``OUTPUT_UNITS`` + - Mandatory + - Specifies the desired unit of measurement for the output size, with valid values of ``BYTE``, ``MB``, ``GB``, ``TB``, or ``PB`` + * - ``DATABASE_NAME`` + - Optional + - Specifies the name of the database to analyze. If not specified, the function will analyze all databases in the cluster. + * - ``SCHEMA_NAME`` + - Optional + - Specifies the name of the schema to analyze. If not specified, the function will analyze all schemas in the specified database. + * - ``TABLE_NAME`` + - Optional + - Specifies the name of a specific table to analyze. If not specified, the function will analyze all tables in the specified schema. Example =========== -The following is an example of using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: .. code-block:: psql - select get_all_roles_database_ddl(); + SELECT get_total_chunks_size('MB'); Output ========== -The following is an example of the output of the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + .. code-block:: postgres - grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl, update to creator_role ; grant select, insert, delete, ddl, update on table "public"."customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."d_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."nation" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."orders" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."part" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."partsupp" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."region" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."supplier" to "sqream" ; alter default schema for "sqream" to "public"; + compression-type | value | size | + -------------------------+--------------------------------+-------+ + Compressed | 0.00036144256591796875 | MB | + Uncompressed | 0.00036144256591796875 | MB | Permissions ============= -Using the ``GET_ALL_ROLES_DATABASE_DDL`` statement requires no special permissions. - -For more information, see the following: - -* :ref:`get_all_roles_global_ddl` - - :: - -* :ref:`get_role_permissions` \ No newline at end of file From f0df1c91b19af5fd5fe1237c5dd31aa97d603a02 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 May 2023 11:35:27 +0300 Subject: [PATCH 0546/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index db8241ec8..3a682bf3c 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -103,7 +103,7 @@ The following table shows the Utility commands: .. list-table:: :widths: 10 100 :header-rows: 1 - + * - Command - Usage * - :ref:`DROP SAVED QUERY<drop_saved_query>` From 5fe95343b675764ba4dd87f20cb7f9e8092150c0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 May 2023 13:07:20 +0300 Subject: [PATCH 0547/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 3a682bf3c..e13113ae4 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -103,7 +103,7 @@ The following table shows the Utility commands: .. list-table:: :widths: 10 100 :header-rows: 1 - + * - Command - Usage * - :ref:`DROP SAVED QUERY<drop_saved_query>` From f4cf974c799750d2268349e8a70fefae38987822 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 May 2023 13:31:32 +0300 Subject: [PATCH 0548/1892] ODBC Installer --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index d32b9684b..26a6750ea 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -77,7 +77,7 @@ Windows -------------- The following are applicable to Windows: -* **ODBC installer** - SQream Drivers v2020.2.0, with Tableau customizations. Please contact your `Sqream represenative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ for this installer. +* **ODBC installer** - SQream Drivers v2020.2.0. Please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ for this installer. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows <install_odbc_windows>`. From c31eedb95ea662f6cc28f3815f0dc6a790440a60 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 9 May 2023 14:34:31 +0300 Subject: [PATCH 0549/1892] Update requirements.txt --- requirements.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/requirements.txt b/requirements.txt index 806fe2730..a4fb056dd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,9 @@ # File: docs/requirements.txt # Defining the exact version will make sure things don't break -sphinx==3.5.3 -sphinx_rtd_theme==0.5.2 +sphinx==5.3.0 +sphinx_rtd_theme==1.2.0 +urllib3<=2.0.0 +openssl-python>=0.1.1 sphinx-notfound-page -Pygments>=2.4.0 +Pygments>=2.4.0 \ No newline at end of file From 8cb2c58efd4e3033cb4bcac88493409ddb7d7d49 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 14 May 2023 14:26:28 +0300 Subject: [PATCH 0550/1892] Update index.rst --- .../client_drivers/python/index.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 7db435a3b..bd71820d8 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -137,7 +137,7 @@ Standard Connection Example import sqlalchemy as sa - engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" + engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" engine = sa.create_engine(engine_url) @@ -156,13 +156,13 @@ The following example is for using a ServerPicker: import sqlalchemy as sa - engine_url = "sqream://dor:DorBerg123$@localhost:3108/pushlive" + engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" engine = sa.create_engine(engine_url, connect_args={"clustered": True}) - res = engine.execute("create or replace table test100 (dor int);") - res = engine.execute('insert into test100 values (5), (6);') - res = engine.execute('select * from test100') + res = engine.execute("create or replace table tab1 (x int);") + res = engine.execute('insert into tab1 values (5), (6);') + res = engine.execute('select * from tab1') for item in res: print(item) @@ -176,7 +176,7 @@ The following example shows how to pull a table in Pandas. This examples uses th import sqlalchemy as sa import pandas as pd - engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" + engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" engine = sa.create_engine(engine_url) @@ -375,7 +375,7 @@ This section shows how to use the ORM to create and populate tables from Python import sqlalchemy as sa import pandas as pd - engine_url = "sqream://rhendricks:secret_passwor@localhost:5000/raviga" + engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" engine = sa.create_engine(engine_url) From b4f270feb27d900bb756c6fbe0490435c4271b52 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 May 2023 17:17:07 +0300 Subject: [PATCH 0551/1892] Update 4.3.rst --- releases/4.3.rst | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 35403320c..40f56cc37 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -70,7 +70,26 @@ Version 4.3 resolved Issues | **SQ No.** | **Description** | +========================+==========================================================================================+ | SQ-11108 | Slow ``COPY FROM`` statements using ORC files | -+------------------------+------------------------------------------------------------------------------------------+ ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13201 | | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13210 | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation failure ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13401 | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13453 | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13566 | ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number multiple query execution using Python failure ++------------------------+------------------------------------------------------------------------------------------+ +| SQ-13694 | S3 access issue ++------------------------+------------------------------------------------------------------------------------------+ + Configuration Changes --------------------- From 8a672a88c23c9d402893eba9de718e5a3c10ec34 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 May 2023 11:30:10 +0300 Subject: [PATCH 0552/1892] Parquet compression algorithm --- data_ingestion/parquet.rst | 29 ++-- operational_guides/exporting_data.rst | 15 -- operational_guides/index.rst | 1 - .../sql_statements/dml_commands/copy_to.rst | 139 +++++++++--------- 4 files changed, 77 insertions(+), 107 deletions(-) delete mode 100644 operational_guides/exporting_data.rst diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 2128cf17c..bb6bf05bb 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -3,16 +3,13 @@ ********************** Ingesting Data from a Parquet File ********************** -This guide covers ingesting data from Parquet files into SQream using :ref:`FOREIGN TABLE<foreign_tables>`, and describes the following; + +Ingesting Parquet files into SQream is generally useful when you want to store the data permanently and perform frequent queries on it. Ingesting the data can also make it easier to join with other tables in your database. However, if you wish to retain your data on external Parquet files instead of ingesting it into SQream due to it being an open-source column-oriented data storage format, you may also execute :ref:`FOREIGN TABLE<foreign_tables>` queries. .. contents:: :local: :depth: 1 - -Overview -=================== -SQream supports ingesting data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, you may want to retain your data on external Parquet files instead of ingesting it into SQream. SQream supports executing queries on external Parquet files. - + Preparing Your Parquet Files ===================== Prepare your source Parquet files according to the requirements described in the following table: @@ -155,7 +152,7 @@ Prepare your source Parquet files according to the requirements described in the - - Supported [#f4]_ -* Your statements will succeed even if your Parquet file contains an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query). If the column containing the unsupported type is referenced, an error message is displayed explaining that the type is not supported and that the column may be ommitted. For solutions to this error message, see more information in **Managing Unsupported Column Types** example in the **Example** section. +Your statements will succeed even if your Parquet file contains unsupported types, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query). If the column containing the unsupported type is referenced, an error message is displayed explaining that the type is not supported and that the column may be ommitted. For solutions to this error message, see more information in **Managing Unsupported Column Types** example in the **Example** section. .. rubric:: Footnotes @@ -169,17 +166,17 @@ Prepare your source Parquet files according to the requirements described in the Making Parquet Files Accessible to Workers ================================================================ -To give workers access to files every node must have the same view of the storage being used. +To give workers access to files, every node must have the same view of the storage being used. * For files hosted on NFS, ensure that the mount is accessible from all servers. -* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct user-id. For more information, see :ref:`hdfs` guide for more information. +* For HDFS, ensure that SQream servers have access to the HDFS name node with the correct user-id. For more information, see :ref:`hdfs` guide. -* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3` guide for more information. +* For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3` guide. Creating a Table =============================================== -Before loading data, you must build the CREATE TABLE to correspond with the file structure of the inserted table. +Before loading data, you must create a table that corresponds to the file structure of the table you wish to insert. The example in this section is based on the source nba.parquet table shown below: @@ -188,7 +185,7 @@ The example in this section is based on the source nba.parquet table shown below :widths: auto :header-rows: 1 -The following example shows the correct file structure used to create the ``CREATE EXTERNAL TABLE`` statement based on the nba.parquet table: +The following example shows the correct file structure used for creating a :ref:`FOREIGN TABLE<foreign_tables>` based on the nba.parquet table: .. code-block:: postgres @@ -215,12 +212,7 @@ The following example shows the correct file structure used to create the ``CREA .. note:: The **nba.parquet** file is stored on S3 at ``s3://sqream-demo-data/nba.parquet``. Ingesting Data into SQream -=================================== -This section describes the following: - -.. contents:: - :local: - :depth: 1 +========================== Syntax ----------- @@ -233,7 +225,6 @@ You can use the :ref:`create_table_as` statement to load the data into SQream, a Examples ---------------- -This section describes the following examples: .. contents:: :local: diff --git a/operational_guides/exporting_data.rst b/operational_guides/exporting_data.rst deleted file mode 100644 index 402887da7..000000000 --- a/operational_guides/exporting_data.rst +++ /dev/null @@ -1,15 +0,0 @@ -.. _exporting_data: - -*********************** -Exporting Data -*********************** -You can export data from SQream, which you may want to do for the following reasons: - - -* To use data in external tables. See `Working with External Data <https://docs.sqream.com/en/v2020-2/installation_guides/external_data.html>`_. -* To share data with other clients or consumers with different systems. -* To copy data into another SQream cluster. - -SQream provides the following methods for exporting data: - -* Copying data from a SQream database table or query to another file - See `COPY TO <https://docs.sqream.com/en/latest/reference/sql/sql_statements/dml_commands/copy_to.html>`_. \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 048efb06f..989d32435 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -17,7 +17,6 @@ This section summarizes the following operational guides: external_data foreign_tables delete_guide - exporting_data logging monitoring_query_performance security diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 00264f50d..e10cbb677 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -3,19 +3,19 @@ ********************** COPY TO ********************** -The **COPY TO** page includes the following sections: -.. contents:: - :local: - :depth: 1 +The ``COPY TO`` statement is used for exporting data from a SQream database table or for exporting query results to a file on the filesystem. +You may wish to export data from SQream for any of the following reasons: -Overview -========== -``COPY ... TO`` is a statement that can be used to export data from a SQream database table or query to a file on the filesystem. +* To use data in external tables. See :ref:`Working with External Data<external_data>`. +* To share data with other clients or consumers using different systems. +* To copy data into another SQream cluster. -In general, ``COPY`` moves data between filesystem files and SQream DB tables. +In general, ``COPY`` moves data between filesystem files and SQream DB tables. If you wish to copy data from a file to a table, see :ref:`COPY FROM<copy_from>`. -.. note:: To copy data from a file to a table, see :ref:`COPY FROM<copy_from>`. +.. contents:: + :local: + :depth: 1 Syntax ========== @@ -100,8 +100,7 @@ The following table shows the ``COPY_TO`` elements: - Enforces the maximum file size (bytes). Permitted values: ``true`` - creates one file of unlimited size, ``false`` - permits creating several files together limited by the ``MAX_FILE_SIZE``. When set to ``true``, the single file size is not limited by the ``MAX_FILE_SIZE`` setting. When set to ``false``, the combined file sizes cannot exceed the ``MAX_FILE_SIZE``. Default value: ``TRUE``. Usage Notes -=============== -The **Usage Notes** describes the following: +=========== .. contents:: :local: @@ -109,7 +108,6 @@ The **Usage Notes** describes the following: Supported Field Delimiters ------------------------------ -The **Supported Field Delimiters** section describes the following: .. contents:: :local: @@ -410,15 +408,40 @@ The date format in the output CSV is formatted as ISO 8601 (``2019-12-31 20:30:5 For more information on the ``datetime`` format, see :ref:`sql_data_types_date`. Examples -=========== -The **Examples** section shows the following examples: +======== .. contents:: :local: :depth: 1 -Exporting a Table to a CSV File without a HEADER Row ------------------------------------- +Exporting Data From SQream to External File Tables +-------------------------------------------------- + +Exporting Tables to Parquet Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The compression algorithm used for exporting data from SQream to Parquet files is Snappy. + +.. code-block:: psql + + COPY nba TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/nba_export.parquet'); + +Exporting Query Results to Parquet Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + COPY (select x,y from t where z=0) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); + +Exporting Tables to ORC Files +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: psql + + COPY nba TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/nba_export.orc'); + +CSV Files +^^^^^^^^^ + The following is an example of exporting a table to a CSV file without a HEADER row: .. code-block:: psql @@ -435,8 +458,6 @@ The following is an example of exporting a table to a CSV file without a HEADER Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 Amir Johnson,Boston Celtics,90,PF,29,6-9,240,\N,12000000 -Exporting a Table to a CSV with a HEADER Row ------------------------------------------ The following is an example of exporting a table to a CSV file with a HEADER row: .. code-block:: psql @@ -452,9 +473,25 @@ The following is an example of exporting a table to a CSV file with a HEADER row John Holland,Boston Celtics,30,SG,27,6-5,205,Boston University,\N R.J. Hunter,Boston Celtics,28,SG,22,6-5,185,Georgia State,1148640 Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 + +The following is an example of exporting the result of a query to a CSV file: + +.. code-block:: psql + + COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv'); + +.. code-block:: console + + $ head -n5 nba_salaries.csv + Atlanta Hawks,4860196 + Boston Celtics,4181504 + Brooklyn Nets,3501898 + Charlotte Hornets,5222728 + Chicago Bulls,5785558 + +TSV Files +^^^^^^^^^ -Exporting a Table to TSV with a HEADER Row ------------------------------------------ The following is an example of exporting a table to a TSV file with a HEADER row: .. code-block:: psql @@ -471,78 +508,36 @@ The following is an example of exporting a table to a TSV file with a HEADER row R.J. Hunter Boston Celtics 28 SG 22 6-5 185 Georgia State 1148640 Jonas Jerebko Boston Celtics 8 PF 29 6-10 231 \N 5000000 -Using Non-Printable ASCII Characters as Delimiters -------------------------------------------------------- -The following is an example of using non-printable ASCII characters as delimiters: +Exporting Data From SQream to Cloud Storage +------------------------------------------- -Non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. - -For example, ASCII character ``15``, known as "shift in", can be specified using ``E'\017'``. - -.. code-block:: psql - - COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\017'); - -.. code-block:: psql - - COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\011'); -- 011 is a tab character - -Exporting the Result of a Query to CSV File --------------------------------------------- -The following is an example of exporting the result of a query to a CSV file: - -.. code-block:: psql - - COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv'); - -.. code-block:: console - - $ head -n5 nba_salaries.csv - Atlanta Hawks,4860196 - Boston Celtics,4181504 - Brooklyn Nets,3501898 - Charlotte Hornets,5222728 - Chicago Bulls,5785558 - -Saving Files to an Authenticated S3 Bucket --------------------------------------------- The following is an example of saving files to an authenticated S3 bucket: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 's3://my_bucket/salaries/nba_export.csv', AWS_ID = 'my_aws_id', AWS_SECRET = 'my_aws_secret'); -Saving Files to an HDFS Path --------------------------------------------- The following is an example of saving files to an HDFS path: .. code-block:: psql COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = 'hdfs://pp_namenode:8020/nba_export.csv'); -Exporting a Table to a Parquet File ------------------------------- -The following is an example of exporting a table to a Parquet file: +Using Non-Printable ASCII Characters as Delimiters +-------------------------------------------------- +The following is an example of using non-printable ASCII characters as delimiters: -.. code-block:: psql - - COPY nba TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/nba_export.parquet'); +Non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. -Exporting a Query to a Parquet File --------------------------------- -The following is an example of exporting a query to a Parquet file: +For example, ASCII character ``15``, known as "shift in", can be specified using ``E'\017'``. .. code-block:: psql - - COPY (select x,y from t where z=0) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); - -Exporting a Table to an ORC File ------------------------------- -The following is an example of exporting a table to an ORC file: + + COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\017'); .. code-block:: psql - COPY nba TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/nba_export.orc'); + COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\011'); -- 011 is a tab character Permissions ============= From 435809f9b3c815dea04e785ecbeb5f27fe135c2e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 May 2023 16:38:49 +0300 Subject: [PATCH 0553/1892] Update not.rst --- reference/sql/sql_functions/scalar_functions/bitwise/not.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst index 69d81e1ce..5a0d4bb7b 100644 --- a/reference/sql/sql_functions/scalar_functions/bitwise/not.rst +++ b/reference/sql/sql_functions/scalar_functions/bitwise/not.rst @@ -15,7 +15,7 @@ Syntax expr ::= integer - + Arguments ============ From e45ad5d628a1d9904f791cbcea7ae6a3291a48df Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 May 2023 17:12:15 +0300 Subject: [PATCH 0554/1892] Update charindex.rst --- .../scalar_functions/string/charindex.rst | 72 ++++++++++--------- 1 file changed, 38 insertions(+), 34 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index 9b00084f5..c8f2e4223 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -9,14 +9,14 @@ Returns the starting position of a string inside another string. See also :ref:`patindex`, :ref:`regexp_instr`. Syntax -========== +====== -.. code-block:: postgres +.. code-block:: sql - CHARINDEX ( needle_string_expr , haystack_string_expr [ , start_location ] ) + CHARINDEX ( needle_string_expr , haystack_string_expr [ , start_location ] ) -Arguments -============ +Parameters +========== .. list-table:: :widths: auto @@ -32,45 +32,49 @@ Arguments - An integer at which the search starts. This value is optional and when not supplied, the search starts at the beggining of ``needle_string_expr`` Returns -============ - -Integer start position of a match, or 0 if no match was found. - -Notes ======= -* If the value is NULL, the result is NULL. +Integer start position of a match, or 0 if no match was found. +If one of the parameters is NULL, then the return value is NULL. Examples -=========== +======== For these examples, consider the following table and contents: -.. code-block:: postgres +.. code-block:: sql - CREATE TABLE jabberwocky(line TEXT(50)); + CREATE TABLE users ( + id INT, + username TEXT, + email TEXT, + password TEXT + ); - INSERT INTO jabberwocky VALUES - ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') - ,('All mimsy were the borogoves, '), (' And the mome raths outgrabe. ') - ,('"Beware the Jabberwock, my son! '), (' The jaws that bite, the claws that catch! ') - ,('Beware the Jubjub bird, and shun '), (' The frumious Bandersnatch!" '); + INSERT INTO users (id, username, email, password) + VALUES (1, 'john_doe', 'john.doe@example.com', 'password1'), + (2, 'jane_doe', 'jane.doe@example.com', 'password2'), + (3, 'bob_smith', 'bob.smith@example.com', 'password3'), + (4, 'susan_jones', 'susan.jones@example.com', 'password4'); Using ``CHARINDEX`` ------------------------------------------ - -.. code-block:: psql - - t=> SELECT line, CHARINDEX('the', line) FROM jabberwocky - line | charindex - ------------------------------------------------+---------- - 'Twas brillig, and the slithy toves | 20 - Did gyre and gimble in the wabe: | 30 - All mimsy were the borogoves, | 16 - And the mome raths outgrabe. | 11 - "Beware the Jabberwock, my son! | 9 - The jaws that bite, the claws that catch! | 27 - Beware the Jubjub bird, and shun | 8 - The frumious Bandersnatch!" | 0 +------------------- + +.. code-block:: sql + + SELECT CHARINDEX('john', username) FROM users; + +Output: + +.. code-block:: none + + charindex| + ---------+ + 1 | + 0 | + 0 | + 0 | + + From bc9ae0bfc28f7a8354120b362503ea828f328792 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 May 2023 11:29:59 +0300 Subject: [PATCH 0555/1892] get total chunks size --- .../get_all_roles_database_ddl.rst | 46 +++++++++++++++++++ reference/sql/sql_statements/index.rst | 6 ++- ...base_ddl.rst => get_total_chunks_size.rst} | 2 + 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst rename reference/sql/sql_statements/utility_commands/{get_all_roles_database_ddl.rst => get_total_chunks_size.rst} (95%) diff --git a/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst new file mode 100644 index 000000000..1f6b6d734 --- /dev/null +++ b/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst @@ -0,0 +1,46 @@ +.. _get_all_roles_database_ddl: + +************************** +GET_ALL_ROLES_DATABASE_DDL +************************** +The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role databases in DDL format. + +.. contents:: + :local: + :depth: 1 + +Syntax +========== +The following is the correct syntax for using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: postgres + + select get_all_roles_database_ddl() + +Example +=========== +The following is an example of using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: psql + + select get_all_roles_database_ddl(); + +Output +========== +The following is an example of the output of the ``GET_ALL_ROLES_DATABASE_DDL`` statement: + +.. code-block:: postgres + + grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl, update to creator_role ; grant select, insert, delete, ddl, update on table "public"."customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."d_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_customer" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."demo_lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."lineitem" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."nation" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."orders" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."part" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."partsupp" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."region" to "sqream" ; grant select, insert, delete, ddl, update on table "public"."supplier" to "sqream" ; alter default schema for "sqream" to "public"; + +Permissions +============= +Using the ``GET_ALL_ROLES_DATABASE_DDL`` statement requires no special permissions. + +For more information, see the following: + +* :ref:`get_all_roles_global_ddl` + + :: + +* :ref:`get_role_permissions` \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index e13113ae4..7044b3a80 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -106,6 +106,8 @@ The following table shows the Utility commands: * - Command - Usage + * - :ref:`GET TOTAL CHUNKS SIZE<get_total_chunks_size>` + - Returns the total size of all data chunks saved in the system * - :ref:`DROP SAVED QUERY<drop_saved_query>` - Drops a saved query * - :ref:`EXECUTE SAVED QUERY<execute_saved_query>` @@ -190,6 +192,8 @@ The following table shows the Access Control commands: - Creates a roles, which lets a database administrator control permissions on tables and databases * - :ref:`drop_role` - Removes roles + * - :ref:`get_all_roles_database_ddl` + - Returns the definition of all role databases in DDL format * - :ref:`get_role_permissions` - Returns all permissions granted to a role in table format * - :ref:`get_role_global_ddl` @@ -198,8 +202,6 @@ The following table shows the Access Control commands: - Returns the definition of all global roles in DDL format * - :ref:`get_role_database_ddl` - Returns the definition of a role's database in DDL format - * - :ref:`get_all_roles_database_ddl` - - Returns the definition of all role databases in DDL format * - :ref:`get_statement_permissions` - Returns a list of permissions required to run a statement or query * - :ref:`grant` diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst similarity index 95% rename from reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst rename to reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst index b6c8ad141..cd2c213f4 100644 --- a/reference/sql/sql_statements/utility_commands/get_all_roles_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst @@ -60,3 +60,5 @@ Output Permissions ============= + +Using the ``get_total_chunks_size`` command requires no special permissions. \ No newline at end of file From a8fa2eae220f536c30b5bb12360c1bf66dfb705f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 May 2023 14:02:18 +0300 Subject: [PATCH 0556/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 5889307ff..740016249 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -55,7 +55,7 @@ The following table shows the supported data types. - Variable length string - UTF-8 unicode - Up to ``4`` bytes - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING`` * - ``NUMERIC`` - 38 digits - 16 bytes From 9c49dcefd1de2b431e82e17fd8df320d17bbd2c9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 May 2023 09:33:28 +0300 Subject: [PATCH 0557/1892] docker --- sqream_studio_5.4.7/getting_started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqream_studio_5.4.7/getting_started.rst b/sqream_studio_5.4.7/getting_started.rst index 21d9348c0..03aeca142 100644 --- a/sqream_studio_5.4.7/getting_started.rst +++ b/sqream_studio_5.4.7/getting_started.rst @@ -5,7 +5,7 @@ Getting Started with SQream Acceleration Studio 5.4.7 **************************** Setting Up and Starting Studio ---------------- -Studio is included with all `dockerized installations of SQream DB <https://docs.sqream.com/en/v2020-2/guides/operations/setup/local_docker.html#installing-sqream-db-docker>`_. When starting Studio, it listens on the local machine on port 8080. +Studio is included with all :ref:`dockerized installations of SQream DB<running_sqream_in_a_docker_container>`. When starting Studio, it listens on the local machine on port 8080. Logging In to Studio --------------- From 706a54124b1758a9ceef4375a1720be858e3f529 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 May 2023 10:36:28 +0300 Subject: [PATCH 0558/1892] Update copy_to.rst --- .../sql_statements/dml_commands/copy_to.rst | 58 ++++++++++++++----- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index e10cbb677..32e462f5d 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -417,32 +417,58 @@ Examples Exporting Data From SQream to External File Tables -------------------------------------------------- -Exporting Tables to Parquet Files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Parquet +^^^^^^^ The compression algorithm used for exporting data from SQream to Parquet files is Snappy. +Exporting tables to Parquet files: + .. code-block:: psql COPY nba TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/nba_export.parquet'); -Exporting Query Results to Parquet Files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Exporting query results to Parquet files: .. code-block:: psql - COPY (select x,y from t where z=0) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); + COPY (SELECT name FROM nba WHERE salary<1148640) TO WRAPPER parquet_fdw OPTIONS (LOCATION = '/tmp/file.parquet'); + +ORC +^^^ +The compression algorithm used for exporting data from SQream to ORC files is ZLIB. -Exporting Tables to ORC Files -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Exporting tables to ORC files: .. code-block:: psql COPY nba TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/nba_export.orc'); + +Exporting query results to ORC files: + +.. code-block:: psql + + COPY (SELECT name from nba where salary<1148640) TO WRAPPER orc_fdw OPTIONS (LOCATION = '/tmp/file.orc'); + +AVRO +^^^^ +The compression algorithm used for exporting data from SQream to Parquet files is Snappy. + +Exporting tables to AVRO files: + +.. code-block:: psql + + COPY nba TO WRAPPER avro_fdw OPTIONS (LOCATION = '/tmp/nba_export.avro'); + +Exporting query results to AVRO files: + +.. code-block:: psql + + COPY (SELECT name from nba where salary<1148640) TO WRAPPER avro_fdw OPTIONS (LOCATION = '/tmp/file.avro'); -CSV Files -^^^^^^^^^ +CSV +^^^ -The following is an example of exporting a table to a CSV file without a HEADER row: +Exporting a table to a CSV file without a HEADER row: .. code-block:: psql @@ -458,7 +484,7 @@ The following is an example of exporting a table to a CSV file without a HEADER Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 Amir Johnson,Boston Celtics,90,PF,29,6-9,240,\N,12000000 -The following is an example of exporting a table to a CSV file with a HEADER row: +Exporting a table to a CSV file with a HEADER row: .. code-block:: psql @@ -474,11 +500,11 @@ The following is an example of exporting a table to a CSV file with a HEADER row R.J. Hunter,Boston Celtics,28,SG,22,6-5,185,Georgia State,1148640 Jonas Jerebko,Boston Celtics,8,PF,29,6-10,231,\N,5000000 -The following is an example of exporting the result of a query to a CSV file: +Exporting the result of a query to a CSV file: .. code-block:: psql - COPY (SELECT "Team", AVG("Salary") FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv'); + COPY (SELECT Team, AVG(Salary) FROM nba GROUP BY 1) TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv'); .. code-block:: console @@ -489,10 +515,10 @@ The following is an example of exporting the result of a query to a CSV file: Charlotte Hornets,5222728 Chicago Bulls,5785558 -TSV Files -^^^^^^^^^ +TSV +^^^ -The following is an example of exporting a table to a TSV file with a HEADER row: +Exporting a table to a TSV file with a HEADER row: .. code-block:: psql From 46ad6c468e5d19f34f2100b74882ac852372b03d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 May 2023 12:01:14 +0300 Subject: [PATCH 0559/1892] Update 4.3.rst --- releases/4.3.rst | 55 +++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 40f56cc37..c2adb44a0 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -66,29 +66,36 @@ Known Issues Version 4.3 resolved Issues ----------------------------- -+------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+==========================================================================================+ -| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13112 | ``GRANT`` query queue issue | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13201 | | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13210 | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13322 | Cleanup operation failure -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13401 | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13453 | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13566 | -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13587 | Large number multiple query execution using Python failure -+------------------------+------------------------------------------------------------------------------------------+ -| SQ-13694 | S3 access issue -+------------------------+------------------------------------------------------------------------------------------+ ++------------------------+-----------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++========================+=====================================================================================================+ +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13210 | Slow query execution time | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation failure | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13401 | JDBC causes the log summery of ``INSERT`` statements to fail | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13453 | | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13566 | | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number query execution using Python failure | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13694 | S3 endpoint access issue | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata to crash | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-13426 | Slow query execution time | ++------------------------+-----------------------------------------------------------------------------------------------------+ +| SQ-11804 | | ++------------------------+-----------------------------------------------------------------------------------------------------+ + Configuration Changes @@ -131,7 +138,7 @@ End of Support --------------- No End of Support changes were made. -Upgrading to v4.2 +Upgrading to v4.3 ------------------- 1. Generate a back-up of the metadata by running the following command: From 2681af554f92f8e7903ebf7d67fee54ff0bb2d5c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 May 2023 12:12:52 +0300 Subject: [PATCH 0560/1892] Update sql_data_types_numeric.rst --- data_type_guides/sql_data_types_numeric.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_type_guides/sql_data_types_numeric.rst b/data_type_guides/sql_data_types_numeric.rst index 8a78e19fa..8d63a82f5 100644 --- a/data_type_guides/sql_data_types_numeric.rst +++ b/data_type_guides/sql_data_types_numeric.rst @@ -5,7 +5,7 @@ Numeric ************************* The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point <floating_point>` is recommended. -The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. +The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. If no parameters are specified, Numeric defaults to ``numeric(38, 0)``. Numeric Examples ^^^^^^^^^^ @@ -14,9 +14,9 @@ The following is an example of the Numeric syntax: .. code-block:: postgres - $ create or replace table t(x numeric(20, 10), y numeric(38, 38)); - $ insert into t values(1234567890.1234567890, 0.123245678901234567890123456789012345678); - $ select x + y from t; + CREATE OR REPLACE table t(x numeric(20, 10), y numeric(38, 38)); + INSERT INTO t VALUES(1234567890.1234567890, 0.123245678901234567890123456789012345678); + SELECT x + y FROM t; The following table shows information relevant to the Numeric data type: From 6a8db6c182f8e53901e47bfe0a8532a6b465f199 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 23 May 2023 16:59:31 +0300 Subject: [PATCH 0561/1892] 4.3 RN --- external_storage_platforms/nba-t10.csv | 10 ++ external_storage_platforms/s3.rst | 79 +++++++++----- .../access_control_permissions.rst | 10 +- releases/4.3.rst | 102 ++++++------------ 4 files changed, 103 insertions(+), 98 deletions(-) create mode 100644 external_storage_platforms/nba-t10.csv diff --git a/external_storage_platforms/nba-t10.csv b/external_storage_platforms/nba-t10.csv new file mode 100644 index 000000000..c9816d654 --- /dev/null +++ b/external_storage_platforms/nba-t10.csv @@ -0,0 +1,10 @@ +Name,Team,Number,Position,Age,Height,Weight,College,Salary +Avery Bradley,Boston Celtics,0,PG,25,2-Jun,180,Texas,7730337 +Jae Crowder,Boston Celtics,99,SF,25,6-Jun,235,Marquette,6796117 +John Holland,Boston Celtics,30,SG,27,5-Jun,205,Boston University, +R.J. Hunter,Boston Celtics,28,SG,22,5-Jun,185,Georgia State,1148640 +Jonas Jerebko,Boston Celtics,8,PF,29,10-Jun,231,,5000000 +Amir Johnson,Boston Celtics,90,PF,29,9-Jun,240,,12000000 +Jordan Mickey,Boston Celtics,55,PF,21,8-Jun,235,LSU,1170960 +Kelly Olynyk,Boston Celtics,41,C,25,Jul-00,238,Gonzaga,2165160 +Terry Rozier,Boston Celtics,12,PG,22,2-Jun,190,Louisville,1824360 diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index a3111f3b9..bb0a22f27 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -5,19 +5,19 @@ Inserting Data Using Amazon S3 *********************** SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. -The **Amazon S3** describes the following topics: - .. contents:: :local: S3 Configuration -============================== +================ + +A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. + -A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_ S3 URI Format -=============== -With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. +============= +With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. The following is an example of the general S3 syntax: @@ -26,45 +26,72 @@ The following is an example of the general S3 syntax: s3://bucket_name/path Authentication -================= +============== SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples -========== -Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. +======== + +AwsEndpointOverride - Enables custom endpoint + +Example: 'https://s3.amazonaws.com' -The **Examples** section includes the following examples: +AwsObjectAccessStyle - whether to use path-style or virtual object style access - read about in AWS documentation. + +If you wish to use custom endpoint, you need to configure sqream using our legacy configuration file, and add AwsEndpointOverride - Enables custom endpoint. And you may add the AwsObjectAccessStyle flag to send request for a different access style. + + + +Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. .. contents:: :local: :depth: 1 Planning for Data Staging --------------------------------- -The examples in this section are based on a CSV file, as shown in the following table: +------------------------- +The examples in this section are based on the following table: + ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Name | Team | Number | Position | Age | Height | Weight | College | Salary | ++===============+================+========+==========+=====+========+========+===================+===========+ +| Avery Bradley | Boston Celtics | 0 | PG | 25 | 2-Jun | 180 | Texas | 7730337 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-Jun | 235 | Marquette | 6796117 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| John Holland | Boston Celtics | 30 | SG | 27 | 5-Jun | 205 | Boston University | | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| R.J. Hunter | Boston Celtics | 28 | SG | 22 | 5-Jun | 185 | Georgia State | 1148640 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 10-Jun | 231 | | 5000000 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Amir Johnson | Boston Celtics | 90 | PF | 29 | 9-Jun | 240 | | 12000000 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jordan Mickey | Boston Celtics | 55 | PF | 21 | 8-Jun | 235 | LSU | 1170960 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Kelly Olynyk | Boston Celtics | 41 | C | 25 | Jul-00 | 238 | Gonzaga | 2165160 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Terry Rozier | Boston Celtics | 12 | PG | 22 | 2-Jun | 190 | Louisville | 1824360 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -.. csv-table:: nba.csv - :file: ../nba-t10.csv - :widths: auto - :header-rows: 1 The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. Creating a Foreign Table ------------------------------ +------------------------ Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres CREATE FOREIGN TABLE nba ( - Name varchar(40), - Team varchar(40), + Name text(40), + Team text(40), Number tinyint, - Position varchar(2), + Position text(2), Age tinyint, - Height varchar(4), + Height text(4), Weight real, - College varchar(40), + College text(40), Salary float ) WRAPPER csv_fdw @@ -79,11 +106,11 @@ In the example above the file format is CSV, and it is stored as an S3 object. I For more information, see the following: -* **Creating a foreign table** - see :ref:`create a foreign table<create_foreign_table>`. -* **Using SQream in an HDFS environment** - see :ref:`hdfs`. +* :ref:`create a foreign table<create_foreign_table>` +* :ref:`hdfs` Querying Foreign Tables ------------------------------- +----------------------- The following shows the data in the foreign table: .. code-block:: psql @@ -103,7 +130,7 @@ The following shows the data in the foreign table: Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 Bulk Loading a File from a Public S3 Bucket ----------------------------------------------- +------------------------------------------- The ``COPY FROM`` command can also be used to load data without staging it first. .. note:: The bucket must be publicly available and objects can be listed. diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index e0a3efa24..e03e9198d 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -25,7 +25,7 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create schemas in the database | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE FUNCTION``| Create and drop functions | +| ``CREATE FUNCTION``| Create and drop functions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Schema** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -35,13 +35,13 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Object/Layer: Table** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | :ref:`select` from the table | +| ``SELECT`` | :ref:`select` from the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``INSERT`` | :ref:`insert` into the table | +| ``INSERT`` | :ref:`insert` into the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | +| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Drop and alter on the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ diff --git a/releases/4.3.rst b/releases/4.3.rst index c2adb44a0..62571e42c 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -1,8 +1,8 @@ .. _4.3: -************************** +***************** Release Notes 4.3 -************************** +***************** SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. @@ -12,20 +12,6 @@ The 4.3 release notes were released on xx/xx/xxxx and describe the following: :local: :depth: 1 -New Features ------------- - - -:ref:`<>` - - :: - -:ref:`<>` - - -Newly Released Connector Drivers --------------------------------- - Compatibility Matrix -------------------- @@ -46,13 +32,6 @@ Compatibility Matrix | | * Pysqream 3.2.5 | | | * Spark | +-------------------------+------------------------------------------------------------------------+ - -SQream Studio Updates and Improvements --------------------------------------- - -SQream Studio v5.5.4 has been released. - - :: Known Issues ------------ @@ -62,41 +41,40 @@ Known Issues * Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression - Version 4.3 resolved Issues ------------------------------ - -+------------------------+-----------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+========================+=====================================================================================================+ -| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13112 | ``GRANT`` query queue issue | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13210 | Slow query execution time | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13322 | Cleanup operation failure | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13401 | JDBC causes the log summery of ``INSERT`` statements to fail | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13453 | | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13566 | | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13587 | Large number query execution using Python failure | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13694 | S3 endpoint access issue | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13467 | Snapshot issue causes metadata to crash | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-13426 | Slow query execution time | -+------------------------+-----------------------------------------------------------------------------------------------------+ -| SQ-11804 | | -+------------------------+-----------------------------------------------------------------------------------------------------+ - - +--------------------------- + ++--------------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+================================================================================================+ +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13210, SQ-13426 | Slow query execution time | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation case-sensitivity issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13453 | Metadata performance issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number of worker connections failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-11804 | Slow metadata optimization | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12799 | Catalog queries may not be terminated | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | ++--------------------+------------------------------------------------------------------------------------------------+ Configuration Changes --------------------- @@ -104,11 +82,6 @@ Configuration Changes You may now configure the ``metadata_server`` using the ``metadata_server_config.json`` :ref:`configuration file<metadata_server>`. -Naming Changes --------------- -No naming changes - - Deprecated Features ------------------- @@ -133,11 +106,6 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t * ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. - -End of Support ---------------- -No End of Support changes were made. - Upgrading to v4.3 ------------------- 1. Generate a back-up of the metadata by running the following command: From d3fb180f80ce82610edb5cd0ad0d93c302ffef37 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 May 2023 08:55:12 +0300 Subject: [PATCH 0562/1892] Delete running_sqream_in_a_docker_container.rst --- .../running_sqream_in_a_docker_container.rst | 1469 ----------------- 1 file changed, 1469 deletions(-) delete mode 100644 installation_guides/running_sqream_in_a_docker_container.rst diff --git a/installation_guides/running_sqream_in_a_docker_container.rst b/installation_guides/running_sqream_in_a_docker_container.rst deleted file mode 100644 index 97fc76476..000000000 --- a/installation_guides/running_sqream_in_a_docker_container.rst +++ /dev/null @@ -1,1469 +0,0 @@ -.. _running_sqream_in_a_docker_container: - -*********************** -Installing and Running SQream in a Docker Container -*********************** -The **Installing and Running SQream in a Docker Container** page describes how to prepare your machine's environment for installing and running SQream in a Docker container. - -This page describes the following: - -.. contents:: - :local: - :depth: 1 - -Setting Up a Host -==================================== - -Operating System Requirements ------------------------------------- -SQream was tested and verified on the following versions of Linux: - - * x86 CentOS/RHEL 7.6 - 7.9 - * IBM RHEL 7.6 - -SQream recommends installing a clean OS on the host to avoid any installation issues. - -.. warning:: Docker-based installation supports only single host deployment and cannot be used on a multi-node cluster. Installing Docker on a single host you will not be able to scale it to a multi-node cluster. - - -Creating a Local User ----------------- -To run SQream in a Docker container you must create a local user. - -**To create a local user:** - -1. Add a local user: - - .. code-block:: - - $ useradd -m -U <local user name> - -2. Set the local user's password: - - .. code-block:: - - $ passwd <local user name> - -3. Add the local user to the ``wheel`` group: - - .. code-block:: - - $ usermod -aG wheel <local user name> - - You can remove the local user from the ``wheel`` group when you have completed the installation. - -4. Log out and log back in as the local user. - -Setting a Local Language ----------------- -After creating a local user you must set a local language. - -**To set a local language:** - -1. Set the local language: - - .. code-block:: - - $ sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: - - $ sudo timedatectl set-timezone Asia/Jerusalem - -You can run the ``timedatectl list-timezones`` command to see your timezone. - -Adding the EPEL Repository ----------------- -After setting a local language you must add the EPEL repository. - -**To add the EPEL repository:** - -1. As a root user, upgrade the **epel-release-latest-7.noarch.rpm** repository: - - 1. RedHat (RHEL 7): - - .. code-block:: - - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - 2. CentOS 7 - - .. code-block:: - - $ sudo yum install epel-release - -Installing the Required NTP Packages ----------------- -After adding the EPEL repository, you must install the required NTP packages. - -You can install the required NTP packages by running the following command: - -.. code-block:: - - $ sudo yum install ntp pciutils python36 kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc - -Installing the Recommended Tools ----------------- -After installin gthe required NTP packages you must install the recommended tools. - -SQream recommends installing the following recommended tools: - -.. code-block:: - - $ sudo yum install bash-completion.noarch vim-enhanced.x86_64 vim-common.x86_64 net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - -Updating to the Current Version of the Operating System ----------------- -After installing the recommended tools you must update to the current version of the operating system. - -SQream recommends updating to the current version of the operating system. This is not recommended if the nvidia driver has **not been installed.** - - - -Configuring the NTP Package ----------------- -After updating to the current version of the operating system you must configure the NTP package. - -**To configure the NTP package:** - -1. Add your local servers to the NTP configuration. - - :: - -2. Configure the **ntpd** service to begin running when your machine is started: - - .. code-block:: - - $ sudo systemctl enable ntpd - $ sudo systemctl start ntpd - $ sudo ntpq -p - -Configuring the Performance Profile ----------------- -After configuring the NTP package you must configure the performance profile. - -**To configure the performance profile:** - -1. *Optional* - Switch the active profile: - - .. code-block:: - - $ sudo tuned-adm profile throughput-performance - -2. Change the multi-user's default run level: - - .. code-block:: - - $ sudo systemctl set-default multi-user.target - -Configuring Your Security Limits ----------------- -After configuring the performance profile you must configure your security limits. Configuring your security limits refers to configuring the number of open files, processes, etc. - -**To configure your security limits:** - -1. Run the **bash** shell as a super-user: - - .. code-block:: - - $ sudo bash - -2. Run the following command: - - .. code-block:: - - $ echo -e "sqream soft nproc 500000\nsqream hard nproc 500000\nsqream soft nofile 500000\nsqream hard nofile 500000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -3. Run the following command: - - .. code-block:: - - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.zone_reclaim_mode = 0 \n vm.vfs_cache_pressure = 200 \n" >> /etc/sysctl.conf - -Disabling Automatic Bug-Reporting Tools ----------------- -After configuring your security limits you must disable the following automatic bug-reporting tools: - -* ccpp.service -* oops.service -* pstoreoops.service -* vmcore.service -* xorg.service - -You can abort the above but-reporting tools by running the following command: - -.. code-block:: - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - -Installing the Nvidia CUDA Driver -------------------------------------- - -1. Verify that the Tesla NVIDIA card has been installed and is detected by the system: - - .. code-block:: - - $ lspci | grep -i nvidia - - The correct output is a list of Nvidia graphic cards. If you do not receive this output, verify that an NVIDIA GPU card has been installed. - -#. Verify that the open-source upstream Nvidia driver is running: - - .. code-block:: - - $ lsmod | grep nouveau - - No output should be generated. - -#. If you receive any output, do the following: - - 1. Disable the open-source upstream Nvidia driver: - - .. code-block:: - - $ sudo bash - $ echo "blacklist nouveau" > /etc/modprobe.d/blacklist-nouveau.conf - $ echo "options nouveau modeset=0" >> /etc/modprobe.d/blacklist-nouveau.conf - $ dracut --force - $ modprobe --showconfig | grep nouveau - - 2. Reboot the server and verify that the Nouveau model has not been loaded: - - .. code-block:: - - $ lsmod | grep nouveau - -#. Check if the Nvidia CUDA driver has already been installed: - - .. code-block:: - - $ nvidia-smi - - The following is an example of the correct output: - - .. code-block:: - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the installed CUDA version shown in the output above is ``10.1``. - - :: - - -#. Do one of the following: - - :: - - 1. If CUDA version 10.1 has already been installed, skip to Docktime Runtime (Community Edition). - :: - - 2. If CUDA version 10.1 has not been installed yet, continue with Step 7 below. - -#. Do one of the following: - - * Install :ref:`CUDA Driver version 10.1 for x86_64 <CUDA_10.1_x8664>`. - - :: - - * Install :ref:`CUDA driver version 10.1 for IBM Power9 <CUDA_10.1_IBMPower9>`. - -.. _CUDA_10.1_x8664: - -Installing the CUDA Driver Version 10.1 for x86_64 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for x86_64:** - -1. Make the following target platform selections: - - :: - - * **Operating system**: Linux - * **Architecture**: x86_64 - * **Distribution**: CentOS - * **Version**: 7 - * **Installer type**: the relevant installer type - -For installer type, SQream recommends selecting **runfile (local)**. The available selections shows only the supported platforms. - -2. Download the base installer for Linux CentOS 7 x86_64: - - .. code-block:: - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - -3. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: - - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - -4. Follow the command line prompts. - - - :: - - -5. Enable the Nvidia service to start at boot and start it: - - .. code-block:: - - $ sudo systemctl enable nvidia-persistenced.service && sudo systemctl start nvidia-persistenced.service - -7. Reboot the server. - - :: -8. Verify that the Nvidia driver has been installed and shows all available GPU's: - - .. code-block:: - - $ nvidia-smi - - The following is the correct output: - - .. code-block:: - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -.. _CUDA_10.1_IBMPower9: - -Installing the CUDA Driver Version 10.1 for IBM Power9 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the CUDA driver version 10.1 for IBM Power9:** - -1. Download the base installer for Linux CentOS 7 PPC64le: - - .. code-block:: - - wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - - -#. Install the base installer for Linux CentOS 7 x86_64 by running the following commands: - - .. code-block:: - - $ sudo rpm -i cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - $ sudo yum clean all - $ sudo yum install nvidia-driver-latest-dkms - -.. warning:: Verify that the output indicates that driver **418.87** will be installed. - - - -3. Copy the file to the **/etc/udev/rules.d** directory. - - :: - -4. If you are using RHEL 7 version (7.6 or later), comment out, remove, or change the hot-pluggable memory rule located in file copied to the **/etc/udev/rules.d** directory by running the following command: - - .. code-block:: - - $ sudo cp /lib/udev/rules.d/40-redhat.rules /etc/udev/rules.d - $ sudo sed -i 's/SUBSYSTEM!="memory",.*GOTO="memory_hotplug_end"/SUBSYSTEM=="*", GOTO="memory_hotplug_end"/' /etc/udev/rules.d/40-redhat.rules - -#. Enable the **nvidia-persisted.service** file: - - .. code-block:: - - $ sudo systemctl enable nvidia-persistenced.service - -#. Reboot your system to initialize the above modifications. - - :: - -#. Verify that the Nvidia driver and the **nvidia-persistenced.service** files are running: - - .. code-block:: - - $ nvidia smi - - The following is the correct output: - - .. code-block:: - - nvidia-smi - Wed Oct 30 14:05:42 2019 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 418.87.00 Driver Version: 418.87.00 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - |===============================+======================+======================| - | 0 Tesla V100-SXM2... On | 00000004:04:00.0 Off | 0 | - | N/A 32C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - | 1 Tesla V100-SXM2... On | 00000035:03:00.0 Off | 0 | - | N/A 33C P0 37W / 300W | 0MiB / 16130MiB | 0% Default | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -#. Verify that the **nvidia-persistenced** service is running: - - .. code-block:: - - $ systemctl status nvidia-persistenced - - The following is the correct output: - - .. code-block:: - - root@gpudb ~]systemctl status nvidia-persistenced - nvidia-persistenced.service - NVIDIA Persistence Daemon - Loaded: loaded (/usr/lib/systemd/system/nvidia-persistenced.service; enabled; vendor preset: disabled) - Active: active (running) since Tue 2019-10-15 21:43:19 KST; 11min ago - Process: 8257 ExecStart=/usr/bin/nvidia-persistenced --verbose (code=exited, status=0/SUCCESS) - Main PID: 8265 (nvidia-persiste) - Tasks: 1 - Memory: 21.0M - CGroup: /system.slice/nvidia-persistenced.service - └─8265 /usr/bin/nvidia-persistenced --verbose - -Installing the Docker Engine (Community Edition) -======================= -After installing the Nvidia CUDA driver you must install the Docker engine. - -This section describes how to install the Docker engine using the following processors: - -* :ref:`Using x86_64 processor on CentOS <dockerx8664centos>` -* :ref:`Using x86_64 processor on Ubuntu <dockerx8664ubuntu>` -* :ref:`Using IBM Power9 (PPC64le) processor <docker_ibmpower9>` - - -.. _dockerx8664centos: - -Installing the Docker Engine Using an x86_64 Processor on CentOS ---------------------------------- -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on CentOS <https://docs.docker.com/engine/install/centos/>`_ - - - -.. _dockerx8664ubuntu: - -Installing the Docker Engine Using an x86_64 Processor on Ubuntu ------------------------------------------------------ - - -The x86_64 processor supports installing the **Docker Community Edition (CE)** versions 18.03 and higher. - -For more information on installing the Docker Engine CE on an x86_64 processor, see `Install Docker Engine on Ubuntu <https://docs.docker.com/install/linux/docker-ce/ubuntu/>`_ - -.. _docker_ibmpower9: - -Installing the Docker Engine on an IBM Power9 Processor ----------------------------------------- -The x86_64 processor only supports installing the **Docker Community Edition (CE)** version 18.03. - -**To install the Docker Engine on an IBM Power9 processor:** - -You can install the Docker Engine on an IBM Power9 processor by running the following command: - -.. code-block:: - - wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/container-selinux-2.9-4.el7.noarch.rpm - wget http://ftp.unicamp.br/pub/ppc64el/rhel/7_1/docker-ppc64el/docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - yum install -y container-selinux-2.9-4.el7.noarch.rpm docker-ce-18.03.1.ce-1.el7.centos.ppc64le.rpm - -For more information on installing the Docker Engine CE on an IBM Power9 processor, see `Install Docker Engine on Ubuntu <https://developer.ibm.com/components/ibm-power/tutorials/install-docker-on-linux-on-power/>`_. - -Docker Post-Installation -================================= -After installing the Docker engine you must configure Docker on your local machine. - -**To configure Docker on your local machine:** - -1. Enable Docker to start on boot: - - .. code-block:: - - $ sudo systemctl enable docker && sudo systemctl start docker - -2. Enable managing Docker as a non-root user: - - .. code-block:: - - $ sudo usermod -aG docker $USER - -3. Log out and log back in via SSH. This causes Docker to re-evaluate your group membership. - - :: - -4. Verify that you can run the following Docker command as a non-root user (without ``sudo``): - - .. code-block:: - - $ docker run hello-world - -If you can run the above Docker command as a non-root user, the following occur: - -* Docker downloads a test image and runs it in a container. -* When the container runs, it prints an informational message and exits. - -For more information on installing the Docker Post-Installation, see `Docker Post-Installation <https://docs.docker.com/install/linux/linux-postinstall/>`_. - -Installing the Nvidia Docker2 ToolKit -========================================== -After configuring Docker on your local machine you must install the Nvidia Docker2 ToolKit. The NVIDIA Docker2 Toolkit lets you build and run GPU-accelerated Docker containers. The Toolkit includes a container runtime library and related utilities for automatically configuring containers to leverage NVIDIA GPU's. - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an x86_64 processor <install_nvidia_docker2_toolkit_x8664_processor>` -* :ref:`Installing the NVIDIA Docker2 Toolkit on a PPC64le processor <install_nvidia_docker2_toolkit_ppc64le_processor>` - -.. _install_nvidia_docker2_toolkit_x8664_processor: - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Processor ----------------------------------------- - -This section describes the following: - -* :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system <install_nvidia_docker2_toolkit_centos>` - -* :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system <install_nvidia_docker2_toolkit_ubuntu>` - -.. _install_nvidia_docker2_toolkit_centos: - -Installing the NVIDIA Docker2 Toolkit on a CentOS Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on a CentOS operating system:** - -1. Install the repository for your distribution: - - .. code-block:: - - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - sudo tee /etc/yum.repos.d/nvidia-docker.repo - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: - - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Do one of the following: - - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 <step_4_centos>`. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 <step_5_centos>`. - -.. _step_4_centos: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - - .. code-block:: - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_centos: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on a CentOS operating system <https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)#centos-distributions-1>` - - -.. _install_nvidia_docker2_toolkit_ubuntu: - -Installing the NVIDIA Docker2 Toolkit on an Ubuntu Operating System -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the NVIDIA Docker2 Toolkit on an Ubuntu operating system:** - -1. Install the repository for your distribution: - - .. code-block:: - - curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add - - distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list - sudo apt-get update - -2. Install the ``nvidia-docker2`` package and reload the Docker daemon configuration: - - .. code-block:: - - $ sudo apt-get install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Do one of the following: - - * If you received an error when installing the ``nvidia-docker2`` package, skip to :ref:`Step 4 <step_4_ubuntu>`. - * If you successfully installed the ``nvidia-docker2`` package, skip to :ref:`Step 5 <step_5_ubuntu>`. - - .. _step_4_ubuntu: - -4. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the ``nvidia-docker2`` package: - - .. code-block:: - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - -.. _step_5_ubuntu: - -5. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on a CentOS operating system, see :ref:`Installing the NVIDIA Docker2 Toolkit on an Ubuntu operating system <https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)#ubuntu-distributions-1>` - -.. _install_nvidia_docker2_toolkit_ppc64le_processor: - -Installing the NVIDIA Docker2 Toolkit on a PPC64le Processor --------------------------------------- - -This section describes how to install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system: - -**To install the NVIDIA Docker2 Toolkit on an IBM RHEL operating system:** - -1. Import the repository and install the ``libnvidia-container`` and the ``nvidia-container-runtime`` containers. - - .. code-block:: - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - sudo tee /etc/yum.repos.d/nvidia-docker.repo - $ sudo yum install -y libnvidia-container* - -2. Do one of the following: - - * If you received an error when installing the containers, skip to :ref:`Step 3 <step_3_installing_nvidia_docker2_toolkit_ppc64le_processor>`. - * If you successfully installed the containers, skip to :ref:`Step 4 <step_4_installing_nvidia_docker2_toolkit_ppc64le_processor>`. - -.. _step_3_installing_nvidia_docker2_toolkit_ppc64le_processor: - -3. Do the following: - - 1. Run the ``sudo vi /etc/yum.repos.d/nvidia-docker.repo`` command if the following error is displayed when installing the containers: - - .. code-block:: - - https://nvidia.github.io/nvidia-docker/centos7/ppc64le/repodata/repomd.xml: - [Errno -1] repomd.xml signature could not be verified for nvidia-docker - - 2. Change ``repo_gpgcheck=1`` to ``repo_gpgcheck=0``. - - :: - - 3. Install the ``libnvidia-container`` container. - - .. code-block:: - - $ sudo yum install -y libnvidia-container* - - .. _step_4_installing_nvidia_docker2_toolkit_ppc64le_processor: - -4. Install the ``nvidia-container-runtime`` container: - - .. code-block:: - - $ sudo yum install -y nvidia-container-runtime* - -5. Add ``nvidia runtime`` to the Docker daemon: - - .. code-block:: - - $ sudo mkdir -p /etc/systemd/system/docker.service.d/ - $ sudo vi /etc/systemd/system/docker.service.d/override.conf - - $ [Service] - $ ExecStart= - $ ExecStart=/usr/bin/dockerd - -6. Restart Docker: - - .. code-block:: - - $ sudo systemctl daemon-reload - $ sudo systemctl restart docker - -7. Verify that the NVIDIA-Docker run has been installed correctly: - - .. code-block:: - - $ docker run --runtime=nvidia --rm nvidia/cuda-ppc64le nvidia-smi - -.. _accessing_hadoop_kubernetes_configuration_files: - -Accessing the Hadoop and Kubernetes Configuration Files --------------------------------------- -The information this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, contact your IT department for access to the following configuration files: - -* Hadoop configuration files: - - * core-site.xml - * hdfs-site.xml - - :: - -* Kubernetes files: - - * Configuration file - krb.conf - * Kubernetes Hadoop client certificate - hdfs.keytab - -Once you have the above files, you must copy them into the correct folders in your working directory. - -For more information about the correct directory to copy the above files into, see the :ref:`Installing the SQream Software <installing_sqream_software>` section below. - -For related information, see the following sections: - -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files <configure_hadoop_kubernetes_configuration_files>` -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters <setting_hadoop_kubernetes_connectivity_parameters>` - -.. _installing_sqream_software: - -Installing the SQream Software -============================== - -Preparing Your Local Environment -------------------------- -After installing the Nvidia Docker2 toolKit you must prepare your local environment. - -.. note:: You must install the SQream software under a *sqream* and not a *root* user. - -The Linux user preparing the local environment must have **read/write** access to the following directories for the SQream software to correctly read and write the required resources: - -* **Log directory** - default: /var/log/sqream/ -* **Configuration directory** - default: /etc/sqream/ -* **Cluster directory** - the location where SQream writes its DB system, such as */mnt/sqreamdb* -* **Ingest directory** - the location where the required data is loaded, such as */mnt/data_source/* - -.. _download_sqream_software: - -Deploying the SQream Software -------------------------- -After preparing your local environment you must deploy the SQream software. Deploying the SQream software requires you to access and extract the required files and to place them in the correct directory. - -**To deploy the SQream software:** - -1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for access to the **sqream_installer-nnn-DBnnn-COnnn-EDnnn-<arch>.tar.gz** file. - -The **sqream_installer-nnn-DBnnn-COnnn-EDnnn-<arch>.tar.gz** file includes the following parameter values: - -* **sqream_installer-nnn** - sqream installer version -* **DBnnn** - SQreamDB version -* **COnnn** - SQream console version -* **EDnnn** - SQream editor version -* **arch** - server arch (applicable to X86.64 and ppc64le) - -2. Extract the tarball file: - - .. code-block:: - - $ tar -xvf sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - - When the tarball file has been extracted, a new folder will be created. The new folder is automatically given the name of the tarball file: - - .. code-block:: - - drwxrwxr-x 9 sqream sqream 4096 Aug 11 11:51 sqream_istaller-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64/ - -rw-rw-r-- 1 sqream sqream 3130398797 Aug 11 11:20 sqream_installer-1.1.5-DB2019.2.1-CO1.5.4-ED3.0.0-x86_64.tar.gz - -3. Change the directory to the new folder that you created in the previous step. - -:: - -4. Verify that the folder you just created contains all of the required files. - - .. code-block:: - - $ ls -la - - The following is an example of the files included in the new folder: - - .. code-block:: - - drwxrwxr-x. 10 sqream sqream 198 Jun 3 17:57 . - drwx------. 25 sqream sqream 4096 Jun 7 18:11 .. - drwxrwxr-x. 2 sqream sqream 226 Jun 7 18:09 .docker - drwxrwxr-x. 2 sqream sqream 64 Jun 3 12:55 .hadoop - drwxrwxr-x. 2 sqream sqream 4096 May 31 14:18 .install - drwxrwxr-x. 2 sqream sqream 39 Jun 3 12:53 .krb5 - drwxrwxr-x. 2 sqream sqream 22 May 31 14:18 license - drwxrwxr-x. 2 sqream sqream 82 May 31 14:18 .sqream - -rwxrwxr-x. 1 sqream sqream 1712 May 31 14:18 sqream-console - -rwxrwxr-x. 1 sqream sqream 4608 May 31 14:18 sqream-install - -For information relevant to Hadoop users, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files <accessing_hadoop_kubernetes_configuration_files>`. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files <configure_hadoop_kubernetes_configuration_files>`. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters <setting_hadoop_kubernetes_connectivity_parameters>`. - -.. _configure_hadoop_kubernetes_configuration_files: - -Configuring the Hadoop and Kubernetes Configuration Files ------------------------------ -The information in this section is optional and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must copy the Hadoop and Kubernetes files into the correct folders in your working directory as shown below: - -* .hadoop/core-site.xml -* .hadoop/hdfs-site.xml -* .krb5/krb5.conf -* .krb5/hdfs.keytab - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files <accessing_hadoop_kubernetes_configuration_files>`. -* :ref:`Setting the Hadoop and Kubernetes Configuration Parameters <setting_hadoop_kubernetes_connectivity_parameters>`. - -Configuring the SQream Software -------------------------------- -After deploying the SQream software, and optionally configuring the Hadoop and Kubernetes configuration files, you must configure the SQream software. - -Configuring the SQream software requires you to do the following: - -* Configure your local environment -* Understand the ``sqream-install`` flags -* Install your SQream license -* Validate your SQream icense -* Change your data ingest folder - -Configuring Your Local Environment -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've downloaded the SQream software, you can begin configuring your local environment. The following commands must be run (as **sudo**) from the same directory that you located your packages. - -For example, you may have saved your packages in **/home/sqream/sqream-console-package/**. - -The following table shows the flags that you can use to configure your local directory: - -.. list-table:: - :widths: 10 50 40 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-i** - - Loads all software from the hidden folder **.docker**. - - Mandatory - * - **-k** - - Loads all license packages from the **/license** directory. - - Mandatory - * - **-f** - - Overwrites existing folders. **Note** Using ``-f`` overwrites **all files** located in mounted directories. - - Mandatory - * - **-c** - - Defines the origin path for writing/reading SQream configuration files. The default location is ``/etc/sqream/``. - - If you are installing the Docker version on a server that already works with SQream, do not use the default path. - * - **-v** - - The SQream cluster location. If a cluster does not exist yet, ``-v`` creates one. If a cluster already exists, ``-v`` mounts it. - - Mandatory - * - **-l** - - SQream system startup logs location, including startup logs and docker logs. The default location is ``/var/log/sqream/``. - - - * - **-d** - - The directory containing customer data to be imported and/or copied to SQream. - - - * - **-s** - - Shows system settings. - - - * - **-r** - - Resets the system configuration. This value is run without any other variables. - - Mandatory - * - **-h** - - Help. Shows the available flags. - - Mandatory - * - **-K** - - Runs license validation - - - * - **-e** - - Used for inserting your RKrb5 server DNS name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters <setting_hadoop_kubernetes_connectivity_parameters>`. - - - * - **-p** - - Used for inserting your Kerberos user name. For more information on setting your Kerberos configuration parameters, see :ref:`Setting the Hadoop and Kubernetes Configuration Parameters <setting_hadoop_kubernetes_connectivity_parameters>`. - - - - -Installing Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your local environment, you must install your license by copying it into the SQream installation package folder located in the **./license** folder: - -.. code-block:: - - $ sudo ./sqream-install -k - -You do not need to extract this folder after uploading into the **./license**. - - -Validating Your License -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You can copy your license package into the SQream console folder located in the **/license** folder by running the following command: - -.. code-block:: - - $ sudo ./sqream-install -K - -The following mandatory flags must be used in the first run: - -.. code-block:: - - $ sudo ./sqream-install -i -k -v <volume path> - -The following is an example of the correct command syntax: - -.. code-block:: - - $ sudo ./sqream-install -i -k -c /etc/sqream -v /home/sqream/sqreamdb -l /var/log/sqream -d /home/sqream/data_ingest - -.. _setting_hadoop_kubernetes_connectivity_parameters: - -Setting the Hadoop and Kubernetes Connectivity Parameters -------------------------------- -The information in this section is optional, and is only relevant for Hadoop users. If you require Hadoop and Kubernetes (Krb5) connectivity, you must set their connectivity parameters. - -The following is the correct syntax when setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: - - $ sudo ./sqream-install -p <Kerberos user name> -e <Kerberos server DNS name>:<Kerberos server IP> - -The following is an example of setting the Hadoop and Kubernetes connectivity parameters: - -.. code-block:: - - $ sudo ./sqream-install -p <nn1@SQ.COM> -e kdc.sq.com:<192.168.1.111> - -For related information, see the following sections: - -* :ref:`Accessing the Hadoop and Kubernetes Configuration Files <accessing_hadoop_kubernetes_configuration_files>`. -* :ref:`Configuring the Hadoop and Kubernetes Configuration Files <configure_hadoop_kubernetes_configuration_files>`. - -Modifying Your Data Ingest Folder -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've validated your license, you can modify your data ingest folder after the first run by running the following command: - -.. code-block:: - - $ sudo ./sqream-install -d /home/sqream/data_in - -Configuring Your Network for Docker -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've modified your data ingest folder (if needed), you must validate that the server network and Docker network that you are setting up do not overlap. - -**To configure your network for Docker:** - -1. To verify that your server network and Docker network do not overlap, run the following command: - -.. code-block:: - - $ ifconfig | grep 172. - -2. Do one of the following: - - * If running the above command output no results, continue the installation process. - * If running the above command output results, run the following command: - - .. code-block:: - - $ ifconfig | grep 192.168. - - -Checking and Verifying Your System Settings -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once you've configured your network for Docker, you can check and verify your system settings. - -Running the following command shows you all the variables used by your SQream system: - -.. code-block:: - - $ ./sqream-install -s - -The following is an example of the correct output: - -.. code-block:: - - SQREAM_CONSOLE_TAG=1.5.4 - SQREAM_TAG=2019.2.1 - SQREAM_EDITOR_TAG=3.0.0 - license_worker_0=f0:cc: - license_worker_1=26:91: - license_worker_2=20:26: - license_worker_3=00:36: - SQREAM_VOLUME=/media/sqreamdb - SQREAM_DATA_INGEST=/media/sqreamdb/data_in - SQREAM_CONFIG_DIR=/etc/sqream/ - LICENSE_VALID=true - SQREAM_LOG_DIR=/var/log/sqream/ - SQREAM_USER=sqream - SQREAM_HOME=/home/sqream - SQREAM_ENV_PATH=/home/sqream/.sqream/env_file - PROCESSOR=x86_64 - METADATA_PORT=3105 - PICKER_PORT=3108 - NUM_OF_GPUS=2 - CUDA_VERSION=10.1 - NVIDIA_SMI_PATH=/usr/bin/nvidia-smi - DOCKER_PATH=/usr/bin/docker - NVIDIA_DRIVER=418 - SQREAM_MODE=single_host - -Using the SQream Console -========================= -After configuring the SQream software and veriying your system settings you can begin using the SQream console. - -SQream Console - Basic Commands ---------------------------------- -The SQream console offers the following basic commands: - -* :ref:`Starting your SQream console <starting_sqream_console>` -* :ref:`Starting Metadata and Picker <starting_metadata_and_picker>` -* :ref:`Starting the running services <starting_running_services>` -* :ref:`Listing the running services <listing_running_services>` -* :ref:`Stopping the running services <stopping_running_services>` -* :ref:`Using the SQream editor <using_sqream_editor>` -* :ref:`Using the SQream Client <using_sqream_client>` - -.. _starting_sqream_console: - -Starting Your SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can start your SQream console by running the following command: - -.. code-block:: - - $ ./sqream-console - -.. _starting_metadata_and_picker: - -Starting the SQream Master -~~~~~~~~~~~~~~~~~ - -**To listen to metadata and picker:** - -1. Start the metadata server (default port 3105) and picker (default port 3108) by running the following command: - - .. code-block:: - - $ sqream master --start - - The following is the correct output: - - .. code-block:: - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - -2. *Optional* - Change the metadata and server picker ports by adding ``-p <port number>`` and ``-m <port number>``: - - .. code-block:: - - $ sqream-console>sqream master --start -p 4105 -m 43108 - $ starting master server in single_host mode ... - $ sqream_single_host_master is up and listening on ports: 4105,4108 - - - -.. _starting_running_services: - -Starting SQream Workers -~~~~~~~~~~~~~~~~~ - - -When starting SQream workers, setting the ``<number of workers>`` value sets how many workers to start. Leaving the ``<number of workers>`` value unspecified runs all of the available resources. - - -.. code-block:: - - $ sqream worker --start <number of workers> - - The following is an example of expected output when setting the ``<number of workers>`` value to ``2``: - - .. code-block:: - - sqream-console>sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - -.. _listing_running_services: - -Listing the Running Services -~~~~~~~~~~~~~~~~~ - -You can list running SQream services to look for container names and ID's by running the following command: - -.. code-block:: - - $ sqream master --list - -The following is an example of the expected output: - -.. code-block:: - - sqream-console>sqream master --list - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038-- - - -.. _stopping_running_services: - -Stopping the Running Services -~~~~~~~~~~~~~~~~~ - -You can stop running services either for a single SQream worker, or all SQream services for both master and worker. - -The following is the command for stopping a running service for a single SQream worker: - -.. code-block:: - - $ sqream worker --stop <full worker name> - -The following is an example of expected output when stopping a running service for a single SQream worker: - -.. code-block:: - - sqream worker stop <full worker name> - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - - -You can stop all running SQream services (both master and worker) by running the following command: - -.. code-block:: - - $ sqream-console>sqream master --stop --all - -The following is an example of expected output when stopping all running services: - -.. code-block:: - - sqream-console>sqream master --stop --all - stopped container sqream_single_host_worker_0, id: 892a8f1a58c5 - stopped container sqream_single_host_master, id: 55cb7e38eb22 - - -.. _using_sqream_editor: - -Using SQream Studio -~~~~~~~~~~~~~~~~~ -SQream Studio is an SQL statement editor. - -**To start SQream Studio:** - -1. Run the following command: - - .. code-block:: - - $ sqream studio --start - -The following is an example of the expected output: - - .. code-block:: - - SQream Acceleration Studio is available at http://192.168.1.62:8080 - -2. Click the ``http://192.168.1.62:8080`` link shown in the CLI. - - -**To stop SQream Studio:** - -You can stop your SQream Studio by running the following command: - -.. code-block:: - - $ sqream studio --stop - -The following is an example of the expected output: - -.. code-block:: - - sqream_admin stopped - - -.. _using_sqream_client: - -Using the SQream Client -~~~~~~~~~~~~~~~~~ -You can use the embedded SQream Client on the following nodes: - -* Master node -* Worker node - - -When using the SQream Client on the Master node, the following default settings are used: - -* **Default port**: 3108. You can change the default port using the ``-p`` variable. -* **Default database**: master. You can change the default database using the ``-d`` variable. - -The following is an example: - -.. code-block:: - - $ sqream client --master -u sqream -w sqream - - -When using the SQream Client on a Worker node (or nodes), you should use the ``-p`` variable for Worker ports. The default database is ``master``, but you can use the ``-d`` variable to change databases. - -The following is an example: - -.. code-block:: - - $ sqream client --worker -p 5000 -u sqream -w sqream - - -Moving from Docker Installation to Standard On-Premises Installation ------------------------------------------------ - -Because Docker creates all files and directories on the host at the **root** level, you must grant ownership of the SQream storage folder to the working directory user. - -SQream Console - Advanced Commands ------------------------------ - -The SQream console offers the following advanced commands: - - -* :ref:`Controlling the spool size <controlling_spool_size>` -* :ref:`Splitting a GPU <splitting_gpu>` -* :ref:`Splitting a GPU and setting the spool size <splitting_gpu_setting_spool_size>` -* :ref:`Using a custom configuration file <using_custom_configuration_file>` -* :ref:`Clustering your Docker environment <clustering_docker_environment>` - - - - -.. _controlling_spool_size: - -Controlling the Spool Size -~~~~~~~~~~~~~~~~~~ - -From the console you can define a spool size value. - -The following example shows the spool size being set to ``50``: - -.. code-block:: - - $ sqream-console>sqream worker --start 2 -m 50 - - -If you don't define the SQream spool size, the SQream console automatically distributes the available RAM between all running workers. - -.. _splitting_gpu: - -Splitting a GPU -~~~~~~~~~~~~~~~~~~ - -You can start more than one sqreamd on a single GPU by splitting it. - - -The following example shows the GPU being split into **two** sqreamd's on the GPU in **slot 0**: - -.. code-block:: - - $ sqream-console>sqream worker --start 2 -g 0 - -.. _splitting_gpu_setting_spool_size: - -Splitting GPU and Setting the Spool Size -~~~~~~~~~~~~~~~~~~ - -You can simultaneously split a GPU and set the spool size by appending the ``-m`` flag: - -.. code-block:: - - $ sqream-console>sqream worker --start 2 -g 0 -m 50 - -.. note:: The console does not validate whether the user-defined spool size is available. Before setting the spool size, verify that the requested resources are available. - -.. _using_custom_configuration_file: - -Using a Custom Configuration File -~~~~~~~~~~~~~~~~~~ - -SQream lets you use your own external custom configuration json files. You must place these json files in the path mounted in the installation. SQream recommends placing the json file in the Configuration folder. - -The SQream console does not validate the integrity of your external configuration files. - -When using your custom configuration file, you can use the ``-j`` flag to define the full path to the Configuration file, as in the example below: - -.. code-block:: - - $ sqream-console>sqream worker --start 1 -j /etc/sqream/configfile.json - -.. note:: To start more than one sqream daemon, you must provide files for each daemon, as in the example below: - -.. code-block:: - - $ sqream worker --start 2 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. note:: To split a specific GPU, you must also list the GPU flag, as in the example below: - -.. code-block:: - - $ sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -.. _clustering_docker_environment: - -Clustering Your Docker Environment -~~~~~~~~~~~~~~~~~~ - -SQream lets you connect to a remote Master node to start Docker in Distributed mode. If you have already connected to a Slave node server in Distributed mode, the **sqream Master** and **Client** commands are only available on the Master node. - -.. code-block:: - - $ --master-host - $ sqream-console>sqream worker --start 1 --master-host 192.168.0.1020 - -Checking the Status of SQream Services ---------------------------- -SQream lets you check the status of SQream services from the following locations: - -* :ref:`From the Sqream console <inside_sqream_console>` -* :ref:`From outside the Sqream console <outside_sqream_console>` - -.. _inside_sqream_console: - -Checking the Status of SQream Services from the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From the SQream console, you can check the status of SQream services by running the following command: - -.. code-block:: - - $ sqream-console>sqream master --list - -The following is an example of the expected output: - -.. code-block:: - - $ sqream-console>sqream master --list - $ checking 3 sqream services: - $ sqream_single_host_worker_1 up, listens on port: 5001 allocated gpu: 1 - $ sqream_single_host_worker_0 up, listens on port: 5000 allocated gpu: 1 - $ sqream_single_host_master up listens on ports: 3105,3108 - -.. _outside_sqream_console: - -Checking the Status of SQream Services from Outside the SQream Console -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -From outside the Sqream Console, you can check the status of SQream services by running the following commands: - -.. code-block:: - - $ sqream-status - $ NAMES STATUS PORTS - $ sqream_single_host_worker_1 Up 3 minutes 0.0.0.0:5001->5001/tcp - $ sqream_single_host_worker_0 Up 3 minutes 0.0.0.0:5000->5000/tcp - $ sqream_single_host_master Up 3 minutes 0.0.0.0:3105->3105/tcp, 0.0.0.0:3108->3108/tcp - $ sqream_editor_3.0.0 Up 3 hours (healthy) 0.0.0.0:3000->3000/tcp - -Upgrading Your SQream System ----------------------------- -This section describes how to upgrade your SQream system. - -**To upgrade your SQream system:** - -1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ team for access to the new SQream package tarball file. - - :: - -2. Set a maintenance window to enable stopping the system while upgrading it. - - :: - -3. Extract the following tarball file received from the SQream Support team, under it with the same user and in the same folder that you used while :ref:`Downloading the SQream Software <_download_sqream_software>`. - - - .. code-block:: - - $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -4. Navigate to the new folder created as a result of extracting the tarball file: - - .. code-block:: - - $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -5. Initiate the upgrade process: - - .. code-block:: - - $ ./sqream-install -i - - Initiating the upgrade process checks if any SQream services are running. If any services are running, you will be prompted to stop them. - -6. Do one of the following: - - * Select **Yes** to stop all running SQream workers (Master and Editor) and continue the upgrade process. - * Select **No** to stop the upgrade process. - - SQream periodically upgrades the metadata structure. If an upgrade version includes a change to the metadata structure, you will be prompted with an approval request message. Your approval is required to finish the upgrade process. - - Because SQream supports only certain metadata versions, all SQream services must be upgraded at the same time. - -7. When the upgrade is complete, load the SQream console and restart your services. - - For assistance, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. From 67f1306aeee307dbf61e9a24c73c764d3f5fbb20 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 May 2023 09:02:49 +0300 Subject: [PATCH 0563/1892] Update getting_started.rst --- sqream_studio_5.4.7/getting_started.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sqream_studio_5.4.7/getting_started.rst b/sqream_studio_5.4.7/getting_started.rst index 03aeca142..8771e5545 100644 --- a/sqream_studio_5.4.7/getting_started.rst +++ b/sqream_studio_5.4.7/getting_started.rst @@ -4,8 +4,9 @@ Getting Started with SQream Acceleration Studio 5.4.7 **************************** Setting Up and Starting Studio ----------------- -Studio is included with all :ref:`dockerized installations of SQream DB<running_sqream_in_a_docker_container>`. When starting Studio, it listens on the local machine on port 8080. +------------------------------ + +When starting Studio, it listens on the local machine on port 8080. Logging In to Studio --------------- From 140417e91afe32cb44a985d434992ce1639515ad Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 May 2023 09:09:43 +0300 Subject: [PATCH 0564/1892] Update installing_studio_on_stand_alone_server.rst --- ...nstalling_studio_on_stand_alone_server.rst | 179 +----------------- 1 file changed, 1 insertion(+), 178 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 362828313..6c6c2e05a 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -5,7 +5,7 @@ *********************** Installing Studio on a Stand-Alone Server *********************** -The **Installing Studio on a Stand-Alone Server** guide describes how to install SQream Studio on a stand-alone server. A stand-alone server is a server that does not run SQream based on binary files, Docker, or Kubernetes. +A stand-alone server is a server that does not run SQream based on binary files or Kubernetes. The Installing Studio on a Stand-Alone Server guide includes the following sections: @@ -431,180 +431,3 @@ To upgrade Studio you need to stop the version that you currently have. Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` -.. _install_studio_docker_container: - -Installing Studio in a Docker Container -^^^^^^^^^^^^^^^^^^^^^^^ -This guide explains how to install SQream Studio in a Docker container and includes the following sections: - -.. contents:: - :local: - :depth: 1 - -Installing Studio --------------- -If you have already installed Docker, you can install Studio in a Docker container. - -**To install Studio:** - -1. Copy the downloaded image onto the target server. - -:: - -2. Load the Docker image. - - .. code-block:: console - - $ docker load -i <docker_image_file> - -:: - -3. If the downloaded image is called **sqream-acceleration-studio-5.1.3.x86_64.docker18.0.3.tar,** run the following command: - - .. code-block:: console - - $ docker load -i sqream-acceleration-studio-5.1.3.x86_64.docker18.0.3.tar - -:: - -4. Start the Docker container. - - .. code-block:: console - - $ docker run -d --restart=unless-stopped -p <external port>:8080 -e runtime=docker -e SQREAM_K8S_PICKER=<SQream host IP or VIP> -e SQREAM_PICKER_PORT=<SQream picker port> -e SQREAM_DATABASE_NAME=<SQream database name> -e SQREAM_ADMIN_UI_PORT=8080 --name=sqream-admin-ui <docker_image_name> - - The following is an example of the command above: - - .. code-block:: console - - $ docker run -d --name sqream-studio -p 8080:8080 -e runtime=docker -e SQREAM_K8S_PICKER=192.168.0.183 -e SQREAM_PICKER_PORT=3108 -e SQREAM_DATABASE_NAME=master -e SQREAM_ADMIN_UI_PORT=8080 sqream-acceleration-studio:5.1.3 - -Back to :ref:`Installing Studio in a Docker Container<install_studio_docker_container>` - -Accessing Studio ------------------ -You can access Studio from Port 8080: ``http://<server ip>:8080``. - -If you want to use Studio over a secure connection (https), you must use the parameter values shown in the following table: - -.. list-table:: - :widths: 10 25 65 - :header-rows: 1 - - * - Parameter - - Default Value - - Description - * - ``--web-ssl-port`` - - 8443 - - - * - ``--web-ssl-key-path`` - - None - - The path of SSL key PEM file for enabling https. Leave empty to disable. - * - ``--web-ssl-cert-path`` - - None - - The path of SSL certificate PEM file for enabling https. Leave empty to disable. - -You can configure the above parameters using the following syntax: - -.. code-block:: console - - $ npm run setup -- -y --host=127.0.0.1 --port=3108 - -.. _using_docker_container_commands: - -Back to :ref:`Installing Studio in a Docker Container<install_studio_docker_container>` - -Using Docker Container Commands ---------------- -When installing Studio in Docker, you can run the following commands: - -* View Docker container logs: - - .. code-block:: console - - $ docker logs -f sqream-admin-ui - -* Restart the Docker container: - - .. code-block:: console - - $ docker restart sqream-admin-ui - -* Kill the Docker container: - - .. code-block:: console - - $ docker rm -f sqream-admin-ui - -Back to :ref:`Installing Studio in a Docker Container<install_studio_docker_container>` - -Setting Up Argument Configurations ----------------- -When creating the **sqream-admin-config.json** configuration file, you can add ``-y`` to create the configuration file in non-interactive mode. Configuration files created in non-interactive mode use all the parameter defaults not provided in the command. - -The following table shows the available arguments: - -.. list-table:: - :widths: 10 25 65 - :header-rows: 1 - - * - Parameter - - Default Value - - Description - * - ``--web--host`` - - 8443 - - - * - ``--web-port`` - - 8080 - - - * - ``--web-ssl-port`` - - 8443 - - - * - ``--web-ssl-key-path`` - - None - - The path of the SSL Key PEM file for enabling https. Leave empty to disable. - * - ``--web-ssl-cert-path`` - - None - - The path of the SSL Certificate PEM file for enabling https. Leave empty to disable. - * - ``--debug-sqream (flag)`` - - false - - - * - ``--host`` - - 127.0.0.1 - - - * - ``--port`` - - 3108 - - - * - ``is-cluster (flag)`` - - true - - - * - ``--service`` - - sqream - - - * - ``--ssl (flag)`` - - false - - Enables the SQream SSL connection. - * - ``--name`` - - default - - - * - ``--data-collector-url`` - - localhost:8100/api/dashboard/data - - Enables the Dashboard. Leaving this blank disables the Dashboard. Using a mock URL uses mock data. - * - ``--cluster-type`` - - standalone (``standalone`` or ``k8s``) - - - * - ``--config-location`` - - ./sqream-admin-config.json - - - * - ``--network-timeout`` - - 60000 (60 seconds) - - - * - ``--access-key`` - - None - - If defined, UI access is blocked unless ``?ui-access=<access key>`` is included in the URL. - -Back to :ref:`Installing Studio in a Docker Container<install_studio_docker_container>` - - :: - -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` \ No newline at end of file From 2bde6c3a6509179c76191396135560ef4afd054c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 May 2023 11:59:20 +0300 Subject: [PATCH 0565/1892] Update 4.3.rst --- releases/4.3.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/releases/4.3.rst b/releases/4.3.rst index 62571e42c..36e838428 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -106,6 +106,12 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t * ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. +End of Support +-------------- + +Support in an :ref:`old method <previous_configuration_method>` of configuring the SQreamDB instance ends on September xxx, 2023. + + Upgrading to v4.3 ------------------- 1. Generate a back-up of the metadata by running the following command: From 2883de426db6ecc10bbea80e6171b6180a6cef54 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 May 2023 16:04:04 +0300 Subject: [PATCH 0566/1892] S3 and permissions --- external_storage_platforms/s3.rst | 22 +++++++++++++- .../access_control_permissions.rst | 30 +++++++++++++++++-- 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index bb0a22f27..18dca4476 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -14,7 +14,6 @@ S3 Configuration A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. - S3 URI Format ============= With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. @@ -25,10 +24,30 @@ The following is an example of the general S3 syntax: s3://bucket_name/path + Authentication ============== SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. + +Access +====== +You may use the following flags within your SQreamDB configuration file to configure access to S3: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Default Value + * - ``AwsEndpointOverride`` + - Override the HTTP endpoint used to talk to a service. + - + - ``AwsObjectAccessStyle`` + - There are two main S3 object access styles, which determine how you can access and interact with the objects stored in an S3 bucket. + - + Examples ======== @@ -47,6 +66,7 @@ Use a foreign table to stage data from S3 before loading from CSV, Parquet, or O .. contents:: :local: :depth: 1 + Planning for Data Staging ------------------------- The examples in this section are based on the following table: diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index e03e9198d..3f1923024 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -55,8 +55,34 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All function permissions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ - - +| **Object/Layer: View** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from view | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | DDL operations of view results | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Foreign Table** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from foreign table | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Foreign table DDL operations | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Column** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from catalog | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Column DDL operations | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Layer: Catalog** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from catalog | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Catalog DDL operations | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Object/Services** | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | Using a specific service | ++--------------------+-------------------------------------------------------------------------------------------------------------------------+ GRANT From efc297b0844454fd5b1835287d758d73ba3cb0f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 May 2023 16:51:42 +0300 Subject: [PATCH 0567/1892] Update delete_guide.rst --- operational_guides/delete_guide.rst | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/operational_guides/delete_guide.rst b/operational_guides/delete_guide.rst index abf99a0b4..bec0f296d 100644 --- a/operational_guides/delete_guide.rst +++ b/operational_guides/delete_guide.rst @@ -1,8 +1,8 @@ .. _delete_guide: -*********************** +************* Deleting Data -*********************** +************* When working with a table in a database, deleting data typically involves removing rows, although it can also involve removing columns. The process for deleting data involves first deleting the desired content, followed by a cleanup operation that reclaims the space previously occupied by the deleted data. This process is further explained below. @@ -19,7 +19,7 @@ By using the WHERE clause in the DELETE statement, you can specify a condition o :depth: 1 The Deletion Process -========== +==================== When you delete rows from a SQL database, the actual deletion process occurs in two steps: @@ -33,7 +33,7 @@ If you want to delete all rows from a table, you can use the :ref:`TRUNCATE<trun Usage Notes -===================== +=========== General Notes ------------- @@ -124,7 +124,7 @@ Deleting Rows from a Table Return animal_id | animal_name | animal_weight - ------------+------------------+-------------------- + ------------+------------------+-------------- 1 | Dog | 7 2 | Possum | 3 3 | Cat | 5 @@ -132,7 +132,7 @@ Deleting Rows from a Table Deleting Values Based on Complex Predicates ---------------------------------------------------- +------------------------------------------- 1. Delete rows from the table: @@ -158,7 +158,7 @@ Deleting Values Based on Complex Predicates Identifying and Cleaning Up Tables --------------------------------------- -Listing Tables that Have Not Been Cleaned Up +Listing tables that have not been cleaned up: .. code-block:: psql @@ -170,7 +170,7 @@ Listing Tables that Have Not Been Cleaned Up 1 row -Identifying Predicates for Clean-Up +Identifying predicates for Clean-Up: .. code-block:: psql @@ -181,13 +181,12 @@ Identifying Predicates for Clean-Up weight > 1000 1 row - -.. _trigger_cleanup: + Triggering a Clean-Up ^^^^^^^^^^^^^^^^^^^^^^ -When running the clean-up operation, you need to specify two parameters: ``schema_name`` and ``table_name``. However, it's important to note that the second parameter is case-sensitive for both ``CLEANUP_CHUNKS`` and ``CLEANUP_EXTENTS``. +When running the clean-up operation, you need to specify two parameters: ``schema_name`` and ``table_name``. Note that both parameters are case-sensitive and cannot operate with upper-cased schema or table names. Running a ``CLEANUP_CHUNKS`` command (also known as ``SWEEP``) to reorganize the chunks: @@ -206,11 +205,11 @@ If you should want to run a clean-up operation without worrying about uppercase .. code-block:: psql - farm=> SELECT CLEANUP_CHUNKS('<schema_name>','<table_name>', false); + farm=> SELECT CLEANUP_CHUNKS('<schema_name>','<table_name>', true); .. code-block:: psql - farm=> SELECT CLEANUP_EXTENTS('<schema_name>','<table_name>', false); + farm=> SELECT CLEANUP_EXTENTS('<schema_name>','<table_name>', true); To display the table: From cb3397f687da5634117f6cabad60ae2155c25edf Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 09:47:16 +0300 Subject: [PATCH 0568/1892] S3 --- external_storage_platforms/s3.rst | 37 +++++++++++++++++++++++-------- releases/4.3.rst | 11 ++++++--- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index 18dca4476..d5433c294 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -7,6 +7,7 @@ SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifie .. contents:: :local: + :depth: 1 S3 Configuration ================ @@ -30,9 +31,11 @@ Authentication SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. -Access -====== -You may use the following flags within your SQreamDB configuration file to configure access to S3: +Connecting to S3 Using SQreamDB Legacy Configuration File +========================================================= + + +You may use the following parameters within your SQreamDB legacy configuration file: .. list-table:: :widths: auto @@ -40,13 +43,29 @@ You may use the following flags within your SQreamDB configuration file to confi * - Parameter - Description - - Default Value + - Parameter Value + - Example * - ``AwsEndpointOverride`` - - Override the HTTP endpoint used to talk to a service. - - - - ``AwsObjectAccessStyle`` - - There are two main S3 object access styles, which determine how you can access and interact with the objects stored in an S3 bucket. - - + - Overrides the AWS S3 HTTP endpoint when using Virtual Private Cloud (VPC) + - ``URL`` + Default: None + - .. code-block:: + + sqream_config_legacy.json: + { + ..., + "AwsEndpointOverride": "https://my.endpoint.local" + } + * - ``AwsObjectAccessStyle`` + - Enables configuration of S3 object access styles, which determine how you can access and interact with the objects stored in an S3 bucket + - ``virtual-host`` or ``path``. Default is ``virtual-host`` + - .. code-block:: + + sqream_config_legacy.json: + { + ..., + "AwsObjectAccessStyle": "path" + } Examples ======== diff --git a/releases/4.3.rst b/releases/4.3.rst index 36e838428..c4e2b7e32 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -76,10 +76,15 @@ Version 4.3 resolved Issues | SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | +--------------------+------------------------------------------------------------------------------------------------+ -Configuration Changes ---------------------- +Configuration Adjustments +------------------------- -You may now configure the ``metadata_server`` using the ``metadata_server_config.json`` :ref:`configuration file<metadata_server>`. +When using SQreamDB legacy configuration file and AWS S3, you may be required to use the following new parameters: + +* ``AwsEndpointOverride`` +* ``AwsObjectAccessStyle`` + +To learn more about how and when you should use them, visit :ref:`s3`. Deprecated Features From 4808556ceb03a4220570f62a27c6160fff395add Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 09:52:10 +0300 Subject: [PATCH 0569/1892] Update s3.rst --- external_storage_platforms/s3.rst | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index d5433c294..2314170cf 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -70,16 +70,6 @@ You may use the following parameters within your SQreamDB legacy configuration f Examples ======== -AwsEndpointOverride - Enables custom endpoint - -Example: 'https://s3.amazonaws.com' - -AwsObjectAccessStyle - whether to use path-style or virtual object style access - read about in AWS documentation. - -If you wish to use custom endpoint, you need to configure sqream using our legacy configuration file, and add AwsEndpointOverride - Enables custom endpoint. And you may add the AwsObjectAccessStyle flag to send request for a different access style. - - - Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. .. contents:: From 0a8c5c93bb3943ebbfaf1d06da8cd5fb29c47cba Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 11:45:30 +0300 Subject: [PATCH 0570/1892] Permissions --- connecting_to_sqream/client_drivers/index.rst | 2 +- .../access_control_permissions.rst | 320 ++++++++++++------ 2 files changed, 210 insertions(+), 112 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 26a6750ea..f8a61d90b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -17,7 +17,7 @@ The following are applicable to all operating systems: * **JDBC** - recommended installation via ``mvn``: - * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.6.jar>`_ - sqream-jdbc-4.5.6 (.jar) + * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.9.jar>`_ - sqream-jdbc-4.5.9 (.jar) * :ref:`java_jdbc` .. _.net: diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 3f1923024..15b41182c 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -4,6 +4,10 @@ Permissions ************** +.. contents:: + :local: + :depth: 1 + The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -85,161 +89,255 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -GRANT ------ +GRANT Syntax +============ :ref:`grant` gives permissions to a role. .. code-block:: postgres - -- Grant permissions at the instance/ storage cluster level: - GRANT + -- Grant permissions at the instance/ storage cluster level: + GRANT + + { SUPERUSER + | LOGIN + | PASSWORD '<password>' + } + TO <role> [, ...] + + -- Grant permissions at the database level: + GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} + + ON DATABASE <database> [, ...] + TO <role> [, ...] + + -- Grant permissions at the schema level: + GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ + PERMISSIONS ]} + ON SCHEMA <schema> [, ...] + TO <role> [, ...] + + -- Grant permissions at the object level: + GRANT {{SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL [PERMISSIONS]} + ON { TABLE <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...] | VIEW <view_name> [, ...] | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] | CATALOG <catalog_name> [, ...] } + TO <role> [, ...]; + + -- Grant execute function permission: + GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name + TO role; + + -- Grant permissions at the column level: + GRANT {{SELECT | DDL } [, ...] | ALL [PERMISSIONS]} + ON { COLUMN <column_name> [, ...] | ALL COLUMNS IN TABLE <table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] | ALL COLUMNS IN VIEW <view_name> [, ...] | ALL COLUMNS IN CATALOG <catalog_name> [, ...]} + TO <role> [, ...]; + + -- Grant permissions at the Service level: + GRANT {{USAGE} [, ...] | ALL [PERMISSIONS]} + ON { SERVICE <service_name> [, ...] | ALL SERVICES IN SYSTEM } + TO <role> [, ...] + + -- Allows role2 to use permissions granted to role1 + GRANT <role1> [, ...] + TO <role2> + + -- Also allows the role2 to grant role1 to other roles: + GRANT <role1> [, ...] + TO <role2> + WITH ADMIN OPTION + +REVOKE Syntax +============= - { SUPERUSER - | LOGIN - | PASSWORD '<password>' - } - TO <role> [, ...] +:ref:`revoke` removes permissions from a role. - -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} +.. code-block:: postgres - ON DATABASE <database> [, ...] - TO <role> [, ...] + -- Revoke permissions at the instance/ storage cluster level: + REVOKE + { SUPERUSER + | LOGIN + | PASSWORD + } + FROM <role> [, ...] + + -- Revoke permissions at the database level: + REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} + ON DATABASE <database> [, ...] + FROM <role> [, ...] + + -- Revoke permissions at the schema level: + REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} + ON SCHEMA <schema> [, ...] + FROM <role> [, ...] + + -- Revoke permissions at the object level: + REVOKE { { SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL } + ON { [ TABLE ] <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...] | VIEW <view_name> [, ...] | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] | CATALOG <catalog_name> [, ...] } + FROM <role> [, ...]; + + -- Revoke permissions at the column level: + REVOKE {{SELECT | DDL } [, ...] | ALL [PERMISSIONS]} + ON { COLUMN <column_name> [, ...] | ALL COLUMNS IN TABLE <table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] | ALL COLUMNS IN VIEW <view_name> [, ...] | ALL COLUMNS IN CATALOG <catalog_name> [, ...]} + FROM <role> [, ...]; + + -- Revoke permissions at the column level: + REVOKE {{USAGE} [, ...] | ALL [PERMISSIONS]} + ON { SERVICE <service_name> [, ...] | ALL SERVICES IN SYSTEM} + FROM <role> [, ...] + + -- Removes access to permissions in role1 by role 2 + REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION + + -- Removes permissions to grant role1 to additional roles from role2 + REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION + +Altering Default Permissions +============================ - -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} - ON SCHEMA <schema> [, ...] - TO <role> [, ...] - - -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL [PERMISSIONS]} - ON { TABLE <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...]} - TO <role> [, ...] - - -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name - TO role; - - -- Allows role2 to use permissions granted to role1 - GRANT <role1> [, ...] - TO <role2> +The default permissions system (See :ref:`alter_default_permissions`) +can be used to automatically grant permissions to newly +created objects (See the departmental example below for one way it can be used). + +A default permissions rule looks for a schema being created, or a +table (possibly by schema), and is table to grant any permission to +that object to any role. This happens when the create table or create +schema statement is run. - -- Also allows the role2 to grant role1 to other roles: - GRANT <role1> [, ...] - TO <role2> - WITH ADMIN OPTION - -``GRANT`` examples: .. code-block:: postgres - GRANT LOGIN,superuser TO admin; + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { SCHEMAS | TABLES | FOREIGN TABLE | VIEWS | COLUMN | SERVICES | CATALOG } + { grant_clause | DROP grant_clause} + TO ROLE { role_name | public }; + + grant_clause ::= + GRANT + { CREATE FUNCTION + | SUPERUSER + | CONNECT + | CREATE + | USAGE + | SELECT + | INSERT + | DELETE + | DDL + | UPDATE + | EXECUTE + | ALL + } + +Examples +======== - GRANT CREATE FUNCTION ON database master TO admin; +GRANT Examples +-------------- - GRANT SELECT ON TABLE admin.table1 TO userA; +Grant superuser privileges and login capability to a role: - GRANT EXECUTE ON FUNCTION my_function TO userA; +.. code-block:: postgres - GRANT ALL ON FUNCTION my_function TO userA; + GRANT SUPERUSER, LOGIN TO role_name; + +Grant specific permissions on a database to a role: - GRANT DDL ON admin.main_table TO userB; +.. code-block:: postgres - GRANT ALL ON all tables IN schema public TO userB; + GRANT CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION ON DATABASE database_name TO role_name; + +Grant various permissions on a schema to a role: - GRANT admin TO userC; +.. code-block:: postgres - GRANT superuser ON schema demo TO userA + GRANT CREATE, DDL, USAGE, SUPERUSER ON SCHEMA schema_name TO role_name; + +Grant permissions on specific objects (table, view, foreign table, or catalog) to a role: - GRANT admin_role TO userB; +.. code-block:: postgres -REVOKE ------- + GRANT SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE table_name TO role_name; -:ref:`revoke` removes permissions from a role. +Grant execute function permission to a role: .. code-block:: postgres - -- Revoke permissions at the instance/ storage cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD - } - FROM <role> [, ...] - - -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} - ON DATABASE <database> [, ...] - FROM <role> [, ...] + GRANT EXECUTE ON FUNCTION function_name TO role_name; - -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} - ON SCHEMA <schema> [, ...] - FROM <role> [, ...] - - -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL } - ON { [ TABLE ] <table_name> [, ...] | ALL TABLES IN SCHEMA +Grant column-level permissions to a role: - <schema_name> [, ...] } - FROM <role> [, ...] - - -- Removes access to permissions in role1 by role 2 - REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION +.. code-block:: postgres - -- Removes permissions to grant role1 to additional roles from role2 - REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION + GRANT SELECT, DDL ON COLUMN column_name TO role_name; +Grant usage permissions on a service to a role: -Examples: +.. code-block:: postgres + + GRANT USAGE ON SERVICE service_name TO role_name; + +Grant role2 the ability to use permissions granted to role1: .. code-block:: postgres - REVOKE superuser on schema demo from userA; + GRANT role1 TO role2; - REVOKE delete on admin.table1 from userB; +Grant role2 the ability to grant role1 to other roles: - REVOKE login from role_test; +.. code-block:: postgres - REVOKE CREATE FUNCTION FROM admin; + GRANT role1 TO role2 WITH ADMIN OPTION; -Default permissions -------------------- -The default permissions system (See :ref:`alter_default_permissions`) -can be used to automatically grant permissions to newly -created objects (See the departmental example below for one way it can be used). +REVOKE Examples +--------------- -A default permissions rule looks for a schema being created, or a -table (possibly by schema), and is table to grant any permission to -that object to any role. This happens when the create table or create -schema statement is run. +Revoke superuser privileges or login capability from a role: + +.. code-block:: postgres + REVOKE SUPERUSER, LOGIN FROM role_name; + +Revoke specific permissions on a database from a role: .. code-block:: postgres + REVOKE CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION FROM role_name; + +Revoke permissions on a schema from a role: + +.. code-block:: postgres + + REVOKE CREATE, DDL, USAGE, SUPERUSER FROM role_name; + +Revoke permissions on specific objects (table, view, foreign table, or catalog) from a role: + +.. code-block:: postgres + + REVOKE SELECT, INSERT, DELETE, DDL, UPDATE FROM TABLE table_name; + +Revoke column-level permissions from a role: + +.. code-block:: postgres + + REVOKE SELECT, DDL FROM COLUMN column_name; + +Revoke usage permissions on a service from a role: + +.. code-block:: postgres + + REVOKE USAGE FROM SERVICE service_name; + +Remove access to permissions in role1 by role2: + +.. code-block:: postgres + + REVOKE role1 FROM role2 WITH ADMIN OPTION; + +Remove permissions to grant role1 to additional roles from role2: + +.. code-block:: postgres + + REVOKE role1 FROM role2 WITH ADMIN OPTION; - ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { TABLES | SCHEMAS } - { grant_clause | DROP grant_clause} - TO ROLE { role_name | public }; - grant_clause ::= - GRANT - { CREATE FUNCTION - | SUPERUSER - | CONNECT - | CREATE - | USAGE - | SELECT - | INSERT - | DELETE - | DDL - | UPDATE - | EXECUTE - | ALL - } \ No newline at end of file From b5836d4e638d4d15e4fb09c1dcdf2b90606431b4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 12:00:33 +0300 Subject: [PATCH 0571/1892] Update 4.3.rst --- releases/4.3.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/releases/4.3.rst b/releases/4.3.rst index c4e2b7e32..ef0cc6adf 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -33,6 +33,19 @@ Compatibility Matrix | | * Spark | +-------------------------+------------------------------------------------------------------------+ +New Features and Enhancements +----------------------------- + +Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: + +* VIEWS +* FOREIGN TABLE +* COLUMN +* CATALOG +* SERVICE + +To learn more about how and when you should use the new permissions, visit :ref:`access_control_permissions`. + Known Issues ------------ From 4f9b138ab9d61d953097081390caa81c2de29fbd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 12:02:35 +0300 Subject: [PATCH 0572/1892] Update 4.3.rst --- releases/4.3.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index ef0cc6adf..6b0fcd857 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -38,11 +38,11 @@ New Features and Enhancements Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: -* VIEWS -* FOREIGN TABLE -* COLUMN -* CATALOG -* SERVICE + * VIEWS + * FOREIGN TABLE + * COLUMN + * CATALOG + * SERVICE To learn more about how and when you should use the new permissions, visit :ref:`access_control_permissions`. From f8e26e3cd11e261f7ce063d9364050794d8d6ed9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 May 2023 17:13:43 +0300 Subject: [PATCH 0573/1892] Update index.rst --- .../client_drivers/python/index.rst | 97 ++++++++++--------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index bd71820d8..12b4a7b3b 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -119,53 +119,56 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins -SQLAlchemy Examples -======================== -SQLAlchemy is an **Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. - -This section includes the following examples: +SQLAlchemy +========== +SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. .. contents:: :local: :depth: 1 -Standard Connection Example ---------------------------------- - - -.. code-block:: python - - import sqlalchemy as sa - - engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" - - engine = sa.create_engine(engine_url) +Creating a Standard Connection +------------------------------ - res = engine.execute('create or replace table test (ints int, ints2 int)') - res = engine.execute('insert into test (ints,ints2) values (5,1), (6,2)') - res = engine.execute('select * from test') - for item in res: - print(item) - -Multi Cluster Connection Example ------------------------- +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``username`` + - Username of a role to use for connection + * - ``password`` + - Specifies the password of the selected role + * - ``host`` + - Specifies the host name + * - ``port`` + - Specifies the port number + * - ``port_ssl`` + - An optional parameter + * - ``database`` + - Specifies the database name + * - ``clustered`` + - Establishing a multi-clustered connection. Input values: ``True``, ``False``. Default is ``False`` + * - ``service`` + - Specifies service queue to use -The following example is for using a ServerPicker: .. code-block:: python import sqlalchemy as sa - - engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" - - engine = sa.create_engine(engine_url, connect_args={"clustered": True}) - res = engine.execute("create or replace table tab1 (x int);") - res = engine.execute('insert into tab1 values (5), (6);') - res = engine.execute('select * from tab1') - for item in res: - print(item) + from sqlalchemy.engine.url import URL + engine_url = URL('sqream' + , username='<user_name>' + , password='<password>' + , host='<host_name>' + , port=<port_number> + , port_ssl=<port_ssl> + , database='<database_name>') + engine = sa.create_engine(engine_url,connect_args={"clustered": False, "service": "<service_name>"}) + Pulling a Table into Pandas --------------------------- @@ -174,25 +177,31 @@ The following example shows how to pull a table in Pandas. This examples uses th .. code-block:: python import sqlalchemy as sa + + from sqlalchemy.engine.url import URL + import pandas as pd - engine_url = "sqream://rhendricks:secret_password@localhost:5000/raviga" - engine = sa.create_engine(engine_url) + engine_url = URL('sqream' + , username='sqream' + , password='12345' + , host='127.0.0.1' + , port=3108 + , database='master') + engine = sa.create_engine(engine_url,connect_args={"clustered": True, "service": "admin"}) table_df = pd.read_sql("select * from nba", con=engine) -API Examples -=============== -This section includes the following examples: +API +=== .. contents:: :local: :depth: 1 - Using the Cursor --------------------------------------------- +---------------- The DB-API specification includes several methods for fetching results from the cursor. This sections shows an example using the ``nba`` table, which looks as follows: .. csv-table:: nba @@ -261,7 +270,7 @@ The following is an example of the contents of the row variables used in our exa .. note:: Calling a fetch command after all rows have been fetched will return an empty array (``[]``). Reading Result Metadata ----------------------------- +----------------------- When you execute a statement, the connection object also contains metadata about the result set, such as **column names**, **types**, etc). The metadata is stored in the :py:attr:`Connection.description` object of the cursor: @@ -287,7 +296,7 @@ You can fetch a list of column names by iterating over the ``description`` list: ['Name', 'Team', 'Number', 'Position', 'Age (as of 2018)', 'Height', 'Weight', 'College', 'Salary'] Loading Data into a Table ---------------------------- +------------------------- This example shows how to load 10,000 rows of dummy data to an instance of SQream. **To load data 10,000 rows of dummy data to an instance of SQream:** @@ -363,7 +372,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea Using SQLAlchemy ORM to Create and Populate Tables ------------------------------------------------------------------------ +-------------------------------------------------- This section shows how to use the ORM to create and populate tables from Python objects. **To use SQLAlchemy ORM to create and populate tables:** From 75b1962e48eee056b984d9d195d3dc5360b6fd17 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 31 May 2023 16:02:47 +0300 Subject: [PATCH 0574/1892] 4.3 release date --- releases/4.3.rst | 2 +- releases/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 6b0fcd857..d8546efcb 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -6,7 +6,7 @@ Release Notes 4.3 SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. -The 4.3 release notes were released on xx/xx/xxxx and describe the following: +The 4.3 release notes were released on 31/05/2023 and describe the following: .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index abb8ab7a9..b02e21ff9 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -13,7 +13,7 @@ Release Notes * - Version - Release Date * - :ref:`4.3` - - xxxxxxxxx + - May 31, 2023 * - :ref:`4.2` - April 23, 2023 * - :ref:`4.1` From 69b5026395b3f49bb59997f69234ed808bac277f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 31 May 2023 16:29:03 +0300 Subject: [PATCH 0575/1892] Update 4.3.rst --- releases/4.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index d8546efcb..99a6fbb85 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -127,7 +127,7 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t End of Support -------------- -Support in an :ref:`old method <previous_configuration_method>` of configuring the SQreamDB instance ends on September xxx, 2023. +Support in an :ref:`old method <previous_configuration_method>` of configuring the SQreamDB instance ends on September 30th, 2023. Upgrading to v4.3 From c2bf828ce7f33fbe95a4d544351975c0196d478f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:13:28 +0300 Subject: [PATCH 0576/1892] Update 4.3.rst --- releases/4.3.rst | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 99a6fbb85..0eaccf68e 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -4,9 +4,7 @@ Release Notes 4.3 ***************** -SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. - -The 4.3 release notes were released on 31/05/2023 and describe the following: +The 4.3 release notes were released on xx/06/2023 and describe the following: .. contents:: :local: @@ -44,7 +42,7 @@ Access control permissions in SQreamDB have been expanded, allowing roles to now * CATALOG * SERVICE -To learn more about how and when you should use the new permissions, visit :ref:`access_control_permissions`. +To learn more about how and when you should use this new capability, visit :ref:`access_control_permissions`. Known Issues ------------ @@ -110,10 +108,7 @@ Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided ► Square Brackets ``[]`` -The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, will soon be deprecated to facilitate the use of the ``ARRAY`` data type. - -* Support in ``[]`` for delimiting database object identifiers ends on June 1st, 2023. -* To delimit database object identifiers, you will be able to use double quotes ``""``. +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, are officially deprecated to facilitate the use of the ``ARRAY`` data type. To delimit database object identifiers, use double quotes ``""``. ► ``VARCHAR`` @@ -121,17 +116,11 @@ The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_ The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. * Support in the ``VARCHAR`` data type ends at September 30th, 2023. -* ``VARCHAR`` is no longer supported for new customers, effective from Version 2022.1.3. +* ``VARCHAR`` is no longer supported for new customers, effective from version 2022.1.3. * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. -End of Support --------------- - -Support in an :ref:`old method <previous_configuration_method>` of configuring the SQreamDB instance ends on September 30th, 2023. - - Upgrading to v4.3 -------------------- +----------------- 1. Generate a back-up of the metadata by running the following command: .. code-block:: console From 3802ea9ac54e52b81d6b4cb950aeaee7db17ef03 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 09:58:31 +0300 Subject: [PATCH 0577/1892] Remove "Previous configuration method" --- configuration_guides/configuration_flags.rst | 3 - .../configuration_methods.rst | 19 -- .../current_method_configuration_levels.rst | 1 - .../current_method_modification_methods.rst | 7 +- .../previous_configuration_method.rst | 268 ------------------ configuration_guides/spool_memory_gb.rst | 1 - configuration_guides/spooling.rst | 44 +-- .../shutdown_server_command.rst | 7 +- 8 files changed, 15 insertions(+), 335 deletions(-) delete mode 100644 configuration_guides/configuration_methods.rst delete mode 100644 configuration_guides/previous_configuration_method.rst diff --git a/configuration_guides/configuration_flags.rst b/configuration_guides/configuration_flags.rst index 3a25dc9bd..a61267a6f 100644 --- a/configuration_guides/configuration_flags.rst +++ b/configuration_guides/configuration_flags.rst @@ -3,9 +3,6 @@ ************************* Configuration Flags ************************* -SQream provides two methods for configuration your instance of SQream. The current configuration method is based on cluster and session-based configuration, described in more detail below. Users can also use the previous configuration method done using a configuration file. - -The **Configuration Methods** page describes the following configurations methods: .. toctree:: :maxdepth: 1 diff --git a/configuration_guides/configuration_methods.rst b/configuration_guides/configuration_methods.rst deleted file mode 100644 index 00a70ab5c..000000000 --- a/configuration_guides/configuration_methods.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _configuration_methods: - -************************* -Configuration Methods -************************* -SQream provides two methods for configuration your instance of SQream. The current configuration method is based on cluster and session-based configuration, described in more detail below. Users can also use the previous configuration method done using a configuration file. - -The **Configuration Methods** page describes the following configurations methods: - -.. toctree:: - :maxdepth: 1 - :glob: - :titlesonly: - - current_configuration_method - previous_configuration_method - - - diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index ad5143def..c7443ede2 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -19,7 +19,6 @@ Worker-Based Configuration -------------- Worker-based configuration lets you modify individual workers using a worker configuration file. Worker-based configuration modifications are persistent. -For more information on making configurations from the worker configuration file, see :ref:`previous_configuration_method`. Session-Based Configuration -------------- diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index 05825b07a..be12a9b4c 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -3,7 +3,7 @@ ************************** Modification Methods ************************** -SQream provides two different ways to modify your configurations. The current method is based on hierarchical configuration as described above. This method is based on making modifications on the **worker configuration file**, while you can still make modifications using the previous method using the **legacy configuration file**, both described below: + .. contents:: :local: @@ -35,7 +35,7 @@ Modifying Your Configuration Using a Legacy Configuration File --------------------- You can modify your configuration using a legacy configuration file. -The Legacy configuration file provides access to the read/write flags used in SQream’s previous configuration method. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. +The Legacy configuration file provides access to the read/write flags. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. The following is an example of the legacy configuration file: @@ -46,5 +46,4 @@ The following is an example of the legacy configuration file: “reextentUse”: false, “useClientLog”: true, “useMetadataServer”” false - } -For more information on using the previous configuration method, see :ref:`previous_configuration_method`. \ No newline at end of file + } \ No newline at end of file diff --git a/configuration_guides/previous_configuration_method.rst b/configuration_guides/previous_configuration_method.rst deleted file mode 100644 index ff48e7cc1..000000000 --- a/configuration_guides/previous_configuration_method.rst +++ /dev/null @@ -1,268 +0,0 @@ -.. _previous_configuration_method: - -************************** -Configuring SQream Using the Previous Configuration Method -************************** -The **Configuring SQream Using the Previous Configuration Method** page describes SQream’s previous method for configuring your instance of SQream, and includes the following topics: - -.. contents:: - :local: - :depth: 1 - -By default, configuration files are stored in ``/etc/sqream``. - -A very minimal configuration file looks like this: - -.. code-block:: json - - { - "compileFlags": { - }, - "runtimeFlags": { - }, - "runtimeGlobalFlags": { - }, - "server": { - "gpu": 0, - "port": 5000, - "cluster": "/home/sqream/sqream_storage", - "licensePath": "/etc/sqream/license.enc" - } - } - -* Each SQream DB worker (``sqreamd``) has a dedicated configuration file. - -* The configuration file contains four distinct sections, ``compileFlags``, ``runtimeFlags``, ``runtimeGlobalFlags``, and ``server``. - -In the example above, the worker will start on port 5000, and will use GPU #0. - -Frequently Set Parameters ------- -.. todo - list-table:: Compiler flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - - - - - - - - - - - - -.. list-table:: Server flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``gpu`` - - ``server`` - - Controls the GPU ordinal to use - - ✗ - - 0 to (number of GPUs in the machine -1). Check with ``nvidia-smi -L`` - - ``"gpu": 0`` - * - ``port`` - - ``server`` - - Controls the TCP port to listen on - - ✗ - - 1024 to 65535 - - ``"port" : 5000`` - * - ``ssl_port`` - - ``server`` - - Controls the SSL TCP port to listen on. Must be different from ``port`` - - ✗ - - 1024 to 65535 - - ``"ssl_port" : 5100`` - * - ``cluster`` - - ``server`` - - Specifies the cluster path root - - ✗ - - Valid local system path - - ``"cluster" : "/home/sqream/sqream_storage"`` - * - ``license_path`` - - ``server`` - - Specifies the license file for this worker - - ✗ - - Valid local system path to license file - - ``"license_path" : "/etc/sqream/license.enc"`` - -.. list-table:: Runtime global flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``spoolMemoryGb`` - - ``runtimeGlobalFlags`` - - Modifies RAM allocated for the worker for intermediate results. Statements that use more memory than this setting will spool to disk, which could degrade performance. We recommend not to exceed the amount of RAM in the machine. This setting must be set lower than the ``limitQueryMemoryGB`` setting. - - ``128`` - - 1 to maximum available RAM in gigabytes. - - ``"spoolMemoryGb": 250`` - * - ``limitQueryMemoryGB`` - - ``runtimeGlobalFlags`` - - Modifies the maximum amount of RAM allocated for a query. The recommended value for this is ``total host memory`` / ``sqreamd workers on host``. For example, for a machine with 512GB of RAM and 4 workers, the recommended setting is ``512/4 → 128``. - - ``10000`` - - ``1`` to ``10000`` - - ``"limitQueryMemoryGB" : 128`` - * - ``cudaMemQuota`` - - ``runtimeGlobalFlags`` - - Modifies the maximum amount of GPU RAM allocated for a worker. The recommended value is 99% for a GPU with a single worker, or 49% for a GPU with two workers. - - ``90`` % - - ``1`` to ``99`` - - ``"cudaMemQuota" : 99`` - * - ``showFullExceptionInfo`` - - ``runtimeGlobalFlags`` - - Shows complete error message with debug information. Use this for debugging. - - ``false`` - - ``true`` or ``false`` - - ``"showFullExceptionInfo" : true`` - * - ``initialSubscribedServices`` - - ``runtimeGlobalFlags`` - - Comma separated list of :ref:`service queues<workload_manager>` that the worker is subscribed to - - ``"sqream"`` - - Comma separated list of service names, with no spaces. Services that don't exist will be created. - - ``"initialSubscribedServices": "sqream,etl,management"`` - * - ``logClientLevel`` - - ``runtimeGlobalFlags`` - - Used to control which log level should appear in the logs - - ``4`` (``INFO``) - - ``0`` SYSTEM (lowest) - ``4`` INFO (highest). See :ref:`information level table<information_level>` for explanation about these log levels. - - ``"logClientLevel" : 3`` - * - ``nodeInfoLoggingSec`` - - ``runtimeGlobalFlags`` - - Sets an interval for automatically logging long-running statements' :ref:`show_node_info` output. Output is written as a message type ``200``. - - ``60`` (every minute) - - Positive whole number >=1. - - ``"nodeInfoLoggingSec" : 5`` - * - ``useLogMaxFileSize`` - - ``runtimeGlobalFlags`` - - Defines whether SQream logs should be cycled when they reach ``logMaxFileSizeMB`` size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. - - ``false`` - - ``false`` or ``true`` - - ``"useLogMaxFileSize" : true`` - * - ``logMaxFileSizeMB`` - - ``runtimeGlobalFlags`` - - Sets the size threshold in megabytes after which a new log file will be opened. - - ``20`` - - ``1`` to ``1024`` (1MB to 1GB) - - ``"logMaxFileSizeMB" : 250`` - * - ``logFileRotateTimeFrequency`` - - ``runtimeGlobalFlags`` - - Control frequency of log rotation - - ``never`` - - ``daily``, ``weekly``, ``monthly``, ``never`` - - ``"logClientLevel" : 3`` - * - ``useMetadataServer`` - - ``runtimeGlobalFlags`` - - Specifies if this worker connects to a cluster (``true``) or is standalone (``false``). If set to ``true``, also set ``metadataServerIp`` - - ``true`` - - ``false`` or ``true`` - - ``"useMetadataServer" : true`` - * - ``metadataServerIp`` - - ``runtimeGlobalFlags`` - - Specifies the hostname or IP of the metadata server, when ``useMetadataServer`` is set to ``true``. - - ``127.0.0.1`` - - A valid IP or hostname - - ``"metadataServerIp": "127.0.0.1"`` - * - ``useConfigIP`` - - ``runtimeGlobalFlags`` - - Specifies if the metadata should use a pre-determined hostname or IP to refer to this worker. If set to ``true``, set the ``machineIp`` configuration accordingly. - - ``false`` - automatically derived by the TCP socket - - ``false`` or ``true`` - - ``"useConfigIP" : true`` - * - ``machineIP`` - - ``runtimeGlobalFlags`` - - Specifies the worker's external IP or hostname, when used from a remote network. - - No default - - A valid IP or hostname - - ``"machineIP": "10.0.1.4"`` - * - ``tempPath`` - - ``runtimeGlobalFlags`` - - Specifies an override for the temporary file path on the local machine. Set this to a local path to improve performance for spooling. - - Defaults to the central storage's built-in temporary folder - - A valid path to a folder on the local machine - - ``"tempPath": "/mnt/nvme0/temp"`` - - - -.. list-table:: Runtime flags - :widths: auto - :header-rows: 1 - - * - Name - - Section - - Description - - Default - - Value range - - Example - * - ``insertParsers`` - - ``runtimeFlags`` - - Sets the number of CSV parsing threads launched during bulk load - - 4 - - 1 to 32 - - ``"insertParsers" : 8`` - * - ``insertCompressors`` - - ``runtimeFlags`` - - Sets the number of compressor threads launched during bulk load - - 4 - - 1 to 32 - - ``"insertCompressors" : 8`` - * - ``statementLockTimeout`` - - ``runtimeGlobalFlags`` - - Sets the delay in seconds before SQream DB will stop waiting for a lock and return an error - - 3 - - >=1 - - ``"statementLockTimeout" : 10`` - - -.. list the main configuration options and how they are used - -.. point to the best practices as well - -.. warning:: JSON files can't contain any comments. - -Recommended Configuration File ------ - -.. code-block:: json - - { - "compileFlags":{ - }, - "runtimeFlags":{ - "insertParsers": 16, - "insertCompressors": 8 - }, - "runtimeGlobalFlags":{ - "limitQueryMemoryGB" : 121, - "spoolMemoryGB" : 108, - "cudaMemQuota": 90, - "initialSubscribedServices" : "sqream", - "useMetadataServer": true, - "metadataServerIp": "127.0.0.1", - "useConfigIP": true, - "machineIP": "127.0.0.1" - }, - "server":{ - "gpu":0, - "port":5000, - "ssl_port": 5100, - "cluster":"/home/sqream/sqream_storage", - "licensePath":"/etc/sqream/license.enc" - } - } \ No newline at end of file diff --git a/configuration_guides/spool_memory_gb.rst b/configuration_guides/spool_memory_gb.rst index 9aa651a74..5ed3264b1 100644 --- a/configuration_guides/spool_memory_gb.rst +++ b/configuration_guides/spool_memory_gb.rst @@ -5,7 +5,6 @@ Setting the Spool Memory ************************* The ``spoolMemoryGB`` flag sets the amount of memory (GB) available to the server for spooling. -The following describes the ``spoolMemoryGB`` flag: * **Data type** - uint * **Default value** - ``8`` \ No newline at end of file diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst index 45c88d3ee..0235b757a 100644 --- a/configuration_guides/spooling.rst +++ b/configuration_guides/spooling.rst @@ -3,16 +3,8 @@ ************************** Configuring the Spooling Feature ************************** -The **Configuring the Spooling Feature** page includes the following topics: -.. contents:: - :local: - :depth: 1 - - -Overview ----------- -From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the ``spoolMemoryGB`` flag. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. +From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. @@ -20,24 +12,10 @@ Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB`` Example Configurations ---------- -The **Example Configurations** section shows the following example configurations: -.. contents:: - :local: - :depth: 1 - -Example 1 - Recommended Settings +Setting Spool Memory ~~~~~~~~~~~ -The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: - -.. code-block:: console - - limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 - spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 - -Example 2 - Setting Spool Memory -~~~~~~~~~~~ -The following is an example of setting ``spoolMemoryGB`` value in the current configuration method per-worker for 512GB of RAM and 4 workers: +The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: .. code-block:: console @@ -54,16 +32,12 @@ The following is an example of setting ``spoolMemoryGB`` value in the current co “spoolMemoryGB" : 108 “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” } - -The following is an example of setting ``spoolMemoryGB`` value in the previous configuration method per-worker for 512GB of RAM and 4 workers: + +Recommended Settings +~~~~~~~~~~~ +The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: .. code-block:: console - “runtimeFlags”: { - “limitQueryMemoryGB” : 121, - “spoolMemoryGB” : 108 - -For more information about configuring the ``spoolMemoryGB`` flag, see the following: - -* `Current configuration method <https://docs.sqream.com/en/latest/configuration_guides/spool_memory_gb.html>`_ -* `Previous configuration method <https://docs.sqream.com/en/latest/configuration_guides/previous_configuration_method.html#id2>`_ \ No newline at end of file + limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 + spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index bc42fcd5d..669e0dbd2 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -3,15 +3,14 @@ ******************** SHUTDOWN SERVER ******************** -The **SHUTDOWN_SERVER** guide describes the following: + + +SQream's method for stopping the SQream server is running the ``shutdown_server()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown by setting it to ``select shutdown_server([is_graceful, [timeout]]);``. This causes the server to wait for any queued statements to complete before shutting down. .. contents:: :local: :depth: 1 -Overview -=============== -SQream's current method for stopping the SQream server is running the ``shutdown_server()`` utility command. Because this command abruptly shuts down the server while executing operations, it has been modified to perform a graceful shutdown by setting it to ``select shutdown_server([is_graceful, [timeout]]);``. This causes the server to wait for any queued statements to complete before shutting down. How Does it Work? ======================== From 8ae2d0b013ff534e64da57558c5ee2301613eb16 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:15:22 +0300 Subject: [PATCH 0578/1892] Update configuration_flags.rst --- configuration_guides/configuration_flags.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configuration_guides/configuration_flags.rst b/configuration_guides/configuration_flags.rst index a61267a6f..d6f5265ce 100644 --- a/configuration_guides/configuration_flags.rst +++ b/configuration_guides/configuration_flags.rst @@ -4,6 +4,8 @@ Configuration Flags ************************* + + .. toctree:: :maxdepth: 1 :glob: From 9a0ef0b92ca8dba8fa96292a17a490a1c0bf93fb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:22:05 +0300 Subject: [PATCH 0579/1892] driver's page --- connecting_to_sqream/client_drivers/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index f8a61d90b..8c404ab06 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -74,10 +74,10 @@ The following are applicable to all operating systems: Windows --------------- +------- The following are applicable to Windows: -* **ODBC installer** - SQream Drivers v2020.2.0. Please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ for this installer. +* For the **ODBC installer**, please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_. For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows <install_odbc_windows>`. @@ -107,4 +107,4 @@ If you couldn't find what you're looking for, contact `SQream Support <https://s .. rubric:: Looking for older drivers? -If you're looking for an older version of SQream DB drivers, versions 1.10 through 2019.2.1 are available at https://sqream.com/product/client-drivers/. \ No newline at end of file +If you're looking for an older version of SQreamDB drivers, visit `here <https://sqream.com/product/client-drivers/>`_. \ No newline at end of file From cccda261203ce356de2b013769c0cf7e7b16ddbc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:39:17 +0300 Subject: [PATCH 0580/1892] Update scalar_sql_udf.rst --- .../user_defined_functions/scalar_sql_udf.rst | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst index de399c3ff..67b23248c 100644 --- a/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst +++ b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst @@ -1,13 +1,12 @@ .. _scalar_sql_udf: Scalar SQL UDF ------------------------ -A **scalar SQL UDF** is a user-defined function that returns a single value, such as the sum of a group of values. Scalar UDFs are different than table-value functions, which return a result set in the form of a table. +============== -This page describes the correct syntax when building simple scalar UDFs and provides three examples. +A **scalar SQL UDF** is a user-defined function that returns a single value, such as the sum of a group of values. Scalar UDFs are different than table-value functions, which return a result set in the form of a table. Syntax -~~~~~~~~~~~~ +------ The following example shows the correct syntax for simple scalar SQL UDF's returning the type name: @@ -28,9 +27,11 @@ The following example shows the correct syntax for simple scalar SQL UDF's retur $ function_body ::= A valid SQL statement Examples -~~~~~~~~~~ -Example 1 – Support for Different Syntax -############ +-------- + +Support for Different Syntax +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Scalar SQL UDF supports standard functionality even when different syntax is used. In the example below, the syntax ``dateadd`` is used instead of ``add_months``, although the function of each is identical. In addition, the operation works correctly even though the order of the expressions in ``add_months`` (``dt``, ``datetime``, and ``n int``) is different than ``MONTH``, ``n``, and ``dt`` in ``dateadd``. @@ -43,8 +44,9 @@ In the example below, the syntax ``dateadd`` is used instead of ``add_months``, $ SELECT dateadd(MONTH ,n,dt) $ $$ LANGUAGE SQL; -Example 2 – Manipulating Strings -############ +Manipulating Strings +~~~~~~~~~~~~~~~~~~~~ + The Scalar SQL UDF can be used to manipulate strings. The following example shows the correct syntax for converting a TEXT date to the DATE type: @@ -57,8 +59,9 @@ The following example shows the correct syntax for converting a TEXT date to the $ select (substring(f,1,4)||'-'||substring(f,5,2)||'-'||substring(f,7,2))::date $ $$ LANGUAGE SQL; -Example 3 – Manually Building Functionality -############ +Manually Building Functionality +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + You can use the Scalar SQL UDF to manually build functionality for otherwise unsupported operations. .. code-block:: console @@ -76,16 +79,13 @@ You can use the Scalar SQL UDF to manually build functionality for otherwise uns $ language sql; Usage Notes -~~~~~~~~~~~~~~ -The following usage notes apply when using simple scalar SQL UDF's: +~~~~~~~~~~~ * During this stage, the SQL embedded in the function body must be of the type ``SELECT expr;``. Creating a UDF with invalid SQL, or with valid SQL of any other type, results in an error. * As with Python UDFs, the argument list can be left empty. -* SQL UDFs can reference other UDF's, including Python UDF's. +* A function cannot (directly or indirectly) reference itself (such as by referencing another function that references it). -**NOTICE:** A function cannot (directly or indirectly) reference itself (such as by referencing another function that references it). - -Because SQL UDF's are one type of supported UDFs, the following Python UDF characteristics apply: +Since SQL UDF's are one type of supported UDFs, the following Python UDF characteristics apply: * UDF permission rules - see `Access Control <https://docs.sqream.com/en/latest/guides/features/access_control.html#access-control>`_. @@ -94,8 +94,7 @@ Because SQL UDF's are one type of supported UDFs, the following Python UDF chara * SQL UDF's should appear in the catalog with Python UDF's - see `Finding Existing UDFs in the Catalog <https://docs.sqream.com/en/latest/guides/features/python_functions.html#finding-existing-udfs-in-the-catalog>`_. Restrictions -~~~~~~~~~~~~~~~~ -The following restrictions apply to simple scalar SQL UDFs: +~~~~~~~~~~~~ * Simple scalar SQL UDF's cannot currently reference other UDFs. * Like Python UDF's, Sqream does not support overloading. From 2ec668056fb5898b01296b57b3de742df5eb6c12 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:54:50 +0300 Subject: [PATCH 0581/1892] Update optimization_best_practices.rst --- operational_guides/optimization_best_practices.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 51982f527..2860b193b 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -195,7 +195,7 @@ Use saved queries to reduce recurring compilation time :ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream DB's metadata for later re-use. -Because the query plan is saved, they can be used to reduce compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. +Saved query plans enable reduced compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. When executed, the saved query plan is recalled and executed on the up-to-date data stored on disk. From 39a612f3415fd08812c9d2a3a2dd4e4c03ec6886 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 10:58:57 +0300 Subject: [PATCH 0582/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 057512968..e727d18d0 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -4,7 +4,7 @@ Monitoring Query Performance ********************************* When analyzing options for query tuning, the first step is to analyze the query plan and execution. -The query plan and execution details explains how SQream DB processes a query and where time is spent. +The query plan and execution details explain how SQream DB processes a query and where time is spent. This document details how to analyze query performance with execution plans. This guide focuses specifically on identifying bottlenecks and possible optimization techniques to improve query performance. Performance tuning options for each query are different. You should adapt the recommendations and tips for your own workloads. From 0cd036e069baffb2682fce2085176d8dfd2025bd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:05:07 +0300 Subject: [PATCH 0583/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index e727d18d0..cca8eb4ea 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -135,7 +135,9 @@ Each row represents a single logical database operation, which is also called a several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 (``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: + .. figure:: /_static/images/show_node_info_graph.png + :height: 70em :align: center From ff54924884ce086844dd198d60d32a4fa3d5a05e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 11:55:42 +0300 Subject: [PATCH 0584/1892] CHR function --- reference/sql/sql_functions/index.rst | 2 + .../scalar_functions/conversion/chr.rst | 50 +++++++++++++++++++ .../sql_functions/scalar_functions/index.rst | 3 +- 3 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 reference/sql/sql_functions/scalar_functions/conversion/chr.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index add12c95d..bcac9819b 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -81,6 +81,8 @@ The following table shows the **conversion** functions: - Converts a number to a hexadecimal string representation * - :ref:`to_unixts` - Converts a ``DATE`` or ``DATETIME`` to a UNIX Timestamp + * - :ref:`chr` + - Returns the ASCII character representation of the supplied integer Date and Time ^^^^^^^^^^^^^^^^ diff --git a/reference/sql/sql_functions/scalar_functions/conversion/chr.rst b/reference/sql/sql_functions/scalar_functions/conversion/chr.rst new file mode 100644 index 000000000..aa52694e1 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/conversion/chr.rst @@ -0,0 +1,50 @@ +.. _chr: + +*** +CHR +*** + +The ``CHR`` function takes an integer parameter representing the ASCII code and returns the corresponding character. + +Syntax +====== + +.. code-block:: postgres + + CHR(n) + +Returns +======= + +Returns the ASCII character representation of the supplied integer. + + +Example +======= + +Create the following table: + +.. code-block:: postgres + + CREATE OR REPLACE TABLE t(x INT NOT NULL); + + INSERT INTO t (x) + VALUES (72), (101), (108), (108), (111); + +Execute the ``CHR`` function: + +.. code-block:: postgres + + SELECT CHR(x) FROM t; + +Output: + +.. code-block:: postgres + + CHR | + ------+ + H | + e | + l | + l | + o | \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index cb749a8b6..94c1db412 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -85,4 +85,5 @@ The **Built-In Scalar Functions** page describes functions that return one value * :ref:`trim` * :ref:`upper` * :ref:`select_ascii` - * :ref:`sign` \ No newline at end of file + * :ref:`sign` + * :ref:`chr` \ No newline at end of file From f7ec880a7b103e7b18db645ecd8153e9fe0efcc1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 12:24:57 +0300 Subject: [PATCH 0585/1892] error_verbosity --- data_ingestion/csv.rst | 1 - .../sql_statements/dml_commands/copy_from.rst | 56 +++++++++---------- 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index afe819fb5..2ee17bc81 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -217,7 +217,6 @@ See :ref:`capturing_rejected_rows` for more information about the error handling COPY table_name FROM 'filename.psv' WITH DELIMITER '|' ERROR_LOG '/temp/load_error.log' -- Save error log - ERROR_VERBOSITY 0; -- Only save rejected rows Stopping the load if a certain amount of rows were rejected diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 05d5083aa..bab998e15 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -87,7 +87,7 @@ Syntax .. _copy_from_config_options: Elements -============ +======== .. list-table:: :widths: auto @@ -254,15 +254,15 @@ Supported Date Formats .. _field_delimiters: Supported Field Delimiters -===================================================== +========================== Field delimiters can be one or more characters. Customizing Quotations Using Alternative Characters ---------------------------- -Syntax Example 1 - Customizing Quotations Using Alternative Characters -************ +Customizing Quotations Using Alternative Characters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is the correct syntax for customizing quotations using alternative characters: @@ -271,8 +271,8 @@ The following is the correct syntax for customizing quotations using alternative copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote='@'); copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote='@'); -Usage Example 1 - Customizing Quotations Using Alternative Characters -************ +Customizing Quotations Using Alternative Characters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is an example of line taken from a CSV when customizing quotations using a character: @@ -281,8 +281,8 @@ The following is an example of line taken from a CSV when customizing quotations Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta -Syntax Example 2 - Customizing Quotations Using ASCII Character Codes -************ +Customizing Quotations Using ASCII Character Codes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is the correct syntax for customizing quotations using ASCII character codes: @@ -291,8 +291,8 @@ The following is the correct syntax for customizing quotations using ASCII chara copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote=E'\064'); copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote=E'\064'); -Usage Example 2 - Customizing Quotations Using ASCII Character Codes -************ +Customizing Quotations Using ASCII Character Codes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is an example of line taken from a CSV when customizing quotations using an ASCII character code: @@ -303,14 +303,14 @@ The following is an example of line taken from a CSV when customizing quotations Multi-Character Delimiters ----------------------------------- +-------------------------- SQream DB supports multi-character field delimiters, sometimes found in non-standard files. A multi-character delimiter can be specified. For example, ``DELIMITER '%%'``, ``DELIMITER '{~}'``, etc. Printable Characters ------------------------ +-------------------- Any printable ASCII character (or characters) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). @@ -319,7 +319,7 @@ A printable character is any ASCII character in the range 32 - 126. :ref:`Literal quoting rules<string_literals>` apply with delimiters. For example, to use ``'`` as a field delimiter, use ``DELIMITER ''''`` Non-Printable Characters ----------------------------- +------------------------ A non-printable character (1 - 31, 127) can be used in its octal form. @@ -370,22 +370,18 @@ The following ASCII field delimiters (octal range 001 - 176) are not supported: Capturing Rejected Rows -========================== +======================= Prior to the column process and storage, the ``COPY`` command parses the data. -Whenever the data can’t be parsed because it is improperly formatted or doesn’t match the data structure, the entire record (or row) will be rejected. - -.. image:: /_static/images/copy_from_rejected_rows.png +Whenever the data can’t be parsed because it is improperly formatted or doesn’t match the data structure, the entire record (or row) will be rejected. +When ``ERROR_LOG`` is not used, the ``COPY`` command will stop and roll back the transaction upon the first error. -#. When ``ERROR_LOG`` is not used, the ``COPY`` command will stop and roll back the transaction upon the first error. - -#. When ``ERROR_LOG`` is set and ``ERROR_VERBOSITY`` is set to ``1`` (default), all errors and rejected rows are saved to the file path specified. +.. image:: /_static/images/copy_from_rejected_rows.png -#. When ``ERROR_LOG`` is set and ``ERROR_VERBOSITY`` is set to ``0``, rejected rows are saved to the file path specified, but errors are not logged. This is useful for replaying the file later. CSV Support -================ +=========== By default, SQream DB's CSV parser can handle `RFC 4180 standard CSVs <https://tools.ietf.org/html/rfc4180>`_ , but can also be modified to support non-standard CSVs (with multi-character delimiters, unquoted fields, etc). @@ -421,10 +417,10 @@ Marking Null Markers .. note:: If a text field is quoted but contains no content (``""``) it is considered an empty text field. It is not considered ``NULL``. Examples -=========== +======== Loading a Standard CSV File ------------------------------- +--------------------------- .. code-block:: postgres @@ -432,7 +428,7 @@ Loading a Standard CSV File Skipping Faulty Rows ------------------------------- +-------------------- .. code-block:: postgres @@ -463,7 +459,7 @@ Loading a Tab Separated Value (TSV) File Loading an ORC File -------------------------------------------- +------------------- .. code-block:: postgres @@ -471,7 +467,7 @@ Loading an ORC File Loading a Parquet File -------------------------------------------- +---------------------- .. code-block:: postgres @@ -479,7 +475,7 @@ Loading a Parquet File Loading a Text File with Non-Printable Delimiters ------------------------------------------------------ +------------------------------------------------- In the file below, the separator is ``DC1``, which is represented by ASCII 17 decimal or 021 octal. @@ -488,7 +484,7 @@ In the file below, the separator is ``DC1``, which is represented by ASCII 17 de COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = E'\021'); Loading a Text File with Multi-Character Delimiters ------------------------------------------------------ +-------------------------------------------------- In the file below, the separator is ``^|``. @@ -504,7 +500,7 @@ In the file below, the separator is ``'|``. The quote character has to be repeat Loading Files with a Header Row ------------------------------------ +------------------------------- Use ``OFFSET`` to skip rows. From 79e8206510e36d28beba32bbf1612e0e95f16e93 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 12:29:44 +0300 Subject: [PATCH 0586/1892] Update csv.rst --- data_ingestion/csv.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 2ee17bc81..77f396ebc 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -192,7 +192,7 @@ Loading a file from a public S3 bucket COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; Loading files from an authenticated S3 bucket ---------------------------------------------------- +--------------------------------------------- .. code-block:: postgres @@ -201,7 +201,7 @@ Loading files from an authenticated S3 bucket .. _hdfs_copy_from_example: Loading files from an HDFS storage ---------------------------------------------------- +---------------------------------- .. code-block:: postgres @@ -220,7 +220,7 @@ See :ref:`capturing_rejected_rows` for more information about the error handling Stopping the load if a certain amount of rows were rejected ------------------------------------------------------------------- +----------------------------------------------------------- .. code-block:: postgres From 8b00d8bc9036ea9080cce43dba35fe37aca59104 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:18:10 +0300 Subject: [PATCH 0587/1892] error_verbosity --- data_ingestion/csv.rst | 26 +++++++++++-------- .../scalar_functions/string/substring.rst | 6 ++--- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 77f396ebc..db63a38ca 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -46,7 +46,7 @@ Prepare the source CSVs, with the following requirements: Place CSVs where SQream DB workers can access -======================================================= +============================================= During data load, the :ref:`copy_from` command can run on any worker (unless explicitly speficied with the :ref:`workload_manager`). It is important that every node has the same view of the storage being used - meaning, every SQream DB worker should have access to the files. @@ -58,7 +58,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. Figure out the table structure -=============================================== +============================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -97,7 +97,7 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st Bulk load the data with COPY FROM -==================================== +================================= The CSV is a standard CSV, but with two differences from SQream DB defaults: @@ -117,13 +117,13 @@ Repeat steps 3 and 4 for every CSV file you want to import. Loading different types of CSV files -======================================= +==================================== :ref:`copy_from` contains several configuration options. See more in :ref:`the COPY FROM elements section<copy_from_config_options>`. Loading a standard CSV file from a local filesystem ---------------------------------------------------------- +--------------------------------------------------- .. code-block:: postgres @@ -215,8 +215,12 @@ See :ref:`capturing_rejected_rows` for more information about the error handling .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' - ERROR_LOG '/temp/load_error.log' -- Save error log + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv' + ,delimiter = '|' + ,continue_on_error = True + ,error_log = '/temp/load_error.log' -- Save error log + ,rejected_data = '/temp/load_rejected.log' -- Only save rejected rows + ); Stopping the load if a certain amount of rows were rejected @@ -225,10 +229,10 @@ Stopping the load if a certain amount of rows were rejected .. code-block:: postgres COPY table_name FROM 'filename.csv' WITH delimiter '|' - ERROR_LOG '/temp/load_err.log' -- Save error log - OFFSET 2 -- skip header row - LIMIT 100 -- Only load 100 rows - STOP AFTER 5 ERRORS; -- Stop the load if 5 errors reached + ERROR_LOG '/temp/load_err.log' -- Save error log + OFFSET 2 -- skip header row + LIMIT 100 -- Only load 100 rows + STOP AFTER 5 ERRORS; -- Stop the load if 5 errors reached Load CSV files from a set of directories ------------------------------------------ diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index 6e6359167..f08656a02 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -27,11 +27,11 @@ Arguments * - Parameter - Description * - ``expr`` - - String expression + - Original string expression from which you want to extract the substring * - ``start_pos`` - - Starting position (starts at 1) + - Starting position within the string where the extraction should start (starts at 1) * - ``length`` - - Number of characters to extract + - Number of characters to be extracted from the string Returns ============ From 553590c347d40e55cfd08f9e978ef023478a01c4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:35:13 +0300 Subject: [PATCH 0588/1892] Update substring.rst --- .../scalar_functions/string/substring.rst | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index f08656a02..205e83d5d 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -1,8 +1,8 @@ .. _substring: -************************** +********* SUBSTRING -************************** +********* Returns a substring of the input starting at ``start_pos``. @@ -11,14 +11,14 @@ Returns a substring of the input starting at ``start_pos``. See also :ref:`regexp_substr`. Syntax -========== +====== .. code-block:: postgres SUBSTRING( expr, start_pos, length ) Arguments -============ +========= .. list-table:: :widths: auto @@ -29,24 +29,25 @@ Arguments * - ``expr`` - Original string expression from which you want to extract the substring * - ``start_pos`` - - Starting position within the string where the extraction should start (starts at 1) + - The start parameter, which accepts an integer or bigint expression, indicates the position from which the returned characters begin. If start is less than 1, the expression starts from the first character. The number of characters returned is determined by the larger value between start + length - 1 and 0. If start exceeds the number of characters in the expression, an empty string is returned * - ``length`` - - Number of characters to be extracted from the string + - A positive integer or bigint expression that specifies the number of characters to be returned from the expression. If the sum of start and length exceeds the total number of characters in the expression, the entire value starting from the position specified by start is returned. If length is negative or zero, the function returns an empty string Returns -============ +======= + +* Returns the same type as the argument supplied -Returns the same type as the argument supplied. +* If any of the arguments is NULL, the return is NULL Notes -======= +===== * Character count starts at 1. -* If the value is NULL, the result is NULL. Examples -=========== +======== For these examples, assume a table named ``nba``, with the following structure: From eb1b2311de499f9511e936f14c6977f4c62e26ac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Jun 2023 09:32:29 +0300 Subject: [PATCH 0589/1892] Services --- feature_guides/workload_manager.rst | 12 ++++-------- ...oring_workers_and_services_from_the_dashboard.rst | 6 +++--- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/feature_guides/workload_manager.rst b/feature_guides/workload_manager.rst index aece3d11f..9cf582dde 100644 --- a/feature_guides/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -4,15 +4,11 @@ Workload Manager *********************** -The **Workload Manager** allows SQream workers to identify their availability to clients with specific service names. The load balancer uses that information to route statements to specific workers. - -Overview -=============================== -The Workload Manager allows a system engineer or database administrator to allocate specific workers and compute resources for various tasks. +The Workload Manager enables SQream workers to identify their availability to clients with specific service names, allowing a system engineer or database administrator to allocate specific workers and compute resources for various tasks. The load balancer then uses this information to route statements to the designated workers. For example: -#. Creating a service queue named ``ETL`` and allocating two workers exclusively to this service prevents non-``ETL`` statements from utilizing these compute resources. +#. Creating a service queue named ``ETL`` and allocating two workers exclusively to this service prevents non-``ETL`` statements from using these compute resources. #. Creating a service for the company's leadership during working hours for dedicated access, and disabling this service at night to allow maintenance operations to use the available compute. @@ -115,7 +111,7 @@ Each worker gets a comma-separated list of service queues that it subscribes to. Verifying the Configuration ----------------------------------- -Use :ref:`show_subscribed_instances` to view service subscriptions for each worker. Use `SHOW_SERVER_STATUS <https://docs.sqream.com/en/v2020.3/reference/sql/sql_statements/monitoring_commands/show_server_status.html>`_ to see the statement queues. +Use :ref:`show_subscribed_instances` to view service subscriptions for each worker. Use :ref:`SHOW_SERVER_STATUS<show_server_status>` to see the statement queues. @@ -151,7 +147,7 @@ When using **SQream Studio**, you can configure a client connection to a specifi -For more information, in Studio, see `Executing Statements from the Toolbar <https://docs.sqream.com/en/v2020.3/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.html#executing-statements-from-the-toolbar>`_. +For more information, in Studio, see :ref:`Executing Statements from the Toolbar<executing_statements_and_running_queries_from_the_editor>`. diff --git a/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst index 4283f64a8..b24736945 100644 --- a/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst @@ -47,7 +47,7 @@ The following is a brief description of the Dashboard panels: Subscribing to Workers from the Services Panel -------------------------- -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined `service queues <https://docs.sqream.com/en/v2020.3/feature_guides/workload_manager.html>`_. +Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined :ref:`service queues<workload_manager>`. @@ -79,7 +79,7 @@ You can add a service by clicking **+ Add** and defining the service name. You can manage workers from the **Workers** panel. For more information about managing workers, see the following: * :ref:`Managing Workers from the Workers Panel<workers_panel_>` -* `Workers <https://docs.sqream.com/en/v2020-2/reference/cli/sqream_console.html?highlight=workers#workers>`_ +* :ref:`Workers<sqream_console_cli_reference>` :ref:`Back to Monitoring Workers and Services from the Dashboard<back_to_dashboard_>` @@ -151,7 +151,7 @@ Clicking the ellipsis in a service shows the following additional options: * **Stop Query** - stops the query. * **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. -For more information on the current query plan, see `SHOW_NODE_INFO <https://docs.sqream.com/en/v2020-2/reference/sql/sql_statements/monitoring_commands/show_node_info.html#show-node-info>`_. For more information on checking active sessions across the cluster, see `SHOW_SERVER_STATUS <https://docs.sqream.com/en/v2020-2/reference/sql/sql_statements/monitoring_commands/show_server_status.html>`_. +For more information on the current query plan, see :ref:`SHOW_NODE_INFO<show_node_info>`. For more information on checking active sessions across the cluster, see :ref:`SHOW_SERVER_STATUS<show_server_status>`. .. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst :start-line: 67 From d826517e4413a2b9c9e46599404e945efd22ed74 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Jun 2023 10:50:21 +0300 Subject: [PATCH 0590/1892] Services --- connecting_to_sqream/client_drivers/index.rst | 2 +- operational_guides/access_control_permissions.rst | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 8c404ab06..dbbd33933 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -31,7 +31,7 @@ The following are applicable to all operating systems: * **Trino**: - * `Trino Connector <>`_ + * Trino Connector * :ref:`trino` .. _spark: diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 15b41182c..bbb3ba4b2 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -132,8 +132,8 @@ GRANT Syntax TO <role> [, ...]; -- Grant permissions at the Service level: - GRANT {{USAGE} [, ...] | ALL [PERMISSIONS]} - ON { SERVICE <service_name> [, ...] | ALL SERVICES IN SYSTEM } + GRANT {{USAGE} [PERMISSIONS]} + ON { SERVICE <service_name> } TO <role> [, ...] -- Allows role2 to use permissions granted to role1 @@ -179,10 +179,11 @@ REVOKE Syntax REVOKE {{SELECT | DDL } [, ...] | ALL [PERMISSIONS]} ON { COLUMN <column_name> [, ...] | ALL COLUMNS IN TABLE <table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] | ALL COLUMNS IN VIEW <view_name> [, ...] | ALL COLUMNS IN CATALOG <catalog_name> [, ...]} FROM <role> [, ...]; + - -- Revoke permissions at the column level: + -- Revoke permissions at the service level: REVOKE {{USAGE} [, ...] | ALL [PERMISSIONS]} - ON { SERVICE <service_name> [, ...] | ALL SERVICES IN SYSTEM} + ON { SERVICE <service_name> } FROM <role> [, ...] -- Removes access to permissions in role1 by role 2 From c97cd5a1b8d345ca4d745a5d18337355ce14cabd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:02:51 +0300 Subject: [PATCH 0591/1892] =?UTF-8?q?GRANT=5FUSAGE=5FON=5FSERVICE=5FTO=5FA?= =?UTF-8?q?LL=5FROLES=EF=83=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../grant_usage_on_service_to_all_roles.rst | 74 +++++++++++++++++++ reference/sql/sql_statements/index.rst | 12 +-- .../get_role_database_ddl.rst | 23 +++--- ...ing_and_managing_roles_and_permissions.rst | 8 +- 4 files changed, 92 insertions(+), 25 deletions(-) create mode 100644 reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst diff --git a/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst b/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst new file mode 100644 index 000000000..2c0f1d338 --- /dev/null +++ b/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst @@ -0,0 +1,74 @@ +.. _grant_usage_on_service_to_all_roles: + +*********************************** +GRANT_USAGE_ON_SERVICE_TO_ALL_ROLES +*********************************** + +The ``grant_usage_on_service_to_all_roles`` utility function enables a ``SUPERUSER`` to grant access to services for other system roles. + +You may use it to perform one of the following options: + +* Granting access to all services for all roles +* Granting access to a specific service for all roles + + +This utility function is particularly beneficial during the upgrade process from SQreamDB version 4.2 or earlier to version 4.3 or later. In previous versions, service access permissions were not required. In this scenario, you can easily grant access to all services for all roles immediately after the upgrade. If you are already using SQreamDB version 4.3 or later, you can grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>`. + +.. note:: + + When you create a new role, it automatically inherits access permissions to all services from the ``PUBLIC`` role. If you prefer to create new roles without automatically granting them access permissions to all services, you will need to follow the :ref:`ALTER DEFAULT PERMISSIONS<alter_default_permissions>` guide to revoke the access permissions of the ``PUBLIC`` role. + +Syntax +====== + +.. code-block:: psql + + SELECT grant_usage_on_service_to_all_roles (<'single service'>) + + +Examples +======== +Granting access to all services for all roles: + +.. code-block:: psql + + SELECT grant_usage_on_service_to_all_roles(); + +Output: + +.. code-block:: + + role_name | service_name | status + ----------+---------------+-------------------- + role1 | service1 | Permission Granted + role1 | service2 | Permission Granted + role1 | service3 | Permission Granted + role2 | service1 | Permission Granted + role2 | service2 | Permission Granted + role2 | service3 | Permission Granted + role3 | service1 | Permission Exists + role3 | service2 | Permission Exists + role3 | service3 | Permission Exists + +Granting access to one specific service for all roles: + +.. code-block:: psql + + SELECT grant_usage_on_service_to_all_roles('service1'); + +Output: + +.. code-block:: + + role_name | service_name | status + ----------+---------------+-------------------- + role1 | service1 | Permission Granted + role2 | service1 | Permission Granted + role3 | service1 | Permission Exists + + +Permissions +=========== + +Using the ``grant_usage_on_service_to_all_roles`` requires ``SUPERUSER`` permission. + diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 7044b3a80..f8c6c4332 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -18,7 +18,7 @@ Data Definition Commands (DDL) The following table shows the Data Definition commands: .. list-table:: - :widths: 10 100 + :widths: 30 100 :header-rows: 1 :name: ddl_commands @@ -71,7 +71,7 @@ Data Manipulation Commands (DML) The following table shows the Data Manipulation commands: .. list-table:: - :widths: 10 100 + :widths: 30 100 :header-rows: 1 :name: dml_commands @@ -101,7 +101,7 @@ Utility Commands The following table shows the Utility commands: .. list-table:: - :widths: 10 100 + :widths: 30 100 :header-rows: 1 * - Command @@ -162,7 +162,7 @@ Workload Management The following table shows the Workload Management commands: .. list-table:: - :widths: 10 100 + :widths: 30 100 :header-rows: 1 * - Command @@ -179,7 +179,7 @@ Access Control Commands The following table shows the Access Control commands: .. list-table:: - :widths: 10 100 + :widths: 30 100 :header-rows: 1 * - Command @@ -206,6 +206,8 @@ The following table shows the Access Control commands: - Returns a list of permissions required to run a statement or query * - :ref:`grant` - Grant permissions to a role + * - :ref:`GRANT_USAGE_ON_SERVICE_TO_ALL_ROLES` + - Grant service usage permissions * - :ref:`revoke` - Revoke permissions from a role * - :ref:`rename_role` diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index 5ff3ecf79..ed7adfcf5 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -5,11 +5,7 @@ GET_ROLE_DATABASE_DDL ******************** The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a role's database in DDL format. -The ``GET_ROLE_DATABASE_DDL`` page describes the following: - -.. contents:: - :local: - :depth: 1 +The ``GET_ROLE_DATABASE_DDL`` page describes the following: Syntax ========== @@ -19,14 +15,6 @@ The following is the correct syntax for using the ``GET_ROLE_DATABASE_DDL`` stat select get_role_database_ddl(<'role_name'>) -Example -=========== -The following is an example of using the ``GET_ROLE_DATABASE_DDL`` statement: - -.. code-block:: psql - - select get_role_database_ddl('public'); - Parameters ============ The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: @@ -39,6 +27,15 @@ The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: - Description * - ``role_name`` - The definition of the database role in DDL format. + +Example +=========== +The following is an example of using the ``GET_ROLE_DATABASE_DDL`` statement: + +.. code-block:: psql + + select get_role_database_ddl('public'); + Output ========== diff --git a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst index 648117ca7..6f0e43ef3 100644 --- a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst @@ -5,14 +5,8 @@ **************************** Creating, Assigning, and Managing Roles and Permissions **************************** -The **Creating, Assigning, and Managing Roles and Permissions** describes the following: -.. contents:: - :local: - :depth: 1 - -Overview ---------------- + In the **Roles** area you can create and assign roles and manage user permissions. The **Type** column displays one of the following assigned role types: From 080fd343b23525515185583829d1fc34012f874f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:37:49 +0300 Subject: [PATCH 0592/1892] Update 4.3.rst --- releases/4.3.rst | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 0eaccf68e..749de6cba 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -90,13 +90,14 @@ Version 4.3 resolved Issues Configuration Adjustments ------------------------- -When using SQreamDB legacy configuration file and AWS S3, you may be required to use the following new parameters: +► You may now configure the object access style and your endpoint URL with Virtual Private Cloud (VPC) when using AWS S3. + +Visit :ref:`s3` to learn more about how and when you should use these two new parameters: * ``AwsEndpointOverride`` * ``AwsObjectAccessStyle`` -To learn more about how and when you should use them, visit :ref:`s3`. - +► Upgrading from SQreamDB version 4.2 to 4.3 requires you to grant access to all services for all roles. To learn more, visit :ref:`grant_usage_on_service_to_all_roles`. Deprecated Features ------------------- @@ -152,6 +153,14 @@ Upgrading to v4.3 .. code-block:: console $ ./upgrade_storage <levelDB path> + + :: + +7. To grant access to all services for all roles, run the following command: + + .. code-block:: psql + + SELECT grant_usage_on_service_to_all_roles(); .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From 22b97d640ec0de1f9ff689b0a012250fcb117584 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Jun 2023 16:45:34 +0300 Subject: [PATCH 0593/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index ace6734cf..bc6276019 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -165,7 +165,7 @@ This section describes the following cluster design considerations: :: -* When using SAN or NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. +* When using NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. Balancing Cost and Performance -------------------------------- @@ -221,7 +221,7 @@ SQream can run on the following 64-bit Linux operating systems: Storage ----------- -For clustered scale-out installations, SQream relies on NAS/SAN storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. +For clustered scale-out installations, SQream relies on NAS storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. From 371e9bafc524c32b17b9d0398fea112ce933d4b2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Jun 2023 14:05:08 +0300 Subject: [PATCH 0594/1892] ASCII --- reference/sql/sql_functions/index.rst | 2 +- .../scalar_functions/string/select_ascii.rst | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index bcac9819b..30495bd6a 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -270,7 +270,7 @@ The following table shows the **string** functions: * - :ref:`upper` - Converts an argument to an upper-case equivalent * - :ref:`select_ascii` - - Return the ASCII code value of the leftmost character of a string + - Returns an ``INT`` value representing the ASCII code of the leftmost character in a string User-Defined Scalar Functions --------------------- diff --git a/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst index 562a7e355..2792e4b67 100644 --- a/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/string/select_ascii.rst @@ -1,22 +1,22 @@ .. _select_ascii: -******************** -SELECT ASCII -******************** -The **SELECT ASCII** function is commonly used in combination with other SQL functions for operations such as data transformation, validation, and storing based on ASCII values. +***** +ASCII +***** +The **ASCII** function is commonly used in combination with other SQL functions for operations such as data transformation, validation, and storing based on ASCII values. Syntax -========== +====== The following shows the syntax for the SELECT ASCII function: .. code-block:: postgres - SELECT ASCII(''); + ASCII() -Returns -========= +Return +====== -The SELECT ASCII function returns the ASCII code value of the leftmost character of a string. +The function returns an 'INT' value representing the ASCII code of the leftmost character in a string. Example =========== From c4e84a7744bc9ca7c59e06418a7a0af4096b484b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Jun 2023 15:16:52 +0300 Subject: [PATCH 0595/1892] Update to_hex.rst --- .../scalar_functions/conversion/to_hex.rst | 55 +++++++++++++++---- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst index d33643f22..2885a605f 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst @@ -7,14 +7,14 @@ TO_HEX Converts an integer to a hexadecimal representation. Syntax -========== +====== .. code-block:: postgres TO_HEX( expr ) --> TEXT Arguments -============ +========= .. list-table:: :widths: auto @@ -23,32 +23,35 @@ Arguments * - Parameter - Description * - ``expr`` - - An integer expression + - This function accepts ``INT`` and ``BIGINT`` expressions Returns -============ - -* Representation of the hexadecimal number of type ``TEXT``. +======= +If the input number is of type ``INT``, the return string will be 10 characters long (8 characters for the digits and 2 characters for the "0x" prefix). If the input number is of type ``BIGINT``, the return string will be 18 characters long (16 characters for the digits and 2 characters for the "0x" prefix). Examples -=========== +======== -For these examples, consider the following table and contents: +``BIGINT`` data type +-------------------- .. code-block:: postgres CREATE TABLE cool_numbers(number BIGINT NOT NULL); + +.. code-block:: postgres INSERT INTO cool_numbers VALUES (42), (3735928559), (666), (3135097598), (3221229823); +.. code-block:: postgres -Convert numbers to hexadecimal -------------------------------------- + SELECT TO_HEX(number) FROM cool_numbers; + +Output: -.. code-block:: psql +.. code-block:: none - master=> SELECT TO_HEX(number) FROM cool_numbers; to_hex ------------------ 0x000000000000002a @@ -56,3 +59,31 @@ Convert numbers to hexadecimal 0x000000000000029a 0x00000000baddcafe 0x00000000c00010ff + + +``INT`` data type +----------------- + +.. code-block:: postgres + + CREATE TABLE cool_numbers(number INT NOT NULL); + +.. code-block:: postgres + + INSERT INTO cool_numbers VALUES (42), (373592855), (666), (313509759), (322122982); + +.. code-block:: postgres + + SELECT TO_HEX(number) FROM cool_numbers; + +Output: + +.. code-block:: none + + to_hex + ------------------ + 0x0000002a + 0x16449317 + 0x0000029a + 0x12afc77f + 0x133334e6 \ No newline at end of file From deacf02edaf59b2e751d57dc6fd3ccc87a75913b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Jun 2023 15:23:28 +0300 Subject: [PATCH 0596/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index bbb3ba4b2..276b969c5 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -143,7 +143,7 @@ GRANT Syntax -- Also allows the role2 to grant role1 to other roles: GRANT <role1> [, ...] TO <role2> - WITH ADMIN OPTION + REVOKE Syntax ============= @@ -187,10 +187,10 @@ REVOKE Syntax FROM <role> [, ...] -- Removes access to permissions in role1 by role 2 - REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION + REVOKE <role1> [, ...] FROM <role2> [, ...] -- Removes permissions to grant role1 to additional roles from role2 - REVOKE <role1> [, ...] FROM <role2> [, ...] WITH ADMIN OPTION + REVOKE <role1> [, ...] FROM <role2> [, ...] Altering Default Permissions ============================ From 76ce16a6e749fe8b1cfa56dc59a69fb4f9c8b869 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 8 Jun 2023 17:39:04 +0300 Subject: [PATCH 0597/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index bc6276019..61d1aae50 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -225,6 +225,5 @@ For clustered scale-out installations, SQream relies on NAS storage. For stand-a SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. -Download the full `SQream Reference Architecture <https://sqream.com/product/hardware/#download>`_ document. .. note:: Non production HW requirements may be found at `Non Production HW Requirements <non_production_hardware_guide.html>`_ \ No newline at end of file From 97e06700ab301bbbbb5e2e4343208fb91e2ab7a1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 07:59:36 +0300 Subject: [PATCH 0598/1892] 4.3 date update --- releases/4.3.rst | 2 +- releases/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 749de6cba..a8dc5421e 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -4,7 +4,7 @@ Release Notes 4.3 ***************** -The 4.3 release notes were released on xx/06/2023 and describe the following: +The 4.3 release notes were released on 11/06/2023 and describe the following: .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index b02e21ff9..241381e3b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -13,7 +13,7 @@ Release Notes * - Version - Release Date * - :ref:`4.3` - - May 31, 2023 + - June 11, 2023 * - :ref:`4.2` - April 23, 2023 * - :ref:`4.1` From d73a1e945bd6a5532af2a0df0f56618aa8fd1439 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 08:10:56 +0300 Subject: [PATCH 0599/1892] Update 4.3.rst --- releases/4.3.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index a8dc5421e..29d06176c 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -156,11 +156,8 @@ Upgrading to v4.3 :: -7. To grant access to all services for all roles, run the following command: +7. v4.3 introduced a new SERVICE permission, existing users may lose SERVICE access. To resolve, either grant users with SERVICE USAGE permission or grant access to all services for all roles using :ref:`grant-usage-on-service-to-all-roles`. - .. code-block:: psql - - SELECT grant_usage_on_service_to_all_roles(); .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From 38044d00ac546496fbebe2393aaddef0124b4dc6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 08:20:15 +0300 Subject: [PATCH 0600/1892] Update 4.3.rst --- releases/4.3.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 29d06176c..b36a9c93a 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -97,8 +97,6 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa * ``AwsEndpointOverride`` * ``AwsObjectAccessStyle`` -► Upgrading from SQreamDB version 4.2 to 4.3 requires you to grant access to all services for all roles. To learn more, visit :ref:`grant_usage_on_service_to_all_roles`. - Deprecated Features ------------------- @@ -156,7 +154,7 @@ Upgrading to v4.3 :: -7. v4.3 introduced a new SERVICE permission, existing users may lose SERVICE access. To resolve, either grant users with SERVICE USAGE permission or grant access to all services for all roles using :ref:`grant-usage-on-service-to-all-roles`. +7. v4.3 introduced a new SERVICE permission, existing users may lose SERVICE access. To resolve, either grant users with SERVICE USAGE permission or grant access to all services for all roles using :ref:`grant_usage_on_service_to_all_roles`. .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From c016581b40d1ce60e6070225a545ccdbad8df153 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 08:29:02 +0300 Subject: [PATCH 0601/1892] Create .readthedocs.yaml --- .readthedocs.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .readthedocs.yaml diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 000000000..a330e260d --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,23 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: conf.py + +# We recommend specifying your dependencies to enable reproducible builds: +# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html +# python: + install: + requirements: requirements.txt + \ No newline at end of file From c619ae9de6b5a61a0c6c9aab98dafe959b5dffce Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 08:35:44 +0300 Subject: [PATCH 0602/1892] gg --- .readthedocs.yaml | 20 +++++++++++++------- conf.py | 2 +- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index a330e260d..eeec35071 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -10,14 +10,20 @@ build: os: ubuntu-22.04 tools: python: "3.11" + # You can also specify other tool versions: + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" # Build documentation in the docs/ directory with Sphinx sphinx: - configuration: conf.py + configuration: conf.py -# We recommend specifying your dependencies to enable reproducible builds: -# https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html -# python: - install: - requirements: requirements.txt - \ No newline at end of file +# If using Sphinx, optionally build your docs in additional formats such as PDF +# formats: +# - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: requirements.txt \ No newline at end of file diff --git a/conf.py b/conf.py index bee87ebd0..4cefff76e 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '4.2' +release = '4.3' From 4af89163812c1802695e46d23122c6cef83ea269 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 Jun 2023 12:04:19 +0300 Subject: [PATCH 0603/1892] Update 4.3.rst --- releases/4.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index b36a9c93a..3071e083a 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -21,7 +21,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 46 | +| Storage version | 49 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 4.5.8 | | | * ODBC 4.4.4 | From 3e0b974728b481fe22410fc01c6909ba4b8e0392 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 06:32:45 +0300 Subject: [PATCH 0604/1892] Update .readthedocs.yaml Enable PDF download --- .readthedocs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index eeec35071..3475abda8 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,8 +20,8 @@ sphinx: configuration: conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF -# formats: -# - pdf + formats: + - pdf # Optionally declare the Python requirements required to build your docs python: From 468f43a5fe53deb5294e97c2f75c6269197d02f9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 06:35:29 +0300 Subject: [PATCH 0605/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 3475abda8..88fe3c408 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,9 +20,8 @@ sphinx: configuration: conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF - formats: - - pdf - +formats: pdf + # Optionally declare the Python requirements required to build your docs python: install: From d42050b03295e222b8974e65640c0b9bf3c0878e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 06:36:42 +0300 Subject: [PATCH 0606/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 88fe3c408..49e20dbc4 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,7 +20,7 @@ sphinx: configuration: conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF -formats: pdf +formats: [pdf] # Optionally declare the Python requirements required to build your docs python: From 06d9deeebb8abe771e57b38169913653207e77e4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 06:41:56 +0300 Subject: [PATCH 0607/1892] Update requirements.txt --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a4fb056dd..8f42b94c9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,5 @@ sphinx_rtd_theme==1.2.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page -Pygments>=2.4.0 \ No newline at end of file +Pygments>=2.4.0 +pdftex>=1.0.0 \ No newline at end of file From f2678cee38d6ba58c7b44e5308e9289cf0ed02fa Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 06:52:56 +0300 Subject: [PATCH 0608/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8f42b94c9..a8c8329d7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,4 @@ urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page Pygments>=2.4.0 -pdftex>=1.0.0 \ No newline at end of file +pdftex \ No newline at end of file From 35ff00b314e75d74cfe975c620e234d60f4580d3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:03:37 +0300 Subject: [PATCH 0609/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 49e20dbc4..139a8d030 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -20,9 +20,16 @@ sphinx: configuration: conf.py # If using Sphinx, optionally build your docs in additional formats such as PDF -formats: [pdf] +formats: [htmlzip,pdf] # Optionally declare the Python requirements required to build your docs python: install: - - requirements: requirements.txt \ No newline at end of file + - requirements: requirements.txt + - method: pip + path: . + extra_requirements: + - docs + - method: pip + path: another/package + system_packages: true \ No newline at end of file From 78869344d64b21ac1ccd8d263c45fac3fc465009 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:06:22 +0300 Subject: [PATCH 0610/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 139a8d030..8ebde2625 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -27,9 +27,4 @@ python: install: - requirements: requirements.txt - method: pip - path: . - extra_requirements: - - docs - - method: pip - path: another/package - system_packages: true \ No newline at end of file +system_packages: true \ No newline at end of file From 7f82277e6220da2d66a51a8982bd8cef1f0c06e7 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:07:30 +0300 Subject: [PATCH 0611/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 8ebde2625..b95f412b9 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -26,5 +26,4 @@ formats: [htmlzip,pdf] python: install: - requirements: requirements.txt - - method: pip system_packages: true \ No newline at end of file From 08fc11048524bf6f313633e85ae6683dc98945eb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 Jun 2023 07:08:03 +0300 Subject: [PATCH 0612/1892] Update .readthedocs.yaml --- .readthedocs.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index b95f412b9..77b6f73c2 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -25,5 +25,4 @@ formats: [htmlzip,pdf] # Optionally declare the Python requirements required to build your docs python: install: - - requirements: requirements.txt -system_packages: true \ No newline at end of file + - requirements: requirements.txt \ No newline at end of file From ae8317c50eab1bafe871817dd7de74f7deaeb4de Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 08:37:25 +0300 Subject: [PATCH 0613/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index bab998e15..91c32cd01 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -105,7 +105,7 @@ Elements - " - - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in **COPY FROM** and foreign tables. - * - ``name_fdw`` + * - ``fdw_name`` - - ``csv_fdw``, ``orc_fdw``, or ``parquet_fdw`` - The name of the Foreign Data Wrapper to use From 35acc01d826dd55662cb774a5c149221a958a4f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 09:11:18 +0300 Subject: [PATCH 0614/1892] Update regexp_replace.rst --- .../string/regexp_replace.rst | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index ba3424190..aa8724d47 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -7,16 +7,15 @@ The ``REGEXP_REPLACE`` function finds and replaces text column substrings using For related information, see the following: -* `REGEXP_COUNT <https://docs.sqream.com/en/latest/reference/sql/sql_functions/scalar_functions/string/regexp_count.html>`_ -* `REGEXP_INSTR <https://docs.sqream.com/en/latest/reference/sql/sql_functions/scalar_functions/string/regexp_instr.html>`_ -* `REGEXP_SUBSTR <https://docs.sqream.com/en/latest/reference/sql/sql_functions/scalar_functions/string/regexp_substr.html>`_ +* :ref:`REGEXP_COUNT<regexp_count>` +* :ref:`REGEXP_INSTR<regexp_instr>` +* :ref:`REGEXP_SUBSTR<regexp_substr>` Syntax --------------- -The following is a syntactic example of the ``REGEXP_REPLACE`` function: +------ .. code-block:: postgres @@ -92,15 +91,15 @@ The following table shows the ``REGEXP_REPLACE`` test patterns: Any character that does not have a defined special meaning inside a [] pair matches only itself. Returns ------------- +------- The ``REGEXP_REPLACE`` function returns the replaced input value. Notes --------------- +----- The test pattern must be a literal string. Example --------------- +------- The following is an example of the ``REGEXP_REPLACE`` function: .. code-block:: @@ -109,8 +108,12 @@ The following is an example of the ``REGEXP_REPLACE`` function: INSERT INTO test values('SWEDEN'); SELECT REGEXP_REPLACE(country_name, 'WEDE', 'PAI') FROM test; - SELECT * FROM test; +Output: + +.. code-block:: none -The output generated from the example above is ``SPAIN``. + country_name| + ------------+ + SPAIN | From ea15a809871bc99d58fef533c0c1784bf8815e54 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 09:12:18 +0300 Subject: [PATCH 0615/1892] Update regexp_replace.rst --- .../sql_functions/scalar_functions/string/regexp_replace.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index aa8724d47..dcf0f85ce 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -43,8 +43,7 @@ The following table shows the ``REGEXP_REPLACE`` arguments: - (Optional) Sets a specific occurrence to replace. Using ``0`` replaces all occurrences. Test Patterns --------------- -The following table shows the ``REGEXP_REPLACE`` test patterns: +------------- .. list-table:: :widths: auto From c6361746ee08f99dfa311259d0f35f6afb11af24 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:38:29 +0300 Subject: [PATCH 0616/1892] Update 4.3.rst --- releases/4.3.rst | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 3071e083a..1995e7fd8 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: +► Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: * VIEWS * FOREIGN TABLE @@ -44,6 +44,8 @@ Access control permissions in SQreamDB have been expanded, allowing roles to now To learn more about how and when you should use this new capability, visit :ref:`access_control_permissions`. +► RocksDB's metadata scale-up improvements have been implemented. + Known Issues ------------ @@ -132,29 +134,24 @@ Upgrading to v4.3 2. Shut down all SQream services. - :: - 3. Copy the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console $ ./upgrade_storage <levelDB path> - :: - -7. v4.3 introduced a new SERVICE permission, existing users may lose SERVICE access. To resolve, either grant users with SERVICE USAGE permission or grant access to all services for all roles using :ref:`grant_usage_on_service_to_all_roles`. +7. Version 4.3 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.3 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From 95096674d32a8b27928143bb6fa2ec27ea724ca7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 11:00:42 +0300 Subject: [PATCH 0617/1892] Update to_hex.rst --- .../scalar_functions/conversion/to_hex.rst | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst index 2885a605f..68c695f09 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/to_hex.rst @@ -42,7 +42,7 @@ Examples .. code-block:: postgres - INSERT INTO cool_numbers VALUES (42), (3735928559), (666), (3135097598), (3221229823); + INSERT INTO cool_numbers VALUES (-42), (3735928559), (666), (3135097598), (3221229823); .. code-block:: postgres @@ -52,13 +52,13 @@ Output: .. code-block:: none - to_hex - ------------------ - 0x000000000000002a - 0x00000000deadbeef - 0x000000000000029a - 0x00000000baddcafe - 0x00000000c00010ff + to_hex + ------------------ + 0xffffffffffffffd6 + 0x00000000deadbeef + 0x000000000000029a + 0x00000000baddcafe + 0x00000000c00010ff ``INT`` data type @@ -70,7 +70,7 @@ Output: .. code-block:: postgres - INSERT INTO cool_numbers VALUES (42), (373592855), (666), (313509759), (322122982); + INSERT INTO cool_numbers VALUES (-42), (373592855), (666), (313509759), (322122982); .. code-block:: postgres @@ -80,10 +80,10 @@ Output: .. code-block:: none - to_hex - ------------------ - 0x0000002a - 0x16449317 - 0x0000029a - 0x12afc77f - 0x133334e6 \ No newline at end of file + to_hex + ---------- + 0xffffffd6 + 0x16449317 + 0x0000029a + 0x12afc77f + 0x133334e6 \ No newline at end of file From c249f89d3d15ffa5ded91289bb9c247888364e7f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 13:47:49 +0300 Subject: [PATCH 0618/1892] Configuration flags --- configuration_guides/admin_cluster_flags.rst | 9 - configuration_guides/admin_flags.rst | 18 - configuration_guides/admin_regular_flags.rst | 32 -- configuration_guides/admin_worker_flags.rst | 20 - configuration_guides/configuration_flags.rst | 19 - .../current_method_all_configurations.rst | 431 ------------------ .../current_method_configuration_levels.rst | 32 -- .../current_method_configuration_roles.rst | 17 - .../current_method_flag_types.rst | 20 - configuration_guides/generic_flags.rst | 17 - .../generic_regular_flags.rst | 21 - configuration_guides/generic_worker_flags.rst | 8 - configuration_guides/index.rst | 6 +- 13 files changed, 2 insertions(+), 648 deletions(-) delete mode 100644 configuration_guides/admin_cluster_flags.rst delete mode 100644 configuration_guides/admin_flags.rst delete mode 100644 configuration_guides/admin_regular_flags.rst delete mode 100644 configuration_guides/admin_worker_flags.rst delete mode 100644 configuration_guides/configuration_flags.rst delete mode 100644 configuration_guides/current_method_all_configurations.rst delete mode 100644 configuration_guides/current_method_configuration_levels.rst delete mode 100644 configuration_guides/current_method_configuration_roles.rst delete mode 100644 configuration_guides/current_method_flag_types.rst delete mode 100644 configuration_guides/generic_flags.rst delete mode 100644 configuration_guides/generic_regular_flags.rst delete mode 100644 configuration_guides/generic_worker_flags.rst diff --git a/configuration_guides/admin_cluster_flags.rst b/configuration_guides/admin_cluster_flags.rst deleted file mode 100644 index f17cee34a..000000000 --- a/configuration_guides/admin_cluster_flags.rst +++ /dev/null @@ -1,9 +0,0 @@ -.. _admin_cluster_flags: - -************************* -Cluster Administration Flags -************************* - -The **Cluster Administration Flags** page describes **Cluster** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - -* `Persisting Your Cache Directory <https://docs.sqream.com/en/v2022.1/configuration_guides/csv_limit_row_length.html>`_ \ No newline at end of file diff --git a/configuration_guides/admin_flags.rst b/configuration_guides/admin_flags.rst deleted file mode 100644 index e71b9f761..000000000 --- a/configuration_guides/admin_flags.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _admin_flags: - -************************* -Administration Flags -************************* - -The **Administration Flags** page describes the following flag types, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - - -.. toctree:: - :maxdepth: 1 - :glob: - - admin_regular_flags - admin_cluster_flags - admin_worker_flags - - diff --git a/configuration_guides/admin_regular_flags.rst b/configuration_guides/admin_regular_flags.rst deleted file mode 100644 index fd7131692..000000000 --- a/configuration_guides/admin_regular_flags.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _admin_regular_flags: - -************************* -Regular Administration Flags -************************* -The **Regular Administration Flags** page describes **Regular** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - -* :ref:`Setting Bin Size<bin_sizes>` -* :ref:`Setting CUDA Memory<check_cuda_memory>` -* :ref:`Limiting Runtime to Utility Functions<compiler_gets_only_ufs>` -* :ref:`Enabling High Bin Control Granularity<copy_to_restrict_utf8>` -* :ref:`Reducing CPU Hashtable Sizes<cpu_reduce_hashtable_size>` -* :ref:`Setting Chunk Size for Copying from CPU to GPU<cuda_mem_cpy_max_size_bytes>` -* :ref:`Indicating GPU Synchronicity<cuda_mem_cpy_synchronous>` -* :ref:`Setting the Graceful Server Shutdown<graceful_shutdown>` -* :ref:`Enabling Modification of R&D Flags<developer_mode>` -* :ref:`Checking for Post-Production CUDA Errors<enable_device_debug_messages>` -* :ref:`Enabling Modification of clientLogger_debug File<enable_log_debug>` -* :ref:`Activating the NVidia Profiler Markers<enable_nv_prof_markers>` -* :ref:`Appending String at End of Log Lines<end_log_message>` -* :ref:`Monitoring and Printing Pinned Allocation Reports<gather_mem_stat>` -* :ref:`Increasing Chunk Size to Reduce Query Speed<increase_chunk_size_before_reduce>` -* :ref:`Adding Rechunker before Expensing Chunk Producer<increase_mem_factors>` -* :ref:`Setting the Buffer Size<level_db_write_buffer_size>` -* :ref:`Setting Memory Used to Abort Server<memory_reset_trigger_mb>` -* :ref:`Splitting Large Reads for Concurrent Execution<mt_read>` -* :ref:`Setting Worker Amount to Handle Concurrent Reads<mt_read_workers>` -* :ref:`Setting Implicit Casts in ORC Files<orc_implicit_casts>` -* :ref:`Setting Timeout Limit for Locking Objects before Executing Statements<statement_lock_timeout>` -* :ref:`Interpreting Decimal Literals as Double Instead of Numeric<use_legacy_decimal_literals>` -* :ref:`Using Legacy String Literals<use_legacy_string_literals>` -* :ref:`Blocking New VARCHAR Objects<block_new_varchar_objects>` diff --git a/configuration_guides/admin_worker_flags.rst b/configuration_guides/admin_worker_flags.rst deleted file mode 100644 index 130131b57..000000000 --- a/configuration_guides/admin_worker_flags.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _admin_worker_flags: - -************************* -Worker Administration Flags -************************* - -.. |icon-new_gray_2022.1.1| image:: /_static/images/new_gray_2022.1.1.png - :align: middle - :width: 110 - - -The **Worker Administration Flags** page describes **Worker** modification type flags, which can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - -* `Setting Total Device Memory Usage in SQream Instance <https://docs.sqream.com/en/v2022.1.2/configuration_guides/cuda_mem_quota.html>`_ -* `Enabling Manually Setting Reported IP <https://docs.sqream.com/en/v2022.1.2/configuration_guides/machine_ip.html>`_ -* `Setting Port Used for Metadata Server Connection <https://docs.sqream.com/en/v2022.1.2/configuration_guides/metadata_server_port.html>`_ -* `Assigning Local Network IP <https://docs.sqream.com/en/v2022.1.2/configuration_guides/use_config_ip.html>`_ -* `Enabling the Query Healer <https://docs.sqream.com/en/v2022.1.2/configuration_guides/is_healer_on.html>`_ -* `Configuring the Query Healer <https://docs.sqream.com/en/v2022.1.2/configuration_guides/healer_max_inactivity_hours.html>`_ -* `Adjusting Permitted Log-in Attempts <https://docs.sqream.com/en/v2022.1.2/configuration_guides/login_max_retries.html>`_ \ No newline at end of file diff --git a/configuration_guides/configuration_flags.rst b/configuration_guides/configuration_flags.rst deleted file mode 100644 index d6f5265ce..000000000 --- a/configuration_guides/configuration_flags.rst +++ /dev/null @@ -1,19 +0,0 @@ -.. _configuration_flags: - -************************* -Configuration Flags -************************* - - - -.. toctree:: - :maxdepth: 1 - :glob: - :titlesonly: - - admin_flags - generic_flags - - - - diff --git a/configuration_guides/current_method_all_configurations.rst b/configuration_guides/current_method_all_configurations.rst deleted file mode 100644 index 9a2352faf..000000000 --- a/configuration_guides/current_method_all_configurations.rst +++ /dev/null @@ -1,431 +0,0 @@ -.. _current_method_all_configurations: - -************************** -All Configurations -************************** -The following table describes all **Generic** and **Administration** configuration flags: - -.. list-table:: - :header-rows: 1 - :widths: 1 2 1 15 1 20 - :class: my-class - :name: my-name - - * - Flag Name - - Access Control - - Modification Type - - Description - - Data Type - - Default Value - - * - ``binSizes`` - - Admin - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - string - - - ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` - ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` - ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` - ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` - ``2684354560,2952790016,3221225472`` - - * - ``cacheEvictionMilliseconds`` - - Generic - - Regular - - Sets how long the cache stores contents before being flushed. - - size_t - - ``2000`` - - - * - ``cacheDiskDir`` - - Generic - - Regular - - Sets the ondisk directory location for the spool to save files on. - - size_t - - Any legal string - - - * - ``cacheDiskGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool on the disk. - - size_t - - ``128`` - - * - ``cachePartitions`` - - Generic - - Regular - - Sets the number of partitions that the cache is split into. - - size_t - - ``4`` - - - * - ``cachePersistentDir`` - - Generic - - Regular - - Sets the persistent directory location for the spool to save files on. - - string - - Any legal string - - - * - ``cachePersistentGB`` - - Generic - - Regular - - Sets the amount of data (GB) for the cache to store persistently. - - size_t - - ``128`` - - - * - ``cacheRamGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by Spool InMemory. - - size_t - - ``16`` - - - - * - ``checkCudaMemory`` - - Admin - - Regular - - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - - boolean - - ``FALSE`` - - * - ``compilerGetsOnlyUFs`` - - Admin - - Regular - - Sets the runtime to pass only utility functions names to the compiler. - - boolean - - ``FALSE`` - - * - ``copyToRestrictUtf8`` - - Admin - - Regular - - Sets the custom bin size in the cache to enable high granularity bin control. - - boolean - - ``FALSE`` - - * - ``cpuReduceHashtableSize`` - - Admin - - Regular - - Sets the hash table size of the CpuReduce. - - uint - - ``10000`` - - * - ``csvLimitRowLength`` - - Admin - - Cluster - - Sets the maximum supported CSV row length. - - uint - - ``100000`` - - * - ``cudaMemcpyMaxSizeBytes`` - - Admin - - Regular - - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - - uint - - ``0`` - - * - ``CudaMemcpySynchronous`` - - Admin - - Regular - - Indicates if copying from/to GPU is synchronous. - - boolean - - ``FALSE`` - - * - ``cudaMemQuota`` - - Admin - - Worker - - Sets the percentage of total device memory to be used by the instance. - - uint - - ``90`` - - * - ``developerMode`` - - Admin - - Regular - - Enables modifying R&D flags. - - boolean - - ``FALSE`` - - * - ``enableDeviceDebugMessages`` - - Admin - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``enableLogDebug`` - - Admin - - Regular - - Enables creating and logging in the clientLogger_debug file. - - boolean - - ``TRUE`` - - * - ``enableNvprofMarkers`` - - Admin - - Regular - - Activates the Nvidia profiler (nvprof) markers. - - boolean - - ``FALSE`` - - * - ``endLogMessage`` - - Admin - - Regular - - Appends a string at the end of every log line. - - string - - ``EOM`` - - - - - - - - * - ``extentStorageFileSizeMB`` - - Admin - - Cluster - - Sets the minimum size in mebibytes of extents for table bulk data. - - uint - - ``20`` - - - * - ``externalTableBlobEstimate`` - - ? - - Regular - - ? - - ? - - ? - - - - - - * - ``flipJoinOrder`` - - Generic - - Regular - - Reorders join to force equijoins and/or equijoins sorted by table size. - - boolean - - ``FALSE`` - - - - * - ``gatherMemStat`` - - Admin - - Regular - - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the **dump_pinned_misses** utility function. - - boolean - - ``FALSE`` - - - * - ``healerMaxInactivityHours`` - - Admin - - Worker - - Defines the threshold for creating a log recording a slow statement. - - size_t - - ``5`` - - - - - * - ``increaseChunkSizeBeforeReduce`` - - Admin - - Regular - - Increases the chunk size to reduce query speed. - - boolean - - ``FALSE`` - - * - ``increaseMemFactors`` - - Admin - - Regular - - Adds rechunker before expensive chunk producer. - - boolean - - ``TRUE`` - - - * - ``isHealerOn`` - - Admin - - Worker - - Periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. - - boolean - - ``TRUE`` - - - - - - * - ``leveldbWriteBufferSize`` - - Admin - - Regular - - Sets the buffer size. - - uint - - ``524288`` - - * - ``limitQueryMemoryGB`` - - Generic - - Worker - - Prevents a query from processing more memory than the flag’s value. - - uint - - ``100000`` - - - - - * - ``loginMaxRetries`` - - Admin - - Worker - - Sets the permitted log-in attempts. - - size_t - - ``5`` - - - - * - ``logSysLevel`` - - Generic - - Regular - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` - - - - - - * - ``machineIP`` - - Admin - - Worker - - Manual setting of reported IP. - - string - - ``127.0.0.1`` - - - * - ``maxAvgBlobSizeToCompressOnGpu`` - - Generic - - Regular - - Sets the CPU to compress columns with size above (flag’s value) * (row count). - - uint - - ``120`` - - - * - ``maxPinnedPercentageOfTotalRAM`` - - Admin - - Regular - - Sets the maximum percentage CPU RAM that pinned memory can use. - - uint - - ``70`` - - - - * - ``memMergeBlobOffsetsCount`` - - Admin - - Regular - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` - - - - * - ``memoryResetTriggerMB`` - - Admin - - Regular - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` - - * - ``metadataServerPort`` - - Admin - - Worker - - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024† because ports below 1024 are usually reserved, although there are no strict limitations. Any positive number (1 - 65535) can be used. - - uint - - ``3105`` - - * - ``mtRead`` - - Admin - - Regular - - Splits large reads to multiple smaller ones and executes them concurrently. - - boolean - - ``FALSE`` - - * - ``mtReadWorkers`` - - Admin - - Regular - - Sets the number of workers to handle smaller concurrent reads. - - uint - - ``30`` - - * - ``orcImplicitCasts`` - - Admin - - Regular - - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - - boolean - - ``TRUE`` - - - * - ``sessionTag`` - - Generic - - Regular - - Sets the name of the session tag. - - string - - Any legal string - - - - * - ``spoolMemoryGB`` - - Generic - - Regular - - Sets the amount of memory (GB) to be used by the server for spooling. - - uint - - ``8`` - - - * - ``statementLockTimeout`` - - Admin - - Regular - - Sets the timeout (seconds) for acquiring object locks before executing statements. - - uint - - ``3`` - - * - ``useConfigIP`` - - Admin - - Worker - - Activates the machineIP (true). Setting to false ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - - boolean - - ``FALSE`` - - * - ``useLegacyDecimalLiterals`` - - Admin - - Regular - - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - * - ``useLegacyStringLiterals`` - - Admin - - Regular - - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - - - - - - - - - * - ``blockNewVarcharObjects`` - - Admin - - Regular - - Disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. - - boolean - - ``FALSE`` \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst deleted file mode 100644 index c7443ede2..000000000 --- a/configuration_guides/current_method_configuration_levels.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _current_method_configuration_levels: - -************************** -Configuration Levels -************************** -SQream's configuration parameters are based on the following hierarchy: - -.. contents:: - :local: - :depth: 1 - -Cluster-Based Configuration --------------- -Cluster-based configuration lets you centralize configurations for all workers on the cluster. Only :ref:`Regular and Cluster flag types<current_method_flag_types>` can be modified on the cluster level. These modifications are persistent and stored at the metadata level, which are applied globally to all workers in the cluster. - -.. note:: While cluster-based configuration was designed for configuring Workers, you can only configure Worker values set to the Regular or Cluster type. - -Worker-Based Configuration --------------- -Worker-based configuration lets you modify individual workers using a worker configuration file. Worker-based configuration modifications are persistent. - - -Session-Based Configuration --------------- -Session-based configurations are not persistent and are deleted when your session ends. This method enables you to modify all required configurations while avoiding conflicts between flag attributes modified on different devices at different points in time. The **SET flag_name** command is used to modify flag values on the session level. Any modifications you make with the **SET flag_name** command apply only to your open session, and are not saved when it ends. - -For example, when the query below has completed executing, the values configured will be restored to its previous setting: - -.. code-block:: console - - set spoolMemoryGB=700; - select * from table a where date='2021-11-11' \ No newline at end of file diff --git a/configuration_guides/current_method_configuration_roles.rst b/configuration_guides/current_method_configuration_roles.rst deleted file mode 100644 index b3afc2b46..000000000 --- a/configuration_guides/current_method_configuration_roles.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _current_method_configuration_roles: - -************************** -Configuration Roles -************************** -SQream divides flags into the following roles, each with their own set of permissions: - -* :ref:`admin_flags` - can be modified by administrators on a session and cluster basis using the ``ALTER SYSTEM SET`` command: - - * Regular - * Worker - * Cluster - -* :ref:`generic_flags` - can be modified by standard users on a session basis: - - * Regular - * Worker \ No newline at end of file diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst deleted file mode 100644 index 93e82e79b..000000000 --- a/configuration_guides/current_method_flag_types.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _current_method_flag_types: - -************************** -Flag Types -************************** -SQream uses three flag types, **Cluster**, **Worker**, and **Regular**. Each of these flag types is associated with one of three hierarchical configuration levels described earlier, making it easier to configure your system. - -The highest level in the hierarchy is Cluster, which lets you set configurations across all workers in a given cluster. Modifying cluster values is **persistent**, meaning that any configurations you set are retained after shutting down your system. Configurations set at the Cluster level take the highest priority and override settings made on the Regular and Worker level. This is known as **cluster-based configuration**. Note that Cluster-based configuration lets you modify Cluster *and* Regular flag types. An example of a Cluster flag is **persisting your cache directory.** - -The second level is Worker, which lets you configure individual workers. Modifying Worker values are also **persistent**. This is known as **worker-based configuration**. Some examples of Worker flags includes **setting total device memory usage** and **setting metadata server connection port**. - -The lowest level is Regular, which means that modifying values of Regular flags affects only your current session and are not persistent. This means that they are automatically restored to their default value when the session ends. This is known as **session-based configuration**. Some examples of Regular flags includes **setting your bin size** and **setting CUDA memory**. - -To see each flag's default value, see one of the following: - -* The **Default Value** column in the :ref:`All Configurations<current_method_all_configurations>` section. - - :: - -* The flag's individual description page, such as :ref:`Setting CUDA Memory<check_cuda_memory>`. \ No newline at end of file diff --git a/configuration_guides/generic_flags.rst b/configuration_guides/generic_flags.rst deleted file mode 100644 index 2f17e8202..000000000 --- a/configuration_guides/generic_flags.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _generic_flags: - -************************* -Generic Flags -************************* - -The **Generic Flags** page describes the following flag types, which can be modified by standard users on a session basis: - -.. toctree:: - :maxdepth: 1 - :glob: - - generic_regular_flags - generic_cluster_flags - generic_worker_flags - - diff --git a/configuration_guides/generic_regular_flags.rst b/configuration_guides/generic_regular_flags.rst deleted file mode 100644 index c262982ec..000000000 --- a/configuration_guides/generic_regular_flags.rst +++ /dev/null @@ -1,21 +0,0 @@ -.. _generic_regular_flags: - -************************* -Regular Generic Flags -************************* - -The **Regular Generic Flags** page describes **Regular** modification type flags, which can be modified by standard users on a session basis: - -* :ref:`Flipping Join Order to Force Equijoins<flip_join_order>` -* :ref:`Determining Client Level<log_sys_level>` -* :ref:`Setting CPU to Compress Defined Columns<max_avg_blob_size_to_compress_on_gpu>` -* :ref:`Setting Query Memory Processing Limit<limit_query_memory_gb>` -* :ref:`Setting the Spool Memory<spool_memory_gb>` -* :ref:`Setting Cache Partitions<cache_partitions>` -* :ref:`Setting Cache Flushing<cache_eviction_milliseconds>` -* :ref:`Setting InMemory Spool Memory<cache_ram_gb>` -* :ref:`Setting Disk Spool Memory<cache_disk_gb>` -* :ref:`Setting Spool Saved File Directory Location<cache_disk_dir>` -* :ref:`Setting Data Stored Persistently on Cache<cache_persistent_gb>` -* :ref:`Setting Persistent Spool Saved File Directory Location<cache_persistent_dir>` -* :ref:`Setting Session Tag Name<session_tag>` \ No newline at end of file diff --git a/configuration_guides/generic_worker_flags.rst b/configuration_guides/generic_worker_flags.rst deleted file mode 100644 index 7ae2a0ee7..000000000 --- a/configuration_guides/generic_worker_flags.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _generic_worker_flags: - -************************* -Worker Generic Flags -************************* -The Worker Generic Flags** page describes **Worker** modification type flags, which can be modified by standard users on a session basis: - - * `Persisting Your Cache Directory <https://docs.sqream.com/en/v2022.1.1/configuration_guides/limit_query_memory_gb.html>`_ \ No newline at end of file diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 9c0b206e7..5a060d551 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -10,8 +10,6 @@ The **Configuration Guides** page describes the following configuration informat :maxdepth: 1 :glob: - spooling configuring_sqream - ldap - configuration_flags - previous_configuration_method \ No newline at end of file + spooling + ldap \ No newline at end of file From 44ba79b940fb30089707a41406a3f57be4d0b883 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:05:56 +0300 Subject: [PATCH 0619/1892] Cinfiguring SQream --- configuration_guides/configuring_sqream.rst | 3 - .../current_method_configuration_levels.rst | 410 ++++++++++++++++++ ...thod_configuring_your_parameter_values.rst | 6 +- .../current_method_flag_types.rst | 72 +++ 4 files changed, 485 insertions(+), 6 deletions(-) create mode 100644 configuration_guides/current_method_configuration_levels.rst create mode 100644 configuration_guides/current_method_flag_types.rst diff --git a/configuration_guides/configuring_sqream.rst b/configuration_guides/configuring_sqream.rst index 901af9e3d..685e24516 100644 --- a/configuration_guides/configuring_sqream.rst +++ b/configuration_guides/configuring_sqream.rst @@ -12,11 +12,8 @@ The **Configuring SQream** page describes the following configuration topics: current_method_configuration_levels current_method_flag_types - current_method_configuration_roles current_method_modification_methods current_method_configuring_your_parameter_values - current_method_command_examples current_method_showing_all_flags_in_the_catalog_table - current_method_all_configurations diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst new file mode 100644 index 000000000..71182637c --- /dev/null +++ b/configuration_guides/current_method_configuration_levels.rst @@ -0,0 +1,410 @@ +.. _current_method_configuration_levels: + +******************************* +Cluster and Session Environment +******************************* + +When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configurations involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. + +Session-based flags only apply to a specific session and are not persistent. Changes made using session-based flags are not visible to other users, and once the session ends, the flags return to their default values. + +Cluster-based flag syntax: + +.. code-block:: postgress + + ALTER SYSTEM SET <flagName> + +Session-based flag syntax: + +.. code-block:: postgress + + SET <flagName> + +.. list-table:: + :header-rows: 1 + :widths: 1 2 1 15 1 20 + :class: my-class + :name: my-name + + * - Flag Name + - Who May Configure + - Cluster / Session + - Description + - Data Type + - Default Value + + * - ``binSizes`` + - SUPERUSER + - Session + - Sets the custom bin size in the cache to enable high granularity bin control. + - string + - + ``16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,`` + ``131072,262144,524288,1048576,2097152,4194304,8388608,16777216,`` + ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` + ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` + ``2684354560,2952790016,3221225472`` + + * - ``cacheEvictionMilliseconds`` + - Anyone + - Session + - Sets how long the cache stores contents before being flushed. Allowed values: 1-4000000000. + - bigint + - ``2000`` + + + * - ``cacheDiskDir`` + - Anyone + - Session + - Sets the ondisk directory location for the spool to save files on. Allowed values: Any legal string. + - bigint + - Any legal string + + + * - ``cacheDiskGB`` + - Anyone + - Session + - Sets the amount of memory (GB) to be used by Spool on the disk. Allowed values: 0-4000000000. + - bigint + - ``128`` + + * - ``cachePartitions`` + - Anyone + - Session + - Sets the number of partitions that the cache is split into. Allowed values: 1-4000000000. + - bigint + - ``4`` + + + * - ``cachePersistentDir`` + - Anyone + - Session + - Sets the persistent directory location for the spool to save files on. Allowed values: Any legal string. + - string + - ``/tmp`` + + + * - ``cachePersistentGB`` + - Anyone + - Session + - Sets the amount of data (GB) for the cache to store persistently. Allowed values: 0-4000000000. + - bigint + - ``128`` + + + * - ``cacheRamGB`` + - Anyone + - Session + - Sets the amount of memory (GB) to be used by Spool InMemory. Allowed values: 0-4000000000. + - bigint + - ``16`` + + + + * - ``checkCudaMemory`` + - SUPERUSER + - Session + - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. + - boolean + - ``FALSE`` + + * - ``compilerGetsOnlyUFs`` + - SUPERUSER + - Session + - Sets the runtime to pass only utility functions names to the compiler. + - boolean + - ``FALSE`` + + * - ``copyToRestrictUtf8`` + - SUPERUSER + - Session + - Sets the custom bin size in the cache to enable high granularity bin control. + - boolean + - ``FALSE`` + + * - ``cpuReduceHashtableSize`` + - SUPERUSER + - Session + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + + * - ``csvLimitRowLength`` + - SUPERUSER + - Cluster + - Sets the maximum supported CSV row length. Allowed values: 1-4000000000 + - uint + - ``100000`` + + * - ``cudaMemcpyMaxSizeBytes`` + - SUPERUSER + - Session + - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. + - uint + - ``0`` + + * - ``CudaMemcpySynchronous`` + - SUPERUSER + - Session + - Indicates if copying from/to GPU is synchronous. + - boolean + - ``FALSE`` + + + * - ``developerMode`` + - SUPERUSER + - Session + - Enables modifying R&D flags. + - boolean + - ``FALSE`` + + * - ``enableDeviceDebugMessages`` + - SUPERUSER + - Session + - Checks for CUDA errors after producing each chunk. + - boolean + - ``FALSE`` + + * - ``enableLogDebug`` + - SUPERUSER + - Session + - Enables creating and logging in the clientLogger_debug file. + - boolean + - ``TRUE`` + + * - ``enableNvprofMarkers`` + - SUPERUSER + - Session + - Activates the Nvidia profiler (nvprof) markers. + - boolean + - ``FALSE`` + + * - ``endLogMessage`` + - SUPERUSER + - Session + - Appends a string at the end of every log line. + - string + - ``EOM`` + + + + + + + + * - ``extentStorageFileSizeMB`` + - SUPERUSER + - Cluster + - Sets the minimum size in mebibytes of extents for table bulk data. + - uint + - ``20`` + + + * - ``externalTableBlobEstimate`` + - ? + - Session + - ? + - ? + - ? + + + + + + * - ``flipJoinOrder`` + - Anyone + - Session + - Reorders join to force equijoins and/or equijoins sorted by table size. + - boolean + - ``FALSE`` + + + + * - ``gatherMemStat`` + - SUPERUSER + - Session + - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the ``dump_pinned_misses`` utility function. + - boolean + - ``FALSE`` + + + + + + + * - ``increaseChunkSizeBeforeReduce`` + - SUPERUSER + - Session + - Increases the chunk size to reduce query speed. + - boolean + - ``FALSE`` + + * - ``increaseMemFactors`` + - SUPERUSER + - Session + - Adds rechunker before expensive chunk producer. + - boolean + - ``TRUE`` + + + + + + + + + * - ``leveldbWriteBufferSize`` + - SUPERUSER + - Session + - Sets the buffer size. + - uint + - ``524288`` + + + + + + * - ``logSysLevel`` + - Anyone + - Session + - + Determines the client log level: + 0 - L_SYSTEM, + 1 - L_FATAL, + 2 - L_ERROR, + 3 - L_WARN, + 4 - L_INFO, + 5 - L_DEBUG, + 6 - L_TRACE + - uint + - ``100000`` + + + + + + + + * - ``maxAvgBlobSizeToCompressOnGpu`` + - Anyone + - Session + - Sets the CPU to compress columns with size above (flag’s value) * (row count). + - uint + - ``120`` + + + * - ``maxPinnedPercentageOfTotalRAM`` + - SUPERUSER + - Session + - Sets the maximum percentage CPU RAM that pinned memory can use. + - uint + - ``70`` + + + + * - ``memMergeBlobOffsetsCount`` + - SUPERUSER + - Session + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + + + * - ``memoryResetTriggerMB`` + - SUPERUSER + - Session + - Sets the size of memory used during a query to trigger aborting the server. + - uint + - ``0`` + + + + * - ``mtRead`` + - SUPERUSER + - Session + - Splits large reads to multiple smaller ones and executes them concurrently. + - boolean + - ``FALSE`` + + * - ``mtReadWorkers`` + - SUPERUSER + - Session + - Sets the number of workers to handle smaller concurrent reads. + - uint + - ``30`` + + * - ``orcImplicitCasts`` + - SUPERUSER + - Session + - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. + - boolean + - ``TRUE`` + + + * - ``sessionTag`` + - Anyone + - Session + - Sets the name of the session tag. Allowed values: Any legal string. + - string + - Any legal string + + + + * - ``spoolMemoryGB`` + - Anyone + - Session + - Sets the amount of memory (GB) to be used by the server for spooling. + - uint + - ``8`` + + + * - ``statementLockTimeout`` + - SUPERUSER + - Session + - Sets the timeout (seconds) for acquiring object locks before executing statements. + - uint + - ``3`` + + + + * - ``useLegacyDecimalLiterals`` + - SUPERUSER + - Session + - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + * - ``useLegacyStringLiterals`` + - SUPERUSER + - Session + - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. + - boolean + - ``FALSE`` + + + + + + + + + + * - ``blockNewVarcharObjects`` + - SUPERUSER + - Session + - Disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. + - boolean + - ``FALSE`` + * - ``defaultGracefulShutdownTimeoutMinutes`` + - SUPERUSER + - Cluster + - Used for setting the amount of time to pass before SQream performs a graceful server shutdown. Allowed values - 1-4000000000. Related flags: ``is_healer_on`` and ``healer_max_inactivity_hours`` + - bigint + - ``5`` + * - ``limitQueryMemoryGB`` + - SUPERUSER + - Cluster + - Prevents a query from processing more memory than the defined value. + - uint + - ``100000`` \ No newline at end of file diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst index d082db693..e3687f55c 100644 --- a/configuration_guides/current_method_configuring_your_parameter_values.rst +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -1,8 +1,8 @@ .. _current_method_configuring_your_parameter_values: -************************** -Configuring Your Parameter Values -************************** +**************** +Parameter Values +**************** The method you must use to configure your parameter values depends on the configuration level. Each configuration level has its own command or set of commands used to configure values, as shown below: +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst new file mode 100644 index 000000000..b0ddf8fc0 --- /dev/null +++ b/configuration_guides/current_method_flag_types.rst @@ -0,0 +1,72 @@ +.. _current_method_flag_types: + +******* +Workers +******* + +Workers can be individually configured using a worker configuration file, which allows for persistent modifications to be made. Persistent modification refers to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. + +It is worth noting that the worker configuration file is not subject to frequent changes on a daily basis, providing stability to the system's configuration. + + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag Name + - Who May Configure + - Description + - Data Type + - Default Value + * - ``cudaMemQuota`` + - SUPERUSER + - Sets the percentage of total device memory used by your instance of SQream. + - uint + - ``90`` + * - ``healerMaxInactivityHours`` + - SUPERUSER + - Used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + - bigint + - ``5`` + * - ``isHealerOn`` + - SUPERUSER + - Enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. + - boolean + - ``TRUE`` + * - ``limitQueryMemoryGB`` + - Anyone + - Prevents a query from processing more memory than the defined value. + - uint + - ``100000`` + * - ``loginMaxRetries`` + - SUPERUSER + - Sets the permitted log-in attempts. + - bigint + - ``5`` + * - ``machineIP`` + - SUPERUSER + - Enables you to manually set the reported IP. + - string + - ``127.0.0.1`` + * - ``metadataServerPort`` + - SUPERUSER + - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024 because ports below 1024 are usually reserved, although there are no strict limitations. You can use any positive number (1 - 65535) while setting this flag. + - uint + - ``3105`` + * - ``useConfigIP`` + - SUPERUSER + - Activates the machineIP (``TRUE``). Setting this flag to ``FALSE`` ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). + - boolean + - ``FALSE`` + + + + + + + + + + + + From d4fd57e347781440797add6257381bca778dda7b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:21:10 +0300 Subject: [PATCH 0620/1892] Delete current_method_command_examples.rst --- .../current_method_command_examples.rst | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 configuration_guides/current_method_command_examples.rst diff --git a/configuration_guides/current_method_command_examples.rst b/configuration_guides/current_method_command_examples.rst deleted file mode 100644 index 2f75a4711..000000000 --- a/configuration_guides/current_method_command_examples.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _current_method_command_examples: - -************************** -Command Examples -************************** -This section includes the following command examples: - -.. contents:: - :local: - :depth: 1 - -Running a Regular Flag Type Command ---------------------- -The following is an example of running a **Regular** flag type command: - -.. code-block:: console - - SET spoolMemoryGB= 11; - executed - -Running a Worker Flag Type Command ---------------------- -The following is an example of running a **Worker** flag type command: - -.. code-block:: console - - SHOW spoolMemoryGB; - -Running a Cluster Flag Type Command ---------------------- -The following is an example of running a **Cluster** flag type command: - -.. code-block:: console - - ALTER SYSTEM RESET useMetadataServer; - executed \ No newline at end of file From 0213031c359952cb612c525135298817ab19377f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:29:30 +0300 Subject: [PATCH 0621/1892] Configuration flags --- .../current_method_configuration_levels.rst | 8 ++++---- configuration_guides/ldap.rst | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 71182637c..1480b4efd 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -4,17 +4,17 @@ Cluster and Session Environment ******************************* -When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configurations involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. +When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. -Session-based flags only apply to a specific session and are not persistent. Changes made using session-based flags are not visible to other users, and once the session ends, the flags return to their default values. +Session flags only apply to a specific session and are not persistent. Changes made using session flags are not visible to other users, and once the session ends, the flags return to their default values. -Cluster-based flag syntax: +Cluster flag syntax: .. code-block:: postgress ALTER SYSTEM SET <flagName> -Session-based flag syntax: +Session flag syntax: .. code-block:: postgress diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index ec16f9c69..4d9e25d24 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -85,7 +85,7 @@ Basic Method Flag Attributes ~~~~~~~~~~~~~~~ -To enable basic LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +To enable basic LDAP authentication, configure the following cluster flag attributes using the ``ALTER SYSTEM SET`` command: .. list-table:: :widths: auto @@ -183,7 +183,7 @@ Advanced Method Flag Attributes ~~~~~~~~~~~~~~~ -To enable advanced LDAP authentication, configure the following **Cluster** flag attributes using the ``ALTER SYSTEM SET`` command: +To enable advanced LDAP authentication, configure the following cluster flag attributes using the ``ALTER SYSTEM SET`` command: .. list-table:: :widths: auto From 2b9bf5d8648f12478b3160800ba739f3d1e74712 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 14:32:44 +0300 Subject: [PATCH 0622/1892] Update configuring_your_instance_of_sqream.rst --- sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst b/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst index 3fcac7861..b5a26f2bb 100644 --- a/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst +++ b/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst @@ -10,7 +10,7 @@ Because session-based configurations are not persistent and are deleted when you Editing Your Parameters ------------------------------- -When configuring your instance of SQream in Studio you can edit parameters for the **Generic** and **Admin** parameters only. +When configuring your instance of SQream in Studio you can edit session and cluster parameters only. Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. From 5baec2a32cd03ed931aaeaa9274d5083048832d5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:02:44 +0300 Subject: [PATCH 0623/1892] Configuration flag --- conf.py | 2 +- .../current_method_configuration_levels.rst | 12 +++++++++--- ...rent_method_configuring_your_parameter_values.rst | 11 ++--------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/conf.py b/conf.py index 4cefff76e..26575ea28 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '4.3' +release = '4.4' diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 1480b4efd..7c9785bbd 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -1,13 +1,16 @@ .. _current_method_configuration_levels: -******************************* -Cluster and Session Environment -******************************* +******************* +Cluster and Session +******************* When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. Session flags only apply to a specific session and are not persistent. Changes made using session flags are not visible to other users, and once the session ends, the flags return to their default values. +Syntax +====== + Cluster flag syntax: .. code-block:: postgress @@ -20,6 +23,9 @@ Session flag syntax: SET <flagName> +Flag List +========= + .. list-table:: :header-rows: 1 :widths: 1 2 1 15 1 20 diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst index e3687f55c..1300b113d 100644 --- a/configuration_guides/current_method_configuring_your_parameter_values.rst +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -3,16 +3,11 @@ **************** Parameter Values **************** -The method you must use to configure your parameter values depends on the configuration level. Each configuration level has its own command or set of commands used to configure values, as shown below: -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Configuration Level** | -+=================================================================================================================================================================================================================================================================================================================+ -| **Regular, Worker, and Cluster** | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | **Command** | **Description** | **Example** | -+-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``SET <flag_name>`` | Used for modifying flag attributes. | ``SET developerMode=true`` | ++=====================================================+===========================================================================================================================================+===============================================================================================================+ +| ``SET<flag_name>`` | Used for modifying flag attributes. | ``SET developerMode=true`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``SHOW <flag-name> / ALL`` | Used to preset either a specific flag value or all flag values. | ``SHOW <heartbeatInterval>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ @@ -32,8 +27,6 @@ The method you must use to configure your parameter values depends on the config | | |* Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` | | | |* Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| **Worker and Cluster** | -+-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``ALTER SYSTEM SET <flag-name>`` | Used for storing or modifying flag attributes in the metadata file. | ``ALTER SYSTEM SET <heartbeatInterval=12;>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``ALTER SYSTEM RESET <flag-name / ALL>`` | Used to remove a flag or all flag attributes from the metadata file. | ``ALTER SYSTEM RESET <heartbeatInterval ALTER SYSTEM RESET ALL>`` | From 44af99e70b6b93f082f71eb88b10ec8c922362ed Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:14:47 +0300 Subject: [PATCH 0624/1892] Configuration flags --- .../healer_detection_frequency_seconds.rst | 2 +- ...ealer_max_statement_inactivity_seconds.rst | 2 +- feature_guides/query_healer.rst | 24 +++++-------------- .../shutdown_server_command.rst | 1 - 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/configuration_guides/healer_detection_frequency_seconds.rst b/configuration_guides/healer_detection_frequency_seconds.rst index 9e7805852..a7c1939ad 100644 --- a/configuration_guides/healer_detection_frequency_seconds.rst +++ b/configuration_guides/healer_detection_frequency_seconds.rst @@ -5,7 +5,7 @@ Healer Detection Frequency Seconds ************************* The ``healerDetectionFrequencySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. -The following describes the ``healerDetectionFrequencySeconds`` worker level flag: +The following describes the ``healerDetectionFrequencySeconds`` worker flag: * **Data type** - size_t * **Default value** - ``1`` diff --git a/configuration_guides/healer_max_statement_inactivity_seconds.rst b/configuration_guides/healer_max_statement_inactivity_seconds.rst index 142e76eb7..533888fff 100644 --- a/configuration_guides/healer_max_statement_inactivity_seconds.rst +++ b/configuration_guides/healer_max_statement_inactivity_seconds.rst @@ -5,7 +5,7 @@ Max Statement Inactivity Seconds ************************* The ``maxStatementInactivitySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. -The following describes the ``maxStatementInactivitySeconds`` worker level flag: +The following describes the ``maxStatementInactivitySeconds`` worker flag: * **Data type** - size_t * **Default value** - ``5`` diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 257de9e32..84181dbbe 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -3,19 +3,13 @@ *********************** Query Healer *********************** -The **Query Healer** page describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview ----------- + + The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding a defined time period. Configuration ------------- -The following **Administration Worker** flags are required to configure the Query Healer: +The following worker flags are required to configure the Query Healer: .. list-table:: :widths: auto @@ -31,7 +25,7 @@ The following **Administration Worker** flags are required to configure the Quer - The :ref:`healer_detection_frequency_seconds` worker level flag triggers the healer to examine the progress of running statements. The default setting is one hour. Query Log ---------------- +--------- The following is an example of a log record for a query stuck in the query detection phase for more than five hours: @@ -42,7 +36,7 @@ The following is an example of a log record for a query stuck in the query detec Once you identify the stuck worker, you can execute the ``shutdown_server`` utility function from this specific worker, as described in the next section. Activating a Graceful Shutdown ------------------- +------------------------------ You can activate a graceful shutdown if your log entry says ``Stuck query found``, as shown in the example above. You can do this by setting the **shutdown_server** utility function to ``select shutdown_server();``. **To activte a graceful shutdown:** @@ -59,10 +53,4 @@ You can activate a graceful shutdown if your log entry says ``Stuck query found` 3. Execute ``shutdown_server``. -For more information, see the following: - -* Activating the :ref:`shutdown_server_command` utility function. This page describes all of ``shutdown_server`` options. - - :: - -* Configuring the :ref:`shutdown_server` flag. \ No newline at end of file +For more information, see the :ref:`shutdown_server_command` utility function. This page describes all of ``shutdown_server`` options. diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index 669e0dbd2..a5996a5ef 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -81,7 +81,6 @@ Note that activating a forced shutdown with a timeout, such as ``select shutdown .. note:: You can set the timeout value using the ``defaultGracefulShutdownTimeoutMinutes`` flag in the Acceleration Studio. -For more information, see :ref:`shutdown_server`. Examples =================== From c42215c5ef00b7126bec0990443e551601af5b96 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 15:16:33 +0300 Subject: [PATCH 0625/1892] Update current_method_configuration_levels.rst --- configuration_guides/current_method_configuration_levels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 7c9785bbd..27f8af8e9 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -1,7 +1,7 @@ .. _current_method_configuration_levels: ******************* -Cluster and Session +Cluster and Session ******************* When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. From d632f1412160fc4c76f35a9fe1811aa14ce399be Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:50:25 +0300 Subject: [PATCH 0626/1892] Update pentaho.rst --- connecting_to_sqream/client_platforms/pentaho.rst | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst index fa8146c41..5bf4c3685 100644 --- a/connecting_to_sqream/client_platforms/pentaho.rst +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -170,9 +170,6 @@ After creating your transformation you must define your output. - Password - Your password. If you leave this blank, you will be prompted to provide it when you connect. - The following message is displayed: - -.. image:: /_static/images/third_party_connectors/pentaho/connection_tested_successfully_2.png 6. Click **OK** in the window above, in the Database Connection window, and Table Output window. @@ -204,19 +201,15 @@ For more information about backing up users, permissions, or schedules, see `Bac 1. On the CSV file input step item, click the **new hop connection** icon. - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options.png 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. - - .. image:: /_static/images/third_party_connectors/pentaho/csv_file_input_options_2.png + 3. Release the mouse button. The following options are displayed. - :: 4. Select **Main output of step**. - .. image:: /_static/images/third_party_connectors/pentaho/main_output_of_step.png :: @@ -242,7 +235,6 @@ For more information about backing up users, permissions, or schedules, see `Bac 10. Click the play button to execute the transformation. - .. image:: /_static/images/third_party_connectors/pentaho/execute_transformation.png The **Run Options** dialog box is displayed. From 487fa97e86d0ee2e4a64bd7a212795a40cef5ea4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Jun 2023 09:32:51 +0300 Subject: [PATCH 0627/1892] H100 --- getting_started/hardware_guide.rst | 10 +++++----- .../recommended_pre-installation_configurations.rst | 5 ++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 61d1aae50..df3e4f093 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -52,7 +52,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * 10x 3.84TB SSD 2.5in Hot plug for storage, RAID6 * - GPU - - 2x A100 NVIDIA + - NVIDIA 2x A100 or H100 * - Operating System - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux @@ -97,7 +97,7 @@ The following table shows SQream's recommended hardware specifications: * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high speed network card minimum 40G compatible to customer’s infrastructure * 50 TB (NAS connected over GPFS, Lustre, Weka, or VAST) GPFS recommended * - GPU - - 2x A100 NVIDIA + - NVIDIA 2x A100 or H100 * - Operating System - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux @@ -200,9 +200,9 @@ SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors, GPU Compute and RAM ------------------------- -The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla V100 32GB or NVIDIA Tesla A100 40GB GPU for best performance and highest concurrent user support. +The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla A100 40GB or H100 GPU for best performance and highest concurrent user support. -GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM, like the NVIDIA Tesla V100 16GB or P100 16GB, or T4 16GB. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. +GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. RAM -------- @@ -223,7 +223,7 @@ Storage ----------- For clustered scale-out installations, SQream relies on NAS storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. -SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla V100 or A100 GPU per 2 users, for full, uninterrupted dedicated access. +SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. .. note:: Non production HW requirements may be found at `Non Production HW Requirements <non_production_hardware_guide.html>`_ \ No newline at end of file diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index cf6328a34..9e965e221 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -830,7 +830,6 @@ Installing the CUDA driver from the Repository is the recommended installation m $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm -.. warning:: For Power9 with V100 GPUs, you must install the **CUDA 10.1** driver. 4. Install the CUDA drivers: @@ -961,7 +960,7 @@ To Tune Up NVIDIA Performance when Driver Installed from the Repository $ sudo systemctl enable nvidia-persistenced -5. For **V100/A100**, add the following lines: +5. For **H100/A100**, add the following lines: .. code-block:: console @@ -1000,7 +999,7 @@ To Tune Up NVIDIA Performance when Driver Installed from the Runfile 3. Add the following lines: - * **For V100/A100**: + * **For H100/A100**: .. code-block:: console From fc73fdf06b67b4f198b63c4be3f9e584aa558e24 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Jun 2023 09:20:26 +0300 Subject: [PATCH 0628/1892] Update chr.rst --- .../scalar_functions/conversion/chr.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/chr.rst b/reference/sql/sql_functions/scalar_functions/conversion/chr.rst index aa52694e1..b98ea5c45 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/chr.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/chr.rst @@ -11,7 +11,20 @@ Syntax .. code-block:: postgres - CHR(n) + CHR(int) + +Argument +======== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Argument + - Description + * - ``int`` + - Integer argument that represents the ASCII code of the character you want to retrieve + Returns ======= From 946de34d3231b7350745c5fc2d75b9e2dee4d52f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 19 Jun 2023 09:43:37 +0300 Subject: [PATCH 0629/1892] Update sql_data_types_date.rst --- data_type_guides/sql_data_types_date.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index 88236c113..5c2a3a4a9 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -95,8 +95,6 @@ The following is an example of the correct output: 1997-01-01 00:00:00.0,1955-11-05 -.. warning:: Some client applications may alter the ``DATETIME`` value by modifying the timezone. - Date Casts and Conversions ^^^^^^^^^^^^^^^^^^^^^^^ From d9ca8dd1c975cefd20d321903bf49af49f121483 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Jun 2023 13:33:49 +0300 Subject: [PATCH 0630/1892] Update drop_role.rst --- .../access_control_commands/drop_role.rst | 32 ++++++++----------- 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/drop_role.rst b/reference/sql/sql_statements/access_control_commands/drop_role.rst index 61c4d5bb9..fe46890ba 100644 --- a/reference/sql/sql_statements/access_control_commands/drop_role.rst +++ b/reference/sql/sql_statements/access_control_commands/drop_role.rst @@ -4,29 +4,22 @@ DROP ROLE ***************** -``DROP ROLE`` remove roles. - -Learn more about the permission system in the :ref:`access control guide<access_control>`. +The ``DROP ROLE`` command is used for removing roles from the database. The optional ``IF EXISTS`` clause can be included to prevent an error if the specified role does not exist. If the ``IF EXISTS`` clause is omitted and the role does not exist, an error will be raised. See also :ref:`create_role`. -Permissions -============= - -To drop a role, the current role must have a ``SUPERUSER`` cluster-level permission. - Syntax -========== +====== .. code-block:: postgres drop_role_statement ::= - DROP ROLE role_name ; + DROP ROLE [IF EXISTS] <role_name> role_name ::= identifier - + Parameters -============ +========== .. list-table:: :widths: auto @@ -35,15 +28,18 @@ Parameters * - Parameter - Description * - ``role_name`` - - The name of the role to drop. - + - Role name to be removed Examples -=========== - -Dropping a role ------------------------------------------ +======== .. code-block:: postgres DROP ROLE new_role; + +Permissions +=========== + +To drop a role, the current role must have a ``SUPERUSER`` permission. + +You can learn more about system permissions in the :ref:`access control guide<access_control>`. \ No newline at end of file From 386b3de134c1b82f95fb4d3c9a796ae8f7d6cbc6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Jun 2023 11:59:25 +0300 Subject: [PATCH 0631/1892] ARRAY --- .../converting_and_casting_types.rst | 7 +- data_type_guides/index.rst | 6 +- data_type_guides/sql_data_type_array.rst | 91 +++++++++++++++++++ data_type_guides/supported_casts.rst | 3 +- data_type_guides/supported_data_types.rst | 10 +- reference/index.rst | 8 +- 6 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 data_type_guides/sql_data_type_array.rst diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 349d4c04d..357450a7d 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -1,8 +1,9 @@ .. _converting_and_casting_types: -************************* -Converting and Casting Types -************************* +********************* +Casts and Conversions +********************* + SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. diff --git a/data_type_guides/index.rst b/data_type_guides/index.rst index 6afec60cf..9d9ceeadd 100644 --- a/data_type_guides/index.rst +++ b/data_type_guides/index.rst @@ -1,8 +1,8 @@ .. _data_type_guides: -************************* -Data Type Guides -************************* +********** +Data Types +********** This section describes the following: .. toctree:: diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst new file mode 100644 index 000000000..93ba46b82 --- /dev/null +++ b/data_type_guides/sql_data_type_array.rst @@ -0,0 +1,91 @@ +.. _sql_data_type_array: + +***** +Array +***** + +The ``ARRAY`` data type offers a convenient way to store ordered collections of elements in a single column. It provides storage efficiency by allowing multiple values of the same data type to be compactly stored, optimizing space utilization and enhancing database performance. Working with arrays simplifies queries as operations and manipulations can be performed on the entire array, resulting in more concise and readable code. + +Each data type has its companion array type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. An array represents a sequence of zero or more elements of the same data type. Arrays in the same column can contain varying numbers of elements across different rows. Arrays can include null values, eliminating the need for separate SQL declarations. + +Syntax +====== + +Defining an array is done by appending the ``[]`` notation to a supported data type, for example, ``int[]`` for an array of integers. + +.. code-block:: + + CREAT TABLE <table_name> (<column1> TEXT[], <column2> INT[]) + + INSERT INTO TABLE <table_name> VALUES ARRAY[<'a','b','c'>], ARRAY[<1,2,3>] + +Size +==== + +The maximum size of an array, indicating the number of elements it can hold, is 65535. You have the option to specify the array size, providing a maximum allowed size, while each row can have a different number of elements up to the specified maximum. If the array size is not specified, the maximum size is assumed. + +Supported Operators +=================== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Operator + - Description + * - Literals + - An array literal can be created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3];`` + * - Mapping + - Parquet, ORC, JSON, and AVRO array types may be mapped into SQreamDB arrays + * - Indexing + - Access to specific elements within the array by using a zero-based index. For example, ``arr[2]`` returns the second array element + * - ``UNNEST`` + - Converts arrayed elements into a set of rows + * - Concatenate ``||`` + - Converts arrayed elements into one string + * - + - + * - + - + * - + - + * - + - + * - + - + * - + - + * - + - + * - + - + +Examples +======== +Creating a table with arrayed columns: + +.. code-block:: + + CREAT TABLE array (column1 TEXT[], column2 INT[]); + +Inserting arrayed values into a table: + +.. code-block:: + + INSERT INTO TABLE array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; + +Converting arrayed elements into a set of rows: + +.. code-block:: + + SELECT UNNEST(ARRAY['a','b','c'], ARRAY[1,2,3]); + +Output: + +.. code-block:: + + column1 | column2 + --------+---------- + a | 1 + b | 2 + c | 3 \ No newline at end of file diff --git a/data_type_guides/supported_casts.rst b/data_type_guides/supported_casts.rst index 34053b647..39844772b 100644 --- a/data_type_guides/supported_casts.rst +++ b/data_type_guides/supported_casts.rst @@ -14,4 +14,5 @@ The **Supported Casts** section describes supported casts for the following type sql_data_types_integer sql_data_types_floating_point sql_data_types_string - sql_data_types_date \ No newline at end of file + sql_data_types_date + sql_data_type_array \ No newline at end of file diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 740016249..abb5d59af 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -1,9 +1,8 @@ .. _supported_data_types: -************************* +******************** Supported Data Types -************************* -The **Supported Data Types** page describes SQream's supported data types: +******************** The following table shows the supported data types. @@ -71,5 +70,10 @@ The following table shows the supported data types. - 8 bytes - ``'1955-11-05 01:24:00.000'`` - ``TIMESTAMP``, ``DATETIME2`` + * - ``ARRAY`` + - Array of values + - Variable + - ``[1,2,3]`` + - NA .. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. \ No newline at end of file diff --git a/reference/index.rst b/reference/index.rst index f1a4a600e..6187b0b1f 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -1,13 +1,13 @@ .. _reference: -************************* -Reference Guides -************************* +********** +References +********** The **Reference Guides** section provides reference for using SQream DB's interfaces and SQL features. .. toctree:: - :maxdepth: 5 + :maxdepth: 1 :caption: In this section: :glob: From 0d98e0bf65afb920b23560876bb551c973293882 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Jun 2023 14:14:28 +0300 Subject: [PATCH 0632/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 29 ++++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 93ba46b82..9d67d9baf 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -15,7 +15,7 @@ Defining an array is done by appending the ``[]`` notation to a supported data t .. code-block:: - CREAT TABLE <table_name> (<column1> TEXT[], <column2> INT[]) + CREATE TABLE <table_name> (<column1> TEXT[], <column2> INT[]) INSERT INTO TABLE <table_name> VALUES ARRAY[<'a','b','c'>], ARRAY[<1,2,3>] @@ -66,9 +66,9 @@ Creating a table with arrayed columns: .. code-block:: - CREAT TABLE array (column1 TEXT[], column2 INT[]); + CREATE TABLE array (column1 TEXT[], column2 INT[]); -Inserting arrayed values into a table: +Inserting array values into a table: .. code-block:: @@ -79,13 +79,28 @@ Converting arrayed elements into a set of rows: .. code-block:: SELECT UNNEST(ARRAY['a','b','c'], ARRAY[1,2,3]); - -Output: .. code-block:: - column1 | column2 + column1 | column2 --------+---------- a | 1 b | 2 - c | 3 \ No newline at end of file + c | 3 + +Updating table values: + +.. code-block:: + + INSERT INTO TABLE array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; + + UPDATE array SET arr[0] = '{7,8,9}'; + + SELECT * FROM array; + +.. code-block:: + + column1 | column2 + --------+---------- + + \ No newline at end of file From 3949202824345ee89e5a5ca1364cf51fb1060154 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 26 Jun 2023 09:23:33 +0300 Subject: [PATCH 0633/1892] Update substring.rst --- .../sql/sql_functions/scalar_functions/string/substring.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/substring.rst b/reference/sql/sql_functions/scalar_functions/string/substring.rst index 205e83d5d..578a0e892 100644 --- a/reference/sql/sql_functions/scalar_functions/string/substring.rst +++ b/reference/sql/sql_functions/scalar_functions/string/substring.rst @@ -4,7 +4,7 @@ SUBSTRING ********* -Returns a substring of the input starting at ``start_pos``. +the ``SUBSTRING`` function is used to extract a portion of a string based on specified starting position and length. .. note:: Some systems call this function ``SUBSTR``. @@ -29,9 +29,9 @@ Arguments * - ``expr`` - Original string expression from which you want to extract the substring * - ``start_pos`` - - The start parameter, which accepts an integer or bigint expression, indicates the position from which the returned characters begin. If start is less than 1, the expression starts from the first character. The number of characters returned is determined by the larger value between start + length - 1 and 0. If start exceeds the number of characters in the expression, an empty string is returned + - Accepts an integer or bigint expression that specifies the position within the string where the extraction should begin. If start exceeds the number of characters in the expression, an empty string is returned. If start is less than 1, the expression starts from the first character * - ``length`` - - A positive integer or bigint expression that specifies the number of characters to be returned from the expression. If the sum of start and length exceeds the total number of characters in the expression, the entire value starting from the position specified by start is returned. If length is negative or zero, the function returns an empty string + - Accepts an integer or bigint expression that specifies the number of characters to be returned from the expression. If the sum of start and length exceeds the total number of characters in the expression, the entire value starting from the position specified by start is returned. If length is negative or zero, the function returns an empty string Returns ======= From 4e48f622356f0a62ca4e7cabb6126c0e5f2aa8db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Jun 2023 08:21:06 +0300 Subject: [PATCH 0634/1892] Update keywords_and_identifiers.rst --- .../sql/sql_syntax/keywords_and_identifiers.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 598b12a17..efe1ba42f 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -1,25 +1,26 @@ .. _keywords_and_identifiers: -*************************** +*********** Identifiers -*************************** +*********** + **Identifiers** are names given to SQL entities, such as tables, columns, databases, and variables. Identifiers must be unique so that entities can be correctly identified during the execution of a program. Identifiers can also be used to change a column name in the result (column alias) in a ``SELECT`` statement. Identifiers can be either quoted or unquoted and a maximum 128 characters long. Identifiers are sometimes referred to as "names". Regular identifiers must follow these rules: -* Must not contain any special characters except for underscores (``_``). -* Must be case-insensitive. SQream converts all identifiers to lowercase unless quoted. -* Does not equal any keywords, such as ``SELECT``, ``OR``, or ``AND``, etc. +* Must not contain a whitespace character or any special characters except for underscores (``_``) +* Must be case-insensitive. SQream converts all identifiers to lowercase unless quoted +* Does not equal any keywords, such as ``SELECT``, ``OR``, or ``AND``, etc -To bypass the rules above you can surround an identifier with double quotes (``"``) or square brackets (``[]``). +To bypass the rules above you can surround an identifier with double quotes (``"``). Quoted identifiers must follow these rules: -* Must be surrounded with double quotes (``"``) or square brackets (``[]``). +* Must be surrounded with double quotes (``"``) * May contain any ASCII character except ``@``, ``$`` or ``"``. -* Must be case-sensitive and referenced with double quotes or square brackets (``[]``). +* Must be case-sensitive and referenced with double quotes (``"``) Identifiers are different than **keywords**, which are predefined words reserved with specific meanings in a statement. Some examples of keywords are ``SELECT``, ``CREATE``, and ``WHERE``. Note that keywords **cannot** be used as identifiers. From 94ec11d0ef31f9f28ac32b8e72b2a9ba08b30ed4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Jun 2023 16:35:26 +0300 Subject: [PATCH 0635/1892] new flags --- .../default_graceful_shutdown_timeout_minutes.rst | 11 +++++++++++ .../healer_action_cleanup_connection.rst | 11 +++++++++++ .../healer_action_graceful_shutdown.rst | 11 +++++++++++ .../healer_detection_frequency_seconds.rst | 11 +++++------ .../healer_run_action_automatically.rst | 11 +++++++++++ configuration_guides/is_healer_on.rst | 7 +++---- .../max_connection_inactivity_seconds.rst | 12 ++++++++++++ .../max_statement_inactivity_seconds.rst | 12 ++++++++++++ 8 files changed, 76 insertions(+), 10 deletions(-) create mode 100644 configuration_guides/default_graceful_shutdown_timeout_minutes.rst create mode 100644 configuration_guides/healer_action_cleanup_connection.rst create mode 100644 configuration_guides/healer_action_graceful_shutdown.rst create mode 100644 configuration_guides/healer_run_action_automatically.rst create mode 100644 configuration_guides/max_connection_inactivity_seconds.rst create mode 100644 configuration_guides/max_statement_inactivity_seconds.rst diff --git a/configuration_guides/default_graceful_shutdown_timeout_minutes.rst b/configuration_guides/default_graceful_shutdown_timeout_minutes.rst new file mode 100644 index 000000000..dbdedcfcd --- /dev/null +++ b/configuration_guides/default_graceful_shutdown_timeout_minutes.rst @@ -0,0 +1,11 @@ +.. _default_graceful_shutdown_timeout_minutes: + +***************************************** +DEFAULT GRACEFUL SHUTDOWN TIMEOUT MINUTES +***************************************** + +The ``defaultGracefulShutdownTimeoutMinutes`` flag determines the duration of the default grace period for shutting down the system before forcefully terminating it. + +* **Data type** - size_t +* **Default value** - ``5`` +* **Allowed values** - 1-4000000000 \ No newline at end of file diff --git a/configuration_guides/healer_action_cleanup_connection.rst b/configuration_guides/healer_action_cleanup_connection.rst new file mode 100644 index 000000000..180d920df --- /dev/null +++ b/configuration_guides/healer_action_cleanup_connection.rst @@ -0,0 +1,11 @@ +.. _healer_action_cleanup_connection: + +******************************** +HEALER ACTION CLEANUP CONNECTION +******************************** + +The ``healerActionCleanupConnection`` enables the automatic cleanup of connections during the execution of healer actions, ensuring the proper management and termination of connections in the system. + +* **Data type** - Boolean +* **Default value** - ``true`` +* **Allowed values** - ``true`` or ``false`` \ No newline at end of file diff --git a/configuration_guides/healer_action_graceful_shutdown.rst b/configuration_guides/healer_action_graceful_shutdown.rst new file mode 100644 index 000000000..7787af229 --- /dev/null +++ b/configuration_guides/healer_action_graceful_shutdown.rst @@ -0,0 +1,11 @@ +.. _healer_action_graceful_shutdown: + +******************************* +HEALER ACTION GRACEFUL SHUTDOWN +******************************* + +The ``healerActionGracefulShutdown`` sets the option for performing a graceful shutdown during the execution of healer actions, allowing ongoing operations to complete before terminating the process or system. + +* **Data type** - Boolean +* **Default value** - ``false`` +* **Allowed values** - ``true`` or ``false`` \ No newline at end of file diff --git a/configuration_guides/healer_detection_frequency_seconds.rst b/configuration_guides/healer_detection_frequency_seconds.rst index a7c1939ad..cdb240faf 100644 --- a/configuration_guides/healer_detection_frequency_seconds.rst +++ b/configuration_guides/healer_detection_frequency_seconds.rst @@ -1,14 +1,13 @@ .. _healer_detection_frequency_seconds: -************************* +********************************** Healer Detection Frequency Seconds -************************* -The ``healerDetectionFrequencySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. +********************************** -The following describes the ``healerDetectionFrequencySeconds`` worker flag: +The ``healerDetectionFrequencySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. * **Data type** - size_t -* **Default value** - ``1`` -* **Allowed values** - 1-3600 +* **Default value** - ``60*60*24`` +* **Allowed values** - 1-4000000000 For related flags, see :ref:`is_healer_on`. \ No newline at end of file diff --git a/configuration_guides/healer_run_action_automatically.rst b/configuration_guides/healer_run_action_automatically.rst new file mode 100644 index 000000000..afb0578f9 --- /dev/null +++ b/configuration_guides/healer_run_action_automatically.rst @@ -0,0 +1,11 @@ +.. _healer_run_action_automatically: + +******************************* +HEALER RUN ACTION AUTOMATICALLY +******************************* + +The ``healerRunActionAutomatically`` flag determines whether the healer component automatically executes actions to resolve issues or requires manual intervention for each action. + +* **Data type** - Boolean +* **Default value** - ``true`` +* **Allowed values** - ``true`` or ``false`` \ No newline at end of file diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst index 1eb0e6384..add20259f 100644 --- a/configuration_guides/is_healer_on.rst +++ b/configuration_guides/is_healer_on.rst @@ -1,11 +1,10 @@ .. _is_healer_on: -************************* +************ Is Healer On -************************* -The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``maxStatementInactivitySeconds`` flag setting. +************ -The following describes the ``is_healer_on`` flag: +The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``maxStatementInactivitySeconds`` flag setting. * **Data type** - boolean * **Default value** - ``true`` diff --git a/configuration_guides/max_connection_inactivity_seconds.rst b/configuration_guides/max_connection_inactivity_seconds.rst new file mode 100644 index 000000000..31a4f36c7 --- /dev/null +++ b/configuration_guides/max_connection_inactivity_seconds.rst @@ -0,0 +1,12 @@ +.. _max_connection_inactivity_seconds: + +******************************** +MAX CONNECTION INACTIVITY SECONDS +******************************** + +The ``maxConnectionInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. + +* **Data type** - size_t +* **Default value** - ``60*60*24 - 86400`` +* **Allowed values** - ``1-4000000000`` + diff --git a/configuration_guides/max_statement_inactivity_seconds.rst b/configuration_guides/max_statement_inactivity_seconds.rst new file mode 100644 index 000000000..a6e35d28c --- /dev/null +++ b/configuration_guides/max_statement_inactivity_seconds.rst @@ -0,0 +1,12 @@ +.. _max_statement_inactivity_seconds: + +******************************** +MAX STATEMENT INACTIVITY SECONDS +******************************** + +The ``maxConnectionInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. + +* **Data type** - size_t +* **Default value** - ``5*60*60 seconds (18000)`` +* **Allowed values** - ``1-4000000000`` + From 43f69092384ffa415960e1dd0c49c16978287f13 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Jun 2023 17:23:31 +0300 Subject: [PATCH 0636/1892] Update healer_detection_frequency_seconds.rst --- configuration_guides/healer_detection_frequency_seconds.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/healer_detection_frequency_seconds.rst b/configuration_guides/healer_detection_frequency_seconds.rst index cdb240faf..f64497600 100644 --- a/configuration_guides/healer_detection_frequency_seconds.rst +++ b/configuration_guides/healer_detection_frequency_seconds.rst @@ -4,7 +4,7 @@ Healer Detection Frequency Seconds ********************************** -The ``healerDetectionFrequencySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. +The ``healerDetectionFrequencySeconds`` flag determines the default frequency for the healer to check that its conditions are met. * **Data type** - size_t * **Default value** - ``60*60*24`` From 80c75a0113df18222cfbf4c0f53acda99171e0fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jul 2023 09:05:35 +0300 Subject: [PATCH 0637/1892] Update current_method_configuring_your_parameter_values.rst --- .../current_method_configuring_your_parameter_values.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst index 1300b113d..027a1a710 100644 --- a/configuration_guides/current_method_configuring_your_parameter_values.rst +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -7,13 +7,13 @@ Parameter Values +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | **Command** | **Description** | **Example** | +=====================================================+===========================================================================================================================================+===============================================================================================================+ -| ``SET<flag_name>`` | Used for modifying flag attributes. | ``SET developerMode=true`` | +| ``SET<flag_name>`` | Used for modifying flag attributes. | ``SET enableLogDebug=false`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``SHOW <flag-name> / ALL`` | Used to preset either a specific flag value or all flag values. | ``SHOW <heartbeatInterval>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``SHOW ALL LIKE`` | Used as a wildcard character for flag names. | ``SHOW <heartbeat*>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``show_conf_UF`` | Used to print all flags with the following attributes: | ``rechunkThreshold,90,true,RND,regular`` | +| ``SELECT show_conf() ;`` | Used to print all flags with the following attributes: | ``rechunkThreshold,90,true,RND,regular`` | | | | | | | * Flag name | | | | * Default value | | @@ -21,7 +21,7 @@ Parameter Values | | * Flag category | | | | * Flag type | | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``show_conf_extended UF`` | Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. | ``rechunkThreshold,90,true,RND,regular`` | +| ``SELECT show_conf_extended();`` | Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. | ``rechunkThreshold,90,true,RND,regular`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``show_md_flag UF`` | Used to show a specific flag/all flags stored in the metadata file. |* Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` | | | |* Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` | From f8a89988da4fde30d74524f8e2d196bd6d334917 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:26:37 +0300 Subject: [PATCH 0638/1892] Update creating_your_first_table.rst --- getting_started/creating_your_first_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index 2837907f8..46701574d 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -60,7 +60,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t .. note:: - * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercases all identifiers bu default. If you want to maintain case, enclose the identifiers with double-quotes. + * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercase all identifiers by default. If you want to maintain case, enclose the identifiers with double-quotes. * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. From 25fdb4b80210e79e9448e6f9456dcdd47b96d38d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:27:12 +0300 Subject: [PATCH 0639/1892] Update creating_your_first_table.rst --- getting_started/creating_your_first_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index 46701574d..05c601c3e 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -60,7 +60,7 @@ You can list the full, verbose ``CREATE TABLE`` statement for a table by using t .. note:: - * SQream DB identifier names such as table names and column names are not case sensitive. SQream DB lowercase all identifiers by default. If you want to maintain case, enclose the identifiers with double-quotes. + * SQream DB identifier names such as table names and column names are not case sensitive. SQreamDB lowercases all identifiers by default. If you want to maintain case, enclose the identifiers with double-quotes. * SQream DB places all tables in the `public` schema, unless another schema is created and specified as part of the table name. For information on listing a ``CREATE TABLE`` statement, see :ref:`get_ddl`. From af3899a7dec01f83542bd8519efec6308edd400b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 6 Jul 2023 13:39:11 +0300 Subject: [PATCH 0640/1892] Update crc64.rst --- .../scalar_functions/numeric/crc64.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst index 8d067485d..4fb4dfdc0 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst @@ -1,20 +1,20 @@ .. _crc64: -************************** +***** CRC64 -************************** +***** -Calculates the CRC-64 hash of a text expression +The ``CRC64`` function calculates the CRC-64 hash of a text expression. Syntax -========== +====== .. code-block:: postgres CRC64( expr ) --> BIGINT Arguments -============ +========= .. list-table:: :widths: auto @@ -26,17 +26,17 @@ Arguments - Text expression (``TEXT``) Returns -============ +======= Returns a CRC-64 hash of the text input, of type ``BIGINT``. .. note:: If the input value is NULL, the result is NULL. Examples -=========== +======== Calculate a CRC-64 hash of a string ---------------------------------------- +----------------------------------- .. code-block:: psql From 31ae99b93455e2b3f9faaa5b552e0293e00e05fb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:05:35 +0300 Subject: [PATCH 0641/1892] Update sum.rst --- .../sql_functions/aggregate_functions/sum.rst | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/sum.rst b/reference/sql/sql_functions/aggregate_functions/sum.rst index 51d7f6d97..f33f0521e 100644 --- a/reference/sql/sql_functions/aggregate_functions/sum.rst +++ b/reference/sql/sql_functions/aggregate_functions/sum.rst @@ -1,14 +1,13 @@ .. _sum: -************************** +*** SUM -************************** +*** Returns the sum of numeric values, or only the distinct values. Syntax -========== - +====== .. code-block:: postgres @@ -23,7 +22,7 @@ Syntax ) Arguments -============ +========= .. list-table:: :widths: auto @@ -37,27 +36,27 @@ Arguments - Specifies that the operation should operate only on unique values Returns -============ +======= -Return type is dependant on the argument. +Return type is dependent on the argument. -* For ``TINYINT``, ``SMALLINT`` and ``INT``, the return type is ``INT``. +* For ``TINYINT``, ``SMALLINT`` and ``INT``, the return type is ``INT`` -* For ``BIGINT``, the return type is ``BIGINT``. +* For ``BIGINT``, the return type is ``BIGINT`` -* For ``REAL``, the return type is ``REAL`` +* For ``REAL``, the return type is ``DOUBLE`` * For ``DOUBLE``, rhe return type is ``DOUBLE`` Notes -======= +===== * ``NULL`` values are ignored * Because ``SUM`` returns the same data type, it can very quickly overflow on large data sets. If the SUM is over 2\ :sup:`31` for example, up-cast to a larger type like ``BIGINT``: ``SUM(expr :: BIGINT)`` Examples -=========== +======== For these examples, assume a table named ``nba``, with the following structure: @@ -85,7 +84,7 @@ Here's a peek at the table contents (:download:`Download nba.csv </_static/sampl :header-rows: 1 Simple sum -------------- +---------- .. code-block:: psql @@ -95,7 +94,7 @@ Simple sum 12311 Sum only distinct values ----------------------------- +------------------------ .. code-block:: psql @@ -105,7 +104,7 @@ Sum only distinct values 649 Combine sum with GROUP BY ------------------------------- +------------------------- .. code-block:: psql From 02a2b6d1a567739c8954831223f3503e87bb80ee Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:47:53 +0300 Subject: [PATCH 0642/1892] Update regexp_replace.rst --- .../string/regexp_replace.rst | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index dcf0f85ce..ff3a0cc6a 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -1,8 +1,9 @@ .. _regexp_replace: -************************** +************** REGEXP_REPLACE -************************** +************** + The ``REGEXP_REPLACE`` function finds and replaces text column substrings using constant regexp-based patterns with constant replacement strings. For related information, see the following: @@ -11,18 +12,16 @@ For related information, see the following: * :ref:`REGEXP_INSTR<regexp_instr>` * :ref:`REGEXP_SUBSTR<regexp_substr>` - - - Syntax ------- +====== .. code-block:: postgres REGEXP_REPLACE(input, pattern [, replacement [, position [, occurrence]]]) Arguments --------------- +========= + The following table shows the ``REGEXP_REPLACE`` arguments: .. list-table:: @@ -43,7 +42,7 @@ The following table shows the ``REGEXP_REPLACE`` arguments: - (Optional) Sets a specific occurrence to replace. Using ``0`` replaces all occurrences. Test Patterns -------------- +============= .. list-table:: :widths: auto @@ -90,16 +89,17 @@ Test Patterns Any character that does not have a defined special meaning inside a [] pair matches only itself. Returns -------- +======= + The ``REGEXP_REPLACE`` function returns the replaced input value. Notes ------ +===== + The test pattern must be a literal string. Example -------- -The following is an example of the ``REGEXP_REPLACE`` function: +======= .. code-block:: @@ -115,4 +115,3 @@ Output: ------------+ SPAIN | - From 00ac6247b7922581835aad58fdaea91fcd8cbbdd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 11:35:07 +0300 Subject: [PATCH 0643/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 44 ++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index df3e4f093..ea6f3606a 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -1,8 +1,9 @@ .. _hardware_guide: -*********************** +************** Hardware Guide -*********************** +************** + The **Hardware Guide** describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. .. rubric:: Need help? @@ -12,7 +13,8 @@ This page is intended as a "reference" to suggested hardware. However, different Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/customer/portals>`_ for additional support. A SQream Cluster -============================ +================ + SQream recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. A typical SQream cluster includes one or more nodes, consisting of @@ -28,7 +30,8 @@ A typical SQream cluster includes one or more nodes, consisting of * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. Single-Node Cluster Example ------------------------------------ +--------------------------- + A single-node SQream cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). An average single-node cluster can be a rackmount server or workstation, containing the following components: @@ -63,7 +66,8 @@ In this system configuration, SQream can store about 100TB of raw data (assuming If a NAS is used, the 10x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. Multi-Node Cluster Examples ------------------------------------ +--------------------------- + Multi-node clusters can handle any number of concurrent users. A typical SQream cluster relies on a minimum of two GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. The **Multi-Node Cluster Examples** section describes the following specifications: @@ -73,7 +77,8 @@ The **Multi-Node Cluster Examples** section describes the following specificatio :depth: 1 Hardware Specifications -~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ + The following table shows SQream's recommended hardware specifications: .. list-table:: @@ -102,7 +107,8 @@ The following table shows SQream's recommended hardware specifications: - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux Metadata Specifications -~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~ + The following table shows SQream's recommended metadata server specifications: .. list-table:: @@ -129,7 +135,8 @@ The following table shows SQream's recommended metadata server specifications: .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at up to 5GB/s. SQream Studio Server Example ------------------------------------ +---------------------------- + The following table shows SQream's recommended Studio server specifications: .. list-table:: @@ -150,7 +157,8 @@ The following table shows SQream's recommended Studio server specifications: - Red Hat Enterprise Linux v7.x or CentOS v7.x Cluster Design Considerations -==================================== +============================= + This section describes the following cluster design considerations: * In a SQream installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. @@ -168,7 +176,8 @@ This section describes the following cluster design considerations: * When using NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. Balancing Cost and Performance --------------------------------- +------------------------------ + Prior to designing and deploying a SQream cluster, a number of important factors must be considered. The **Balancing Cost and Performance** section provides a breakdown of deployment details to ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario, as shown in the following table: @@ -195,23 +204,27 @@ The **Balancing Cost and Performance** section provides a breakdown of deploymen - Balance price and performance CPU Compute -------------- +----------- + SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors, and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. GPU Compute and RAM -------------------------- +------------------- + The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla A100 40GB or H100 GPU for best performance and highest concurrent user support. GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. RAM --------- +--- + SQream requires using **Error-Correcting Code memory (ECC)**, standard on most enterprise servers. Large amounts of memory are required for improved performance for heavy external operations, such as sorting and joining. SQream recommends at least 256GB of RAM per GPU on your machine. Operating System ---------------------- +---------------- + SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7 @@ -220,7 +233,8 @@ SQream can run on the following 64-bit Linux operating systems: * Other Linux distributions may be supported via nvidia-docker Storage ------------ +------- + For clustered scale-out installations, SQream relies on NAS storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. From 6de9cce6afdc34abfd6a9570be9374ea27e47099 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 13:54:53 +0300 Subject: [PATCH 0644/1892] Short ingestion menu items --- data_ingestion/avro.rst | 67 ++++++++++++++------- data_ingestion/csv.rst | 30 ++++----- data_ingestion/index.rst | 8 ++- data_ingestion/ingesting_data.rst | 44 +++++++++----- data_ingestion/ingesting_from_databases.rst | 1 + data_ingestion/json.rst | 2 +- data_ingestion/orc.rst | 26 ++++---- data_ingestion/parquet.rst | 6 +- 8 files changed, 111 insertions(+), 73 deletions(-) create mode 100644 data_ingestion/ingesting_from_databases.rst diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index a548ec265..f471830af 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -1,8 +1,9 @@ .. _avro: -************************** -Ingesting Data from Avro -************************** +**** +Avro +**** + The **Ingesting Data from Avro** page describes ingesting data from Avro into SQream and includes the following: @@ -12,11 +13,13 @@ The **Ingesting Data from Avro** page describes ingesting data from Avro into SQ :depth: 1 Overview -=========== +======== + **Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. Avro files are represented using the **Object Container File** format, in which the Avro schema is encoded alongside binary data. Multiple files loaded in the same transaction are serialized using the same schema. If they are not serialized using the same schema, an error message is displayed. SQream uses the **.avro** extension for ingested Avro files. Making Avro Files Accessible to Workers -================ +======================================= + To give workers access to files every node must have the same view of the storage being used. The following apply for Avro files to be accessible to workers: @@ -30,7 +33,8 @@ The following apply for Avro files to be accessible to workers: For more information about restricted worker access, see :ref:`workload_manager`. Preparing Your Table -=============== +==================== + You can build your table structure on both local and foreign tables: .. contents:: @@ -38,7 +42,8 @@ You can build your table structure on both local and foreign tables: :depth: 1 Creating a Table ---------------------- +---------------- + Before loading data, you must build the ``CREATE TABLE`` to correspond with the file structure of the inserted table. The example in this section is based on the source ``nba.avro`` table shown below: @@ -78,7 +83,8 @@ The following example shows the correct file structure used to create the ``CREA .. note:: The **nba.avro** file is stored on S3 at ``s3://sqream-demo-data/nba.avro``. Creating a Foreign Table ---------------------- +------------------------ + Before loading data, you must build the ``CREATE FOREIGN TABLE`` to correspond with the file structure of the inserted table. The example in this section is based on the source ``nba.avro`` table shown below: @@ -120,7 +126,8 @@ The following example shows the correct file structure used to create the ``CREA .. note:: The examples in the sections above are identical except for the syntax used to create the tables. Mapping Between SQream and Avro Data Types -================= +========================================== + Mapping between SQream and Avro data types depends on the Avro data type: .. contents:: @@ -128,7 +135,8 @@ Mapping between SQream and Avro data types depends on the Avro data type: :depth: 1 Primitive Data Types --------------- +-------------------- + The following table shows the supported **Primitive** data types: +-------------+------------------------------------------------------+ @@ -154,7 +162,8 @@ The following table shows the supported **Primitive** data types: +-------------+-----------+---------------+-----------+--------------+ Complex Data Types --------------- +------------------ + The following table shows the supported **Complex** data types: +------------+-------------------------------------------------------+ @@ -176,7 +185,8 @@ The following table shows the supported **Complex** data types: +------------+------------+----------------+-------------+-----------+ Logical Data Types --------------- +------------------ + The following table shows the supported **Logical** data types: +----------------------------+-------------------------------------------------+ @@ -208,11 +218,13 @@ The following table shows the supported **Logical** data types: .. note:: Number types include **tinyint**, **smallint**, **int**, **bigint**, **real** and **float**, and **numeric**. String types include **text**. Mapping Objects to Rows -=============== +======================= + When mapping objects to rows, each Avro object or message must contain one ``record`` type object corresponding to a single row in SQream. The ``record`` fields are associated by name to their target table columns. Additional unmapped fields will be ignored. Note that using the JSONPath option overrides this. Ingesting Data into SQream -============== +========================== + This section includes the following: .. contents:: @@ -220,7 +232,8 @@ This section includes the following: :depth: 1 Syntax ------------ +------ + Before ingesting data into SQream from an Avro file, you must create a table using the following syntax: .. code-block:: postgres @@ -236,7 +249,8 @@ After creating a table you can ingest data from an Avro file into SQream using t avro_fdw Example ------------ +------- + The following is an example of creating a table: .. code-block:: postgres @@ -262,7 +276,8 @@ The following is an example of loading data from an Avro file into SQream: For more examples, see :ref:`additional_examples`. Parameters -=================== +========== + The following table shows the Avro parameter: .. list-table:: @@ -275,7 +290,8 @@ The following table shows the Avro parameter: - The schema name for the table. Defaults to ``public`` if not specified. Best Practices -============ +============== + Because external tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Avro files into SQream. This lets you determine if your table output is identical to your originally inserted table. The following is an example of the output based on the **nba.avro** table: @@ -301,7 +317,8 @@ The following is an example of the output based on the **nba.avro** table: .. _additional_examples: Additional Examples -=============== +=================== + This section includes the following additional examples of loading data into SQream: .. contents:: @@ -309,7 +326,8 @@ This section includes the following additional examples of loading data into SQr :depth: 1 Omitting Unsupported Column Types --------------- +--------------------------------- + When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. In the example below, the ``Position`` column is not supported due its type. @@ -320,7 +338,8 @@ In the example below, the ``Position`` column is not supported due its type. SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; Modifying Data Before Loading --------------- +----------------------------- + One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement @@ -335,7 +354,8 @@ In the example below, the ``Position`` column is set to the default ``NULL``. ORDER BY weight; Loading a Table from a Directory of Avro Files on HDFS --------------- +------------------------------------------------------ + The following is an example of loading a table from a directory of Avro files on HDFS: .. code-block:: postgres @@ -353,7 +373,8 @@ The following is an example of loading a table from a directory of Avro files on For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. Loading a Table from a Directory of Avro Files on S3 --------------- +---------------------------------------------------- + The following is an example of loading a table from a directory of Avro files on S3: .. code-block:: postgres diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index db63a38ca..993bcb2a7 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -1,8 +1,8 @@ .. _csv: -********************** -Ingesting Data from a CSV File -********************** +*** +CSV +*** This guide covers ingesting data from CSV files into SQream DB using the :ref:`copy_from` method. @@ -12,7 +12,7 @@ This guide covers ingesting data from CSV files into SQream DB using the :ref:`c :depth: 1 Prepare CSVs -===================== +============ Prepare the source CSVs, with the following requirements: @@ -131,21 +131,21 @@ Loading a standard CSV file from a local filesystem Loading a PSV (pipe separated value) file -------------------------------------------- +----------------------------------------- .. code-block:: postgres COPY table_name FROM '/home/rhendricks/file.psv' WITH DELIMITER '|'; Loading a TSV (tab separated value) file -------------------------------------------- +---------------------------------------- .. code-block:: postgres COPY table_name FROM '/home/rhendricks/file.tsv' WITH DELIMITER '\t'; Loading a text file with non-printable delimiter ------------------------------------------------------ +------------------------------------------------ In the file below, the separator is ``DC1``, which is represented by ASCII 17 decimal or 021 octal. @@ -154,7 +154,7 @@ In the file below, the separator is ``DC1``, which is represented by ASCII 17 de COPY table_name FROM 'file.txt' WITH DELIMITER E'\021'; Loading a text file with multi-character delimiters ------------------------------------------------------ +--------------------------------------------------- In the file below, the separator is ``'|``. @@ -163,7 +163,7 @@ In the file below, the separator is ``'|``. COPY table_name FROM 'file.txt' WITH DELIMITER '''|'; Loading files with a header row ------------------------------------ +------------------------------- Use ``OFFSET`` to skip rows. @@ -176,14 +176,14 @@ Use ``OFFSET`` to skip rows. .. _changing_record_delimiter: Loading files formatted for Windows (``\r\n``) ---------------------------------------------------- +---------------------------------------------- .. code-block:: postgres COPY table_name FROM 'filename.psv' WITH DELIMITER '|' RECORD DELIMITER '\r\n'; Loading a file from a public S3 bucket ------------------------------------------- +-------------------------------------- .. note:: The bucket must be publicly available and objects can be listed @@ -209,7 +209,7 @@ Loading files from an HDFS storage Saving rejected rows to a file ----------------------------------- +------------------------------ See :ref:`capturing_rejected_rows` for more information about the error handling capabilities of ``COPY FROM``. @@ -235,7 +235,7 @@ Stopping the load if a certain amount of rows were rejected STOP AFTER 5 ERRORS; -- Stop the load if 5 errors reached Load CSV files from a set of directories ------------------------------------------- +---------------------------------------- Use glob patterns (wildcards) to load multiple files to one table. @@ -245,7 +245,7 @@ Use glob patterns (wildcards) to load multiple files to one table. Rearrange destination columns ---------------------------------- +----------------------------- When the source of the files does not match the table structure, tell the ``COPY`` command what the order of columns should be @@ -256,7 +256,7 @@ When the source of the files does not match the table structure, tell the ``COPY .. note:: Any column not specified will revert to its default value or ``NULL`` value if nullable Loading non-standard dates ----------------------------------- +-------------------------- If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQream DB. diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index 290e0fce3..ad3e27e93 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -1,8 +1,9 @@ .. _data_ingestion: -************************* +********************** Data Ingestion Sources -************************* +********************** + The **Data Ingestion Sources** page provides information about the following: .. toctree:: @@ -15,5 +16,6 @@ The **Data Ingestion Sources** page provides information about the following: parquet orc json + ingesting_from_databases -For information about database tools and interfaces that SQream supports, see `Third Party Tools <https://docs.sqream.com/en/v2022.1.1/connecting_to_sqream/index.html>`_. \ No newline at end of file +For information about database tools and interfaces that SQream supports, see :ref:`Third Party Tools <connecting_to_sqream>`. \ No newline at end of file diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index 97d57ef4c..db157f6b4 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -1,8 +1,9 @@ .. _ingesting_data: -*************************** -Ingesting Data Overview -*************************** +******** +Overview +******** + The **Ingesting Data Overview** page provides basic information useful when ingesting data into SQream from a variety of sources and locations, and describes the following: .. contents:: @@ -10,7 +11,8 @@ The **Ingesting Data Overview** page provides basic information useful when inge :depth: 1 Getting Started -================================ +=============== + SQream supports ingesting data using the following methods: * Executing the ``INSERT`` statement using a client driver. @@ -44,7 +46,8 @@ For more information, see the following: * Loading data from foreign tables - :ref:`foreign_tables` Data Loading Considerations -================================ +=========================== + The **Data Loading Considerations** section describes the following: .. contents:: @@ -52,7 +55,8 @@ The **Data Loading Considerations** section describes the following: :depth: 1 Verifying Data and Performance after Loading ------------------------------------------ +-------------------------------------------- + Like many RDBMSs, SQream recommends its own set of best practices for table design and query optimization. When using SQream, verify the following: * That your data is structured as you expect (row counts, data types, formatting, content). @@ -67,6 +71,7 @@ Like many RDBMSs, SQream recommends its own set of best practices for table desi File Soure Location when Loading -------------------------------- + While you are loading data, you can use the ``COPY FROM`` command to let statements run on any worker. If you are running multiple nodes, verify that all nodes can see the source the same. Loading data from a local file that is only on one node and not on shared storage may cause it to fail. If required, you can also control which node a statement runs on using the Workload Manager). For more information, see the following: @@ -76,7 +81,8 @@ For more information, see the following: * :ref:`workload_manager` Supported Load Methods -------------------------------- +---------------------- + You can use the ``COPY FROM`` syntax to load CSV files. .. note:: The ``COPY FROM`` cannot be used for loading data from Parquet and ORC files. @@ -118,17 +124,20 @@ For more information, see the following: * :ref:`INSERT<insert>` Unsupported Data Types ------------------------------ +---------------------- + SQream does not support certain features that are supported by other databases, such as ``ARRAY``, ``BLOB``, ``ENUM``, and ``SET``. You must convert these data types before loading them. For example, you can store ``ENUM`` as ``TEXT``. Handing Extended Errors ----------------------------- +----------------------- + While you can use foreign tables to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options and extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. For more information, see :ref:`foreign tables<foreign_tables>`. Best Practices for CSV ------------------------------- +---------------------- + Text files, such as CSV, rarely conform to `RFC 4180 <https://tools.ietf.org/html/rfc4180>`_ , so you may need to make the following modifications: * Use ``OFFSET 2`` for files containing header rows. @@ -148,7 +157,8 @@ Text files, such as CSV, rarely conform to `RFC 4180 <https://tools.ietf.org/htm * Field delimiters do not have to be a displayable ASCII character. For all supported field delimiters, see :ref:`field_delimiters`. Best Practices for Parquet --------------------------------- +-------------------------- + The following list shows the best practices when ingesting data from Parquet files: * You must load Parquet files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. @@ -156,7 +166,8 @@ The following list shows the best practices when ingesting data from Parquet fil * Parquet files support **predicate pushdown**. When a query is issued over Parquet files, SQream uses row-group metadata to determine which row-groups in a file must be read for a particular query and the row indexes can narrow the search to a particular set of rows. Supported Types and Behavior Notes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Unlike the ORC format, the column types should match the data types exactly, as shown in the table below: .. list-table:: @@ -269,7 +280,8 @@ Unlike the ORC format, the column types should match the data types exactly, as If a Parquet file has an unsupported type, such as ``enum``, ``uuid``, ``time``, ``json``, ``bson``, ``lists``, ``maps``, but the table does not reference this data (i.e., the data does not appear in the :ref:`SELECT` query), the statement will succeed. If the table **does** reference a column, an error will be displayed explaining that the type is not supported, but the column may be omitted. Best Practices for ORC --------------------------------- +---------------------- + The following list shows the best practices when ingesting data from ORC files: * You must load ORC files through :ref:`foreign_tables`. Note that the destination table structure must be identical to the number of columns between the source files. @@ -277,7 +289,8 @@ The following list shows the best practices when ingesting data from ORC files: * ORC files support **predicate pushdown**. When a query is issued over ORC files, SQream uses ORC metadata to determine which stripes in a file need to be read for a particular query and the row indexes can narrow the search to a particular set of 10,000 rows. Type Support and Behavior Notes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + You must load ORC files through foreign table. Note that the destination table structure must be identical to the number of columns between the source files. For more information, see :ref:`foreign_tables`. @@ -457,7 +470,8 @@ The types should match to some extent within the same "class", as shown in the f try to combine sensibly with the external table stuff Further Reading and Migration Guides -======================================= +==================================== + For more information, see the following: * :ref:`copy_from` diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst new file mode 100644 index 000000000..86ee4e369 --- /dev/null +++ b/data_ingestion/ingesting_from_databases.rst @@ -0,0 +1 @@ +.. _ingesting_from_databases: ****************** External Databases ****************** .. contents:: :local: :depth: 1 Making JSON Files Accessible to Workers ======================================= Mapping between JSON and SQream =============================== Character Escaping ------------------ Ingesting JSON Data into SQream =============================== Syntax ------- Parameters ---------- Automatic Schema Inference -------------------------- Examples -------- \ No newline at end of file diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 50fe2258c..1c47b892e 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: ************************** Ingesting Data from JSON ************************** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ------------ The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference --------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples ------------ JSON object array: .. code-block:: postgres { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: postgres [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON object array: .. code-block:: postgres { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: postgres [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index 4906a80de..397dd7946 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -1,8 +1,8 @@ .. _orc: -********************** -Ingesting Data from an ORC File -********************** +*** +ORC +*** .. contents:: :local: @@ -12,7 +12,7 @@ This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREI Prepare the files -===================== +================= Prepare the source ORC files, with the following requirements: @@ -158,7 +158,7 @@ Prepare the source ORC files, with the following requirements: .. [#f7] Will succeed if all values fit the destination type Place ORC files where SQream DB workers can access them -================================================================ +======================================================= Any worker may try to access files (unless explicitly speficied with the :ref:`workload_manager`). It is important that every node has the same view of the storage being used - meaning, every SQream DB worker should have access to the files. @@ -170,7 +170,7 @@ It is important that every node has the same view of the storage being used - me * For S3, ensure network access to the S3 endpoint. See our :ref:`s3` guide for more information. Figure out the table structure -=============================================== +============================== Prior to loading data, you will need to write out the table structure, so that it matches the file structure. @@ -214,7 +214,7 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA Verify table contents -==================================== +===================== External tables do not verify file integrity or structure, so verify that the table definition matches up and contains the correct data. @@ -237,7 +237,7 @@ External tables do not verify file integrity or structure, so verify that the ta If any errors show up at this stage, verify the structure of the ORC files and match them to the external table structure you created. Copying data into SQream DB -=================================== +=========================== To load the data into SQream DB, use the :ref:`create_table_as` statement: @@ -247,7 +247,7 @@ To load the data into SQream DB, use the :ref:`create_table_as` statement: SELECT * FROM ext_nba; Working around unsupported column types ---------------------------------------------- +--------------------------------------- Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. @@ -264,7 +264,7 @@ For this example, assume that the ``Position`` column isn't supported because of Modifying data during the copy process ------------------------------------------- +-------------------------------------- One of the main reasons for staging data with ``EXTERNAL TABLE`` is to examine the contents and modify them before loading them. @@ -281,13 +281,13 @@ Similar to the previous example, we will also set the ``Position`` column as a d Further ORC loading examples -======================================= +============================ :ref:`create_foreign_table` contains several configuration options. See more in :ref:`the CREATE FOREIGN TABLE parameters section<cft_parameters>`. Loading a table from a directory of ORC files on HDFS ------------------------------------------------------------- +----------------------------------------------------- .. code-block:: postgres @@ -302,7 +302,7 @@ Loading a table from a directory of ORC files on HDFS CREATE TABLE users AS SELECT * FROM ext_users; Loading a table from a bucket of files on S3 ------------------------------------------------ +-------------------------------------------- .. code-block:: postgres diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index bb6bf05bb..a77563734 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -1,8 +1,8 @@ .. _parquet: -********************** -Ingesting Data from a Parquet File -********************** +******* +Parquet +******* Ingesting Parquet files into SQream is generally useful when you want to store the data permanently and perform frequent queries on it. Ingesting the data can also make it easier to join with other tables in your database. However, if you wish to retain your data on external Parquet files instead of ingesting it into SQream due to it being an open-source column-oriented data storage format, you may also execute :ref:`FOREIGN TABLE<foreign_tables>` queries. From 99772b831f0aa76e972cf75932a601d7067907ee Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 14:10:41 +0300 Subject: [PATCH 0645/1892] Short menu items --- .../client_drivers/Spark/index.rst | 6 +-- .../client_drivers/dotnet/index.rst | 36 +++++++++------ connecting_to_sqream/client_drivers/index.rst | 6 ++- .../client_drivers/jdbc/index.rst | 33 ++++++++----- .../client_drivers/nodejs/index.rst | 46 +++++++++---------- .../client_drivers/odbc/index.rst | 4 +- .../client_drivers/python/index.rst | 20 +++++--- .../client_drivers/trino/index.rst | 10 ++-- .../client_platforms/index.rst | 7 +-- .../client_platforms/informatica.rst | 22 +++++---- .../client_platforms/microstrategy.rst | 20 ++++---- .../client_platforms/pentaho.rst | 24 ++++++---- connecting_to_sqream/client_platforms/php.rst | 18 +++++--- .../client_platforms/power_bi.rst | 22 +++++---- connecting_to_sqream/client_platforms/r.rst | 14 +++--- .../client_platforms/sap_businessobjects.rst | 15 +++--- .../client_platforms/sas_viya.rst | 40 ++++++++++------ .../client_platforms/sql_workbench.rst | 24 +++++----- .../client_platforms/tableau.rst | 8 ++-- .../client_platforms/talend.rst | 23 ++++++---- .../client_platforms/tibco_spotfire.rst | 37 +++++++++------ 21 files changed, 260 insertions(+), 175 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index a7b031e53..e6ce90ade 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -1,8 +1,8 @@ .. _spark: -************************* -Using Spark With SQream -************************* +***** +Spark +***** The Spark connector enables reading and writing data to and from SQreamDB and may be used for large-scale data processing. diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index ed0c61557..22512fd93 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -1,8 +1,9 @@ .. _net: -************************* -Connecting to SQream Using .NET -************************* +**** +.NET +**** + The SqreamNet ADO.NET Data Provider lets you connect to SQream through your .NET environment. The .NET page includes the following sections: @@ -12,7 +13,8 @@ The .NET page includes the following sections: :depth: 1 Integrating SQreamNet -================================== +===================== + The **Integrating SQreamNet** section describes the following: .. contents:: @@ -20,28 +22,33 @@ The **Integrating SQreamNet** section describes the following: :depth: 1 Prerequisites ----------------- +------------- + The SqreamNet provider requires a .NET version 6 or newer. Getting the DLL file ----------------- +-------------------- + The .NET driver is available for download from the :ref:`client drivers download page<client_drivers>`. Integrating SQreamNet -------------------------- +--------------------- + After downloading the .NET driver, save the archive file to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. Known Driver Limitations ----------------------------- +------------------------ + * Unicode characters are not supported when using ``INSERT INTO AS SELECT``. * To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. Connecting to SQream For the First Time -============================================== +======================================= + An initial connection to SQream must be established by creating a **SqreamConnection** object using a connection string. .. contents:: @@ -50,7 +57,8 @@ An initial connection to SQream must be established by creating a **SqreamConnec Connection String --------------------- +----------------- + To connect to SQream, instantiate a **SqreamConnection** object using this connection string. The following is the syntax for SQream: @@ -60,7 +68,7 @@ The following is the syntax for SQream: "Data Source=<hostname or ip>,<port>;User=<username>;Password=<password>;Initial Catalog=<database name>;Integrated Security=true"; Connection Parameters -^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto @@ -100,7 +108,8 @@ Connection Parameters - Connect via load balancer (use only if exists, and check port). Connection String Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following is an example of a SQream cluster with load balancer and no service queues (with SSL): .. code-block:: text @@ -122,7 +131,8 @@ The following is an example of a SQream cluster with load balancer and a specifi Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=raviga;Integrated Security=true;service=etl;cluster=true; Sample C# Program --------------------- +----------------- + You can download the :download:`.NET Application Sample File <sample.cs>` below by right-clicking and saving it to your computer. .. literalinclude:: sample.cs diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index dbbd33933..5a8faeeef 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -7,10 +7,11 @@ Client Drivers The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. Client Driver Downloads -============================= +======================= All Operating Systems ---------------------------- +--------------------- + The following are applicable to all operating systems: .. _jdbc: @@ -75,6 +76,7 @@ The following are applicable to all operating systems: Windows ------- + The following are applicable to Windows: * For the **ODBC installer**, please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_. diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 3f625759c..db7b1602c 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -1,8 +1,9 @@ .. _java_jdbc: -************************* +**** JDBC -************************* +**** + The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. .. contents:: @@ -10,7 +11,8 @@ The SQream JDBC driver lets you connect to SQream using many Java applications a :depth: 1 Installing the JDBC Driver -================================== +========================== + The **Installing the JDBC Driver** section describes the following: .. contents:: @@ -18,7 +20,8 @@ The **Installing the JDBC Driver** section describes the following: :depth: 1 Prerequisites ----------------- +------------- + The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: * **Oracle Java** - Download and install `Java 8 <https://www.java.com/en/download/manual.jsp>`_ from Oracle for your platform. @@ -32,12 +35,14 @@ The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using O * **Windows** - SQream recommends installing `Zulu 8 <https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk>`_ Getting the JAR file ---------------------- +-------------------- + The SQream JDBC driver is available for download from the :ref:`client drivers download page<client_drivers>`. This JAR file can be integrated into your Java-based applications or projects. Setting Up the Class Path ----------------------------- +------------------------- + To use the driver, you must include the JAR named ``sqream-jdbc-<version>.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: @@ -54,7 +59,8 @@ Alternatively, you can pass ``-classpath`` to the Java executable file: $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app Connecting to SQream Using a JDBC Application -============================================== +============================================= + You can connect to SQream using one of the following JDBC applications: .. contents:: @@ -62,11 +68,13 @@ You can connect to SQream using one of the following JDBC applications: :depth: 1 Driver Class --------------- +------------ + Use ``com.sqream.jdbc.SQDriver`` as the driver class in the JDBC application. Connection String --------------------- +----------------- + JDBC drivers rely on a connection string. The following is the syntax for SQream: @@ -76,7 +84,8 @@ The following is the syntax for SQream: jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>sqream;[<optional parameters>; ...] Connection Parameters -^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ + The following table shows the connection string parameters: .. list-table:: @@ -137,7 +146,8 @@ The following table shows the connection string parameters: - Sets the duration, in seconds, for which a database connection can remain idle before it is terminated. If the parameter is set to its default value, idle connections will not be terminated. The idle connection timer begins counting after the completion of a query execution. Connection String Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following is an example of a SQream cluster with load balancer and no service queues (with SSL): .. code-block:: text @@ -158,6 +168,7 @@ The following is an example of a SQream cluster with load balancer and a specifi Sample Java Program -------------------- + You can download the :download:`JDBC Application Sample File <sample.java>` below by right-clicking and saving it to your computer. .. literalinclude:: sample.java diff --git a/connecting_to_sqream/client_drivers/nodejs/index.rst b/connecting_to_sqream/client_drivers/nodejs/index.rst index 94b84a072..ad90bc4f7 100644 --- a/connecting_to_sqream/client_drivers/nodejs/index.rst +++ b/connecting_to_sqream/client_drivers/nodejs/index.rst @@ -1,8 +1,8 @@ .. _nodejs: -************************* -Connecting to SQream Using Node.JS -************************* +******* +Node.JS +******* The SQream DB Node.JS driver allows Javascript applications and tools connect to SQream DB. This tutorial shows you how to write a Node application using the Node.JS interface. @@ -13,15 +13,15 @@ The driver requires Node 10 or newer. :local: Installing the Node.JS driver -================================== +============================= Prerequisites ----------------- +------------- * Node.JS 10 or newer. Follow instructions at `nodejs.org <https://nodejs.org/en/download/package-manager/>`_ . Install with NPM -------------------- +---------------- Installing with npm is the easiest and most reliable method. If you need to install the driver in an offline system, see the offline method below. @@ -31,7 +31,7 @@ If you need to install the driver in an offline system, see the offline method b $ npm install @sqream/sqreamdb Install from an offline package -------------------------------------- +------------------------------- The Node driver is provided as a tarball for download from the `SQream Drivers page <http://sqream.com/product/client-drivers>`_ . @@ -43,10 +43,10 @@ After downloading the tarball, use ``npm`` to install the offline package. Connect to SQream DB with a Node.JS application -==================================================== +=============================================== Create a simple test ------------------------------------------- +-------------------- Replace the connection parameters with real parameters for a SQream DB installation. @@ -77,7 +77,7 @@ Replace the connection parameters with real parameters for a SQream DB installat Run the test ----------------- +------------ A successful run should look like this: @@ -88,10 +88,10 @@ A successful run should look like this: API reference -==================== +============= Connection parameters ---------------------------- +--------------------- .. list-table:: :widths: auto @@ -135,7 +135,7 @@ Connection parameters - Connect via load balancer (use only if exists, and check port). For example, ``true`` Events -------------- +------ The connector handles event returns with an event emitter @@ -149,7 +149,7 @@ getTypes The ``getTypes`` event returns the results columns types. Example -^^^^^^^^^^^^^^^^^ +^^^^^^^ .. code-block:: javascript @@ -170,7 +170,7 @@ Example }); Input placeholders -------------------------- +------------------ The Node.JS driver can replace parameters in a statement. @@ -196,10 +196,10 @@ The valid placeholder formats are provided in the table below. See the :ref:`input placeholders example<input_placeholders_example>` below. Examples -=============== +======== Setting configuration flags ------------------------------------ +--------------------------- SQream DB configuration flags can be set per statement, as a parameter to ``runQuery``. @@ -218,7 +218,7 @@ For example: Lazyloading ------------------------------------ +----------- To process rows without keeping them in memory, you can lazyload the rows with an async: @@ -259,7 +259,7 @@ To process rows without keeping them in memory, you can lazyload the rows with a Reusing a connection ------------------------------------ +-------------------- It is possible to execeute multiple queries with the same connection (although only one query can be executed at a time). @@ -304,7 +304,7 @@ It is possible to execeute multiple queries with the same connection (although o .. _input_placeholders_example: Using placeholders in queries ------------------------------------ +----------------------------- Input placeholders allow values like user input to be passed as parameters into queries, with proper escaping. @@ -334,11 +334,11 @@ The query that will run is ``SELECT col1 FROM public.table2 WHERE name = 'john'' Troubleshooting and recommended configuration -================================================ +============================================= Preventing ``heap out of memory`` errors --------------------------------------------- +---------------------------------------- Some workloads may cause Node.JS to fail with the error: @@ -355,7 +355,7 @@ For example, set the space size to 2GB: $ node --max-old-space-size=2048 my-application.js BIGINT support ------------------------- +-------------- The Node.JS connector supports fetching ``BIGINT`` values from SQream DB. However, some applications may encounter an error when trying to serialize those values. diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 195bc6897..e4895b3bc 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -1,8 +1,8 @@ .. _odbc: -************************* +**** ODBC -************************* +**** .. toctree:: :maxdepth: 1 diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 12b4a7b3b..938a8847d 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -1,8 +1,8 @@ .. _pysqream: -************************* -Connecting to SQream Using Python (pysqream) -************************* +***************** +Python (pysqream) +***************** The current Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQream DB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. @@ -14,7 +14,7 @@ The current Pysqream connector supports Python version 3.9 and newer. It include :depth: 1 Installing the Python Connector -================================== +=============================== Prerequisites ------------- @@ -39,6 +39,7 @@ To see your current Python version, run the following command: PIP ~~~ + The Python connector is installed via ``pip``, the standard package manager for Python, which is used to install, upgrade and manage Python packages (libraries) and their dependencies. We recommend upgrading to the latest version of ``pip`` before installing. @@ -64,6 +65,7 @@ To verify that you have the latest version, run the following command: OpenSSL for Linux ~~~~~~~~~~~~~~~~~ + The Python connector relies on OpenSSL for secure connections to SQream DB. Some distributions of Python do not include OpenSSL. To install OpenSSL on RHEL/CentOS, run the following command: @@ -81,6 +83,7 @@ To install OpenSSL on Ubuntu, run the following command: Installing via PIP with an internet connection ---------------------------------------------- + The Python connector is available via `PyPi <https://pypi.org/project/pysqream/>`_. To install the connector using pip, it is advisable to use the ``-U`` or ``--user`` flags instead of sudo, as it ensures packages are installed per user. However, it is worth noting that the connector can only be accessed under the same user. @@ -94,7 +97,7 @@ To install ``pysqream`` and ``pysqream-sqlalchemy`` with the ``--user`` flag, ru ``pip3`` will automatically install all necessary libraries and modules. Installing via PIP without an internet connection ----------------------------------------------- +------------------------------------------------- #. To get the ``.whl`` package file, contact you SQream support representative. @@ -110,7 +113,8 @@ Installing via PIP without an internet connection python3.9 -m pip install pysqream-sqlalchemy-0.8.zip -U --no-index --find-links . Upgrading an Existing Installation --------------------------------------- +---------------------------------- + The Python drivers are updated periodically. To upgrade an existing pysqream installation, use pip's ``-U`` flag: .. code-block:: console @@ -172,6 +176,7 @@ Creating a Standard Connection Pulling a Table into Pandas --------------------------- + The following example shows how to pull a table in Pandas. This examples uses the URL method to create the connection string: .. code-block:: python @@ -271,6 +276,7 @@ The following is an example of the contents of the row variables used in our exa Reading Result Metadata ----------------------- + When you execute a statement, the connection object also contains metadata about the result set, such as **column names**, **types**, etc). The metadata is stored in the :py:attr:`Connection.description` object of the cursor: @@ -297,6 +303,7 @@ You can fetch a list of column names by iterating over the ``description`` list: Loading Data into a Table ------------------------- + This example shows how to load 10,000 rows of dummy data to an instance of SQream. **To load data 10,000 rows of dummy data to an instance of SQream:** @@ -373,6 +380,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea Using SQLAlchemy ORM to Create and Populate Tables -------------------------------------------------- + This section shows how to use the ORM to create and populate tables from Python objects. **To use SQLAlchemy ORM to create and populate tables:** diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index 6a8ac9bac..700e15801 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -1,8 +1,8 @@ .. _trino: -************************* -Connecting to SQream Using Trino -************************* +***** +Trino +***** If you are using Trino for distributed SQL query processing and wish to use it to connect to a SQream, follow these instructions. @@ -14,6 +14,7 @@ If you are using Trino for distributed SQL query processing and wish to use it t Prerequisites ------------- + To use Trino with SQream, you must have the following installed: * SQream version 4.1 or later @@ -37,7 +38,7 @@ In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https: Trino Connector -~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ The Trino Connector must be installed on each cluster node dedicated to Trino. @@ -98,6 +99,7 @@ The following is an example of the ``DESCRIBE sqream.public.t`` statement: Supported Data Types and Mapping -------------------------------- + Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. .. list-table:: diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 6cd49667e..21417c6e8 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -1,14 +1,15 @@ .. _client_platforms: -************************************ +**************** Client Platforms -************************************ +**************** + These topics explain how to install and connect a variety of third party tools. Browse the articles below, in the sidebar, or use the search to find the information you need. Overview -========== +======== SQream DB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, tools, vizualisers, and utilities. diff --git a/connecting_to_sqream/client_platforms/informatica.rst b/connecting_to_sqream/client_platforms/informatica.rst index ec39a0129..9a5c41023 100644 --- a/connecting_to_sqream/client_platforms/informatica.rst +++ b/connecting_to_sqream/client_platforms/informatica.rst @@ -1,11 +1,12 @@ .. _informatica: -************************* -Connect to SQream Using Informatica Cloud Services -************************* +************************** +Informatica Cloud Services +************************** Overview -========= +======== + The **Connecting to SQream Using Informatica Cloud Services** page is quick start guide for connecting to SQream using Informatica cloud services. It describes the following: @@ -14,7 +15,8 @@ It describes the following: :local: Establishing a Connection between SQream and Informatica ------------------ +-------------------------------------------------------- + The **Establishing a Connection between SQream and Informatica** page describes how to establish a connection between SQream and the Informatica data integration Cloud. **To establish a connection between SQream and the Informatica data integration Cloud:** @@ -93,7 +95,7 @@ The **Establishing a Connection between SQream and Informatica** page describes .. note:: If you do not download Secure Agent, you will not be able to connect your Runtime Environment with the running agent and continue establishing a connection between SQream and the Informatica data integration Cloud. Establishing a Connection In Your Environment ------------------ +--------------------------------------------- The **Establishing a Connection In Your Environment** describes the following: @@ -101,7 +103,8 @@ The **Establishing a Connection In Your Environment** describes the following: :local: Establishing an ODBC DSN Connection In Your Environment -~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After establishing a connection between SQream and Informatica you can establish an ODBC DSN connection in your environment. **To establish an ODBC connection in your environment:** @@ -129,7 +132,8 @@ After establishing a connection between SQream and Informatica you can establish 6. Click **Actions** > **Publish**. Establishing a JDBC Connection In Your Environment -~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After establishing a connection between SQream and Informatica you can establish a JDBC connection in your environment. **To establish a JDBC connection in your environment:** @@ -162,7 +166,7 @@ After establishing a connection between SQream and Informatica you can establish 6. Click **Actions** > **Publish**. Supported SQream Driver Versions ---------------- +-------------------------------- SQream supports the following SQream driver versions: diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index 370312a0d..ff8a1f306 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -1,14 +1,15 @@ .. _microstrategy: -************************* -Connect to SQream Using MicroStrategy -************************* +************* +MicroStrategy +************* .. _ms_top: Overview ---------------- +-------- + This document is a Quick Start Guide that describes how to install MicroStrategy and connect a datasource to the MicroStrategy dasbhoard for analysis. @@ -20,12 +21,9 @@ The **Connecting to SQream Using MicroStrategy** page describes the following: :local: - - - - What is MicroStrategy? -================ +====================== + MicroStrategy is a Business Intelligence software offering a wide variety of data analytics capabilities. SQream uses the MicroStrategy connector for reading and loading data into SQream. MicroStrategy provides the following: @@ -48,7 +46,7 @@ For more information about Microstrategy, see `MicroStrategy <https://www.micros Connecting a Data Source -======================= +======================== 1. Activate the **MicroStrategy Desktop** app. The app displays the Dossiers panel to the right. @@ -172,7 +170,7 @@ Your populated dashboard is displayed and is ready for data discovery and analyt :ref:`Back to Overview <ms_top>` Supported SQream Drivers -================ +======================== The following list shows the supported SQream drivers and versions: diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst index 5bf4c3685..7b3423afd 100644 --- a/connecting_to_sqream/client_platforms/pentaho.rst +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -1,12 +1,13 @@ .. _pentaho_data_integration: -************************* -Connecting to SQream Using Pentaho Data Integration -************************* +************************ +Pentaho Data Integration +************************ .. _pentaho_top: Overview -========= +======== + This document is a Quick Start Guide that describes how to install Pentaho, create a transformation, and define your output. The Connecting to SQream Using Pentaho page describes the following: @@ -20,7 +21,8 @@ The Connecting to SQream Using Pentaho page describes the following: .. _install_pentaho: Installing Pentaho -~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~ + To install PDI, see the `Pentaho Community Edition (CE) Installation Guide <https://www.hitachivantara.com/en-us/pdf/white-paper/pentaho-community-edition-installation-guide-for-windows-whitepaper.pdf>`_. The **Pentaho Community Edition (CE) Installation Guide** describes how to do the following: @@ -34,7 +36,8 @@ The **Pentaho Community Edition (CE) Installation Guide** describes how to do th .. _install_set_up_jdbc_driver: Installing and Setting Up the JDBC Driver -~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After installing Pentaho you must install and set up the JDBC driver. This section explains how to set up the JDBC driver using Pentaho. These instructions use Spoon, the graphical transformation and job designer associated with the PDI suite. You can install the driver by copying and pasting the SQream JDBC .jar file into your **<directory>/design-tools/data-integration/lib** directory. @@ -46,7 +49,8 @@ You can install the driver by copying and pasting the SQream JDBC .jar file into .. _create_transformation: Creating a Transformation -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~ + After installing Pentaho you can create a transformation. **To create a transformation:** @@ -116,7 +120,8 @@ After installing Pentaho you can create a transformation. .. _define_output: Defining Your Output ------------------ +-------------------- + After creating your transformation you must define your output. **To define your output:** @@ -178,7 +183,8 @@ After creating your transformation you must define your output. .. _import_data: Importing Data ------------------ +-------------- + After defining your output you can begin importing your data. For more information about backing up users, permissions, or schedules, see `Backup and Restore Pentaho Repositories <https://help.pentaho.com/Documentation/7.0/0P0/Managing_the_Pentaho_Repository/Backup_and_Restore_Pentaho_Repositories>`_ diff --git a/connecting_to_sqream/client_platforms/php.rst b/connecting_to_sqream/client_platforms/php.rst index ebb2c796f..b15a5121f 100644 --- a/connecting_to_sqream/client_platforms/php.rst +++ b/connecting_to_sqream/client_platforms/php.rst @@ -1,11 +1,12 @@ .. _php: -***************************** -Connect to SQream Using PHP -***************************** +*** +PHP +*** Overview -========== +======== + PHP is an open source scripting language that executes scripts on servers. The **Connect to PHP** page explains how to connect to a SQream cluster, and describes the following: .. contents:: @@ -13,7 +14,8 @@ PHP is an open source scripting language that executes scripts on servers. The * :depth: 1 Installing PHP -------------------- +-------------- + **To install PHP:** 1. Download the JDBC driver installer from the `SQream Drivers page <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/index.html>`_. @@ -29,7 +31,8 @@ Installing PHP For more information, navigate to `PHP Documentation <https://www.php.net/manual/en/intro.uodbc.php>`_ and see the topic menu on the right side of the page. Configuring PHP -------------------- +--------------- + You can configure PHP in one of the following ways: * When compiling, configure PHP to enable uODBC using ``./configure --with-pdo-odbc=unixODBC,/usr/local``. @@ -51,7 +54,8 @@ You can configure PHP in one of the following ways: * Setting the size limitation in your code before fetchng your result using **odbc_longreadlen($result, "10000");**. Operating PHP -------------------- +------------- + After configuring PHP, you can test your connection. **To test your connection:** diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index b43adf578..a299e9e4a 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -1,11 +1,12 @@ .. _power_bi: -************************* -Connecting to SQream Using Power BI Desktop -************************* +********** +BI Desktop +********** Overview -========= +======== + **Power BI Desktop** lets you connect to SQream and use underlying data as with other data sources in Power BI Desktop. SQream integrates with Power BI Desktop to do the following: @@ -35,7 +36,8 @@ The **Connect to SQream Using Power BI** page describes the following: :depth: 1 Prerequisites -------------------- +------------- + To connect to SQream, the following must be installed: * **ODBC data source administrator** - 32 or 64, depending on your operating system. For Windows users, the ODBC data source administrator is embedded within the operating system. @@ -43,7 +45,8 @@ To connect to SQream, the following must be installed: * **SQream driver** - The SQream application required for interacting with the ODBC according to the configuration specified in the ODBC administrator tool. Installing Power BI Desktop -------------------- +--------------------------- + **To install Power BI Desktop:** 1. Download `Power BI Desktop 64x <https://powerbi.microsoft.com/en-us/downloads/>`_. @@ -115,7 +118,8 @@ Installing Power BI Desktop 13. Provide your user name and password and click **Connect**. Best Practices for Power BI ---------------- +--------------------------- + SQream recommends using Power BI in the following ways for acquiring the best performance metrics: * Creating bar, pie, line, or plot charts when illustrating one or more columns. @@ -129,7 +133,8 @@ SQream recommends using Power BI in the following ways for acquiring the best pe * Creating a unified view using **PowerQuery** to connect different data sources into a single dashboard. Supported SQream Driver Versions ---------------- +-------------------------------- + SQream supports the following SQream driver versions: * The **PowerQuery Connector** is an additional layer on top of the ODBC. @@ -140,4 +145,5 @@ SQream supports the following SQream driver versions: Related Information ------------------- + For more information, see the `Glossary <https://docs.sqream.com/en/v2022.1/glossary.html>`_. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/r.rst b/connecting_to_sqream/client_platforms/r.rst index c84bf901b..a79015363 100644 --- a/connecting_to_sqream/client_platforms/r.rst +++ b/connecting_to_sqream/client_platforms/r.rst @@ -1,8 +1,8 @@ .. _r: -***************************** -Connect to SQream Using R -***************************** +* +R +* You can use R to interact with a SQream DB cluster. @@ -12,7 +12,7 @@ This tutorial is a guide that will show you how to connect R to SQream DB. :local: JDBC -========= +==== #. Get the :ref:`SQream DB JDBC driver<java_jdbc>`. @@ -66,7 +66,7 @@ JDBC > close(con) A full example ------------------ +-------------- .. code-block:: rconsole @@ -85,7 +85,7 @@ A full example > close(con) ODBC -========= +==== #. Install the :ref:`SQream DB ODBC driver<odbc>` for your operating system, and create a DSN. @@ -135,7 +135,7 @@ ODBC > close(ch) A full example ------------------ +-------------- .. code-block:: rconsole diff --git a/connecting_to_sqream/client_platforms/sap_businessobjects.rst b/connecting_to_sqream/client_platforms/sap_businessobjects.rst index 4c740b034..260ce5963 100644 --- a/connecting_to_sqream/client_platforms/sap_businessobjects.rst +++ b/connecting_to_sqream/client_platforms/sap_businessobjects.rst @@ -1,8 +1,9 @@ .. _sap_businessobjects: -************************* -Connecting to SQream Using SAP BusinessObjects -************************* +******************* +SAP BusinessObjects +******************* + The **Connecting to SQream Using SAP BusinessObjects** guide includes the following sections: .. contents:: @@ -10,7 +11,8 @@ The **Connecting to SQream Using SAP BusinessObjects** guide includes the follow :depth: 1 Overview -========== +======== + The **Connecting to SQream Using SAP BusinessObjects** guide describes the best practices for configuring a connection between SQream and the SAP BusinessObjects BI platform. SAP BO's multi-tier architecture includes both client and server components, and this guide describes integrating SQream with SAP BO's object client tools using a generic JDBC connector. The instructions in this guide are relevant to both the **Universe Design Tool (UDT)** and the **Information Design Tool (IDT)**. This document only covers how to establish a connection using the generic out-of-the-box JDBC connectors, and does not cover related business object products, such as the **Business Objects Data Integrator**. The **Define a new connection** window below shows the generic JDBC driver, which you can use to establish a new connection to a database. @@ -19,8 +21,9 @@ The **Define a new connection** window below shows the generic JDBC driver, whic SAP BO also lets you customize the interface to include a SQream data source. -Establising a New Connection Using a Generic JDCB Connector -========== +Establishing a New Connection Using a Generic JDCB Connector +============================================================ + This section shows an example of using a generic JDBC connector to establish a new connection. **To establish a new connection using a generic JDBC connector:** diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index d827fdc40..9815e122b 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -1,11 +1,12 @@ .. _connect_to_sas_viya: -************************* -Connect to SQream Using SAS Viya -************************* +******** +SAS Viya +******** Overview -========== +======== + SAS Viya is a cloud-enabled analytics engine used for producing useful insights. The **Connect to SQream Using SAS Viya** page describes how to connect to SAS Viya, and describes the following: .. contents:: @@ -14,6 +15,7 @@ SAS Viya is a cloud-enabled analytics engine used for producing useful insights. Installing SAS Viya ------------------- + The **Installing SAS Viya** section describes the following: .. contents:: @@ -21,13 +23,15 @@ The **Installing SAS Viya** section describes the following: :depth: 1 Downloading SAS Viya -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~ + Integrating with SQream has been tested with SAS Viya v.03.05 and newer. To download SAS Viya, see `SAS Viya <https://www.sas.com/en_us/software/viya.html>`_. Installing the JDBC Driver -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ + The SQream JDBC driver is required for establishing a connection between SAS Viya and SQream. **To install the JDBC driver:** @@ -41,7 +45,8 @@ The SQream JDBC driver is required for establishing a connection between SAS Viy SQream recommends creating the directory ``/opt/sqream`` on the SAS Viya server. Configuring SAS Viya -------------------- +-------------------- + After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQream Studio. **To configure the JDBC driver from the SAS Studio:** @@ -62,7 +67,8 @@ After installing the JDBC driver, you must configure the JDBC driver from the SA For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/jdbc/index.html#connection-string-examples>`_. Operating SAS Viya --------------------- +------------------ + The **Operating SAS Viya** section describes the following: .. contents:: @@ -70,7 +76,8 @@ The **Operating SAS Viya** section describes the following: :depth: 1 Using SAS Viya Visual Analytics -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + This section describes how to use SAS Viya Visual Analytics. **To use SAS Viya Visual Analytics:** @@ -137,7 +144,8 @@ If your connection is not successful, see :ref:`troubleshooting_sas_viya` below. .. _troubleshooting_sas_viya: Troubleshooting SAS Viya -------------------------- +------------------------ + The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: .. contents:: @@ -145,7 +153,8 @@ The **Best Practices and Troubleshooting** section describes the following best :depth: 1 Inserting Only Required Data -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + When using SAS Viya, SQream recommends using only data that you need, as described below: * Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. @@ -155,11 +164,13 @@ When using SAS Viya, SQream recommends using only data that you need, as describ * To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. Creating a Separate Service for SAS Viya -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. Locating the SQream JDBC Driver -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: .. code-block:: text @@ -181,5 +192,6 @@ In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the fol For more troubleshooting assistance, see the `SQream Support Portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Supporting TEXT -~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~ + In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst index a5f7e8871..cc3228892 100644 --- a/connecting_to_sqream/client_platforms/sql_workbench.rst +++ b/connecting_to_sqream/client_platforms/sql_workbench.rst @@ -1,8 +1,8 @@ .. _connect_to_sql_workbench: -***************************** -Connect to SQream Using SQL Workbench -***************************** +************* +SQL Workbench +************* You can use SQL Workbench to interact with a SQream DB cluster. SQL Workbench/J is a free SQL query tool, and is designed to run on any JRE-enabled environment. @@ -12,7 +12,8 @@ This tutorial is a guide that will show you how to connect SQL Workbench to SQre :local: Installing SQL Workbench with the SQream Installer -===================================================================== +================================================== + This section applies to Windows only. SQream DB's driver installer for Windows can install the Java prerequisites and SQL Workbench for you. @@ -35,11 +36,12 @@ SQream DB's driver installer for Windows can install the Java prerequisites and You are now ready to create a profile for your cluster. Continue to :ref:`Creating a new connection profile <new_connection_profile>`. Installing SQL Workbench Manually -=================================================== +================================= + This section applies to Linux and MacOS only. Install Java Runtime ------------------------- +-------------------- Both SQL Workbench and the SQream DB JDBC driver require Java 1.8 or newer. You can install either Oracle Java or OpenJDK. @@ -54,14 +56,14 @@ For Linux and BSD, see https://openjdk.java.net/install/ For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk Get the SQream DB JDBC Driver -------------------------------- +----------------------------- SQream DB's JDBC driver is provided as a zipped JAR file, available for download from the `SQream Drivers page <http://sqream.com/product/client-drivers>`_. Download and extract the JAR file from the zip archive. Install SQL Workbench ------------------------ +--------------------- #. Download the latest stable release from https://www.sql-workbench.eu/downloads.html . The **Generic package for all systems** is recommended. @@ -70,7 +72,7 @@ Install SQL Workbench #. Start SQL workbench. If you are using 64 bit windows, run ``SQLWorkbench64.exe`` instead of ``SQLWOrkbench.exe``. Setting up the SQream DB JDBC Driver Profile ---------------------------------------------- +-------------------------------------------- #. Define a connection profile - :menuselection:`&File --> &Connect window (Alt+C)` @@ -103,7 +105,7 @@ Setting up the SQream DB JDBC Driver Profile .. _new_connection_profile: Create a New Connection Profile for Your Cluster -===================================================== +================================================ .. image:: /_static/images/sql_workbench_connection_profile.png @@ -120,7 +122,7 @@ Create a New Connection Profile for Your Cluster #. Click OK to save the connection profile and connect to SQream DB Suggested Optional Configuration -================================== +================================ If you installed SQL Workbench manually, you can set a customization to help SQL Workbench show information correctly in the DB Explorer panel. diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 7e4e92509..733efc317 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -1,8 +1,8 @@ .. _tableau: -************************* -Connecting to SQream Using Tableau -************************* +******* +Tableau +******* SQream's Tableau connector, based on standard JDBC, enables storing and fast querying large volumes of data. This connector is useful for users who want to integrate and analyze data from various sources within the Tableau platform. With the Tableau connector, users can easily connect to databases and cloud applications and perform high-speed queries on large datasets. Additionally, the connector allows for seamless integration with Tableau, enabling users to visualize their data. @@ -64,7 +64,7 @@ Installing the Tableau Connector 3. Restart Tableau Desktop or Tableau server. Connecting to SQream ---------------------- +-------------------- #. Start Tableau Desktop. diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index 7f11092fb..e2db1d278 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -1,12 +1,13 @@ .. _talend: -************************* -Connecting to SQream Using Talend -************************* +****** +Talend +****** Overview -================= -This page describes how to use Talend to interact with a SQream cluster. The Talend connector is used for reading data from a SQream cluster and loading data into SQream. In addition, this page provides a viability report on Talend's comptability with SQream for stakeholders. +======== + +This page describes how to use Talend to interact with a SQream cluster. The Talend connector is used for reading data from a SQream cluster and loading data into SQream. In addition, this page provides a viability report on Talend's comparability with SQream for stakeholders. The **Connecting to SQream Using Talend** describes the following: @@ -15,7 +16,8 @@ The **Connecting to SQream Using Talend** describes the following: :depth: 1 Creating a New Metadata JDBC DB Connection ----------------- +------------------------------------------ + **To create a new metadata JDBC DB connection:** 1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. @@ -97,7 +99,8 @@ Creating a New Metadata JDBC DB Connection For more information on loading data from JSON files to the Talend Open Studio, see `How to Load Data from JSON Files in Talend <https://www.youtube.com/watch?v=qNt9CYZFFqQ&list=PLOr008ImHvfan_fuDr5RVyexpeYJAp9FX&index=6>`_. Supported SQream Drivers ----------------- +------------------------ + The following list shows the supported SQream drivers and versions: * **JDBC** - Version 4.3.3 and higher. @@ -107,7 +110,8 @@ The following list shows the supported SQream drivers and versions: * **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database <https://www.easysoft.com/blog/talend.html>`_. Supported Data Sources ----------------- +---------------------- + Talend Cloud connectors let you create reusable connections with a wide variety of systems and environments, such as those shown below. This lets you access and read records of a range of diverse data. * **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. @@ -117,7 +121,8 @@ Talend Cloud connectors let you create reusable connections with a wide variety * **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors <https://help.talend.com/r/vqIZei8ynfi_BaDCg3d~_g/M0qzU1kTnL0bPou7OuxJfw>`_. Known Issues ----------------- +------------ + As of 6/1/2021 schemas were not displayed for tables with identical names. If you experience issues using Talend, see the `SQream support portal <https://support.sqream.com>`_. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst index 2d85fecf1..b3ce5a95b 100644 --- a/connecting_to_sqream/client_platforms/tibco_spotfire.rst +++ b/connecting_to_sqream/client_platforms/tibco_spotfire.rst @@ -1,11 +1,13 @@ .. _tibco_spotfire: -************************* -Connecting to SQream Using TIBCO Spotfire -************************* +************** +TIBCO Spotfire +************** + Overview -========= +======== + The **TIBCO Spotfire** software is an analytics solution that enables visualizing and exploring data through dashboards and advanced analytics. This document is a Quick Start Guide that describes the following: @@ -15,7 +17,8 @@ This document is a Quick Start Guide that describes the following: :depth: 1 Establishing a Connection between TIBCO Spotfire and SQream ------------------ +----------------------------------------------------------- + TIBCO Spotfire supports the following versions: * **JDBC driver** - Version 4.5.2 @@ -30,13 +33,15 @@ The **Establishing a JDBC Connection between TIBCO Spotfire and SQream** section :depth: 1 Creating a JDBC Connection -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ + For TIBCO Spotfire to recognize SQream, you must add the correct JDBC jar file to Spotfire's loaded binary folder. The following is an example of a path to the Spotfire loaded binaries folder: ``C:\tibco\tss\7.12.0\tomcat\bin``. For the complete TIBCO Spotfire documentation, see `TIBCO Spotfire® JDBC Data Access Connectivity Details <https://community.tibco.com/wiki/tibco-spotfire-jdbc-data-access-connectivity-details>`_. Creating an ODBC Connection -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **To create an ODBC connection** 1. Install and configure ODBC on Windows. @@ -84,7 +89,8 @@ Creating an ODBC Connection .. note:: Verify that you have checked the SQL statement. Creating the SQream Data Source Template -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After creating a connection, you can create your SQream data source template. **To create your SQream data source template:** @@ -183,7 +189,8 @@ After creating a connection, you can create your SQream data source template. 5. Close and restart your Spotfire server. Creating a Data Source -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~ + After creating the SQream data source template, you can create a data source. **To create a data source:** @@ -225,7 +232,8 @@ After creating the SQream data source template, you can create a data source. * **Username and Password** - define your SQream username and password. Creating an Information Link -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + After creating a data source, you can create an information link. **To create an information link**: @@ -354,7 +362,8 @@ After creating a data source, you can create an information link. For more information on the Information Link attributes, see `Information Link Tab <https://docs.tibco.com/pub/spotfire/7.0.1/doc/html/id/id_information_link_tab.htm>`_. Troubleshooting -------------- +--------------- + The **Troubleshooting** section describes the following scenarios: .. contents:: @@ -362,7 +371,8 @@ The **Troubleshooting** section describes the following scenarios: :depth: 1 The JDBC Driver does not Support Boolean, Decimal, or Numeric Types -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + When attempting to load data, the the Boolean, Decimal, or Numeric column types are not supported and generate the following error: .. code-block:: console @@ -381,7 +391,8 @@ For more information, see the following: * **Supported data types** - :ref:`Data Types<supported_data_types>`. Information Services do not Support Live Queries -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + TIBCO Spotfire data connectors support live queries, but no APIs currently exist for creating custom data connectors. This is resolved by creating a customized SQream adapter using TIBCO's **Data Virtualization (TDV)** or the **Spotfire Advanced Services (ADS)**. These can be used from the built-in TDV connector to enable live queries. This resolution applies to JDBC and ODBC drivers. \ No newline at end of file From 25fcb8059c839b4b55d393dcc15a7f2121614adf Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 16:11:44 +0300 Subject: [PATCH 0646/1892] SQLoader --- .../client_platforms/index.rst | 1 - connecting_to_sqream/index.rst | 9 ++++--- data_ingestion/ingesting_from_databases.rst | 2 +- data_ingestion/parquet.rst | 26 ++++++++++++------- 4 files changed, 23 insertions(+), 15 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 21417c6e8..6b9b70efd 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -36,7 +36,6 @@ If you are looking for a tool that is not listed, SQream and our partners can he tableau talend tibco_spotfire - xxdiagnosing_common_connectivity_issues .. image:: /_static/images/connectivity_ecosystem.png diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index 10533b0ac..1fc769b95 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,9 +1,10 @@ .. _connecting_to_sqream: -************************* -Connecting to SQream -************************* -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. +********************** +Connecting to SQreamDB +********************** + +SQreamDB supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. .. toctree:: :maxdepth: 2 diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 86ee4e369..1e00cf5b7 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** .. contents:: :local: :depth: 1 Making JSON Files Accessible to Workers ======================================= Mapping between JSON and SQream =============================== Character Escaping ------------------ Ingesting JSON Data into SQream =============================== Syntax ------- Parameters ---------- Automatic Schema Inference -------------------------- Examples -------- \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration files * jar file Syntax ====== code-block:: console java -jar sqloader-0.0.1.jar <parameter> Transferring External Database Data into SQreamDB Tables ======================================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - Table types =========== There are three types of table you may create using the SQLoader, You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - CDC - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index a77563734..355d27344 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -11,7 +11,8 @@ Ingesting Parquet files into SQream is generally useful when you want to store t :depth: 1 Preparing Your Parquet Files -===================== +============================ + Prepare your source Parquet files according to the requirements described in the following table: .. list-table:: @@ -165,7 +166,8 @@ Your statements will succeed even if your Parquet file contains unsupported type .. [#f4] Any microseconds will be rounded down to milliseconds. Making Parquet Files Accessible to Workers -================================================================ +========================================== + To give workers access to files, every node must have the same view of the storage being used. * For files hosted on NFS, ensure that the mount is accessible from all servers. @@ -175,7 +177,8 @@ To give workers access to files, every node must have the same view of the stora * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3` guide. Creating a Table -=============================================== +================ + Before loading data, you must create a table that corresponds to the file structure of the table you wish to insert. The example in this section is based on the source nba.parquet table shown below: @@ -215,7 +218,8 @@ Ingesting Data into SQream ========================== Syntax ------------ +------ + You can use the :ref:`create_table_as` statement to load the data into SQream, as shown below: .. code-block:: postgres @@ -224,14 +228,15 @@ You can use the :ref:`create_table_as` statement to load the data into SQream, a SELECT * FROM ext_nba; Examples ----------------- +-------- .. contents:: :local: :depth: 1 Omitting Unsupported Column Types -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + When loading data, you can omit columns using the NULL as argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a “type mismatch” error. In the example below, the ``Position column`` is not supported due its type. @@ -257,7 +262,8 @@ In the example below, the ``Position column`` is set to the default ``NULL``. ORDER BY weight; Loading a Table from a Directory of Parquet Files on HDFS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The following is an example of loading a table from a directory of Parquet files on HDFS: .. code-block:: postgres @@ -273,7 +279,8 @@ The following is an example of loading a table from a directory of Parquet files CREATE TABLE users AS SELECT * FROM ext_users; Loading a Table from a Directory of Parquet Files on S3 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The following is an example of loading a table from a directory of Parquet files on S3: .. code-block:: postgres @@ -292,7 +299,8 @@ The following is an example of loading a table from a directory of Parquet files For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. Best Practices -============ +============== + Because external tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Parquet files into SQream. This lets you determine if your table output is identical to your originally inserted table. The following is an example of the output based on the **nba.parquet** table: From eadf2e065d8542e1c94b303c5a63f00e51b3c310 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:07:34 +0300 Subject: [PATCH 0647/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 1e00cf5b7..6bc434732 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration files * jar file Syntax ====== code-block:: console java -jar sqloader-0.0.1.jar <parameter> Transferring External Database Data into SQreamDB Tables ======================================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - * - ```` - Table types =========== There are three types of table you may create using the SQLoader, You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - CDC - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - CDC - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From c3d2d15fb712ccdaffaecea59e7d6b999061ed39 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:08:35 +0300 Subject: [PATCH 0648/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 6bc434732..efffc2ad6 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - CDC - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From d51db80a9659dce7ec22c8aa046fb1bf432c014c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:23:01 +0300 Subject: [PATCH 0649/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index efffc2ad6..4b186ba99 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ****************** Exterior Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From cfc4e0ab926228b54995bd566ff7ff742d3c11b7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:41:17 +0300 Subject: [PATCH 0650/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 4b186ba99..d6b9517fc 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** Exterior Databases ****************** The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From a820e0862963b924eabe6a88eaf4105bdbaebb85 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:41:52 +0300 Subject: [PATCH 0651/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index d6b9517fc..9a9dc1022 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From baaffbb889b662972d2f847dc7c82664b9165a31 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:45:44 +0300 Subject: [PATCH 0652/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 9a9dc1022..7e1aeb056 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * ``SQLoader.jar`` file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * `SQLoader.jar <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From b7ce990e4f93bdd5d71f7f93edb7892fd2e25673 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:46:51 +0300 Subject: [PATCH 0653/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 7e1aeb056..5fb13cfdc 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * `SQLoader.jar <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ file Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From cc76a9c9c566cec48ea2475f947246536606e7c2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 11:18:34 +0300 Subject: [PATCH 0654/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 5fb13cfdc..aa8fdecb9 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following SQLoader files downloaded: * configuration file * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration file, run the ``sqloader.jar`` file. 2. Customize your table using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=Log directory path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=true/false`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of table you may create using the SQLoader. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - * - Change Data Capture (CDC) - * - Incremental - Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * configuration files * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration files, run the ``sqloader.jar`` file using the following command: .. code-block:: java -jar sqloader.jar 2. You may customize the data load by using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=<Log directory> path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of data loading. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - This is a full load. The entire source table will be loaded into SQreamDB. * - Change Data Capture (CDC) - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``, ``UPDATE``, and ``DELETE``. SQLoader recognizes the table by the table name and metadata. * - Incremental - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``. SQLoader recognizes the table by the table name and metadata. Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file From b76312c75bf5981e6a02d113e78261bb16502947 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 12:19:07 +0300 Subject: [PATCH 0655/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index aa8fdecb9..ba8401ede 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * configuration files * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration files, run the ``sqloader.jar`` file using the following command: .. code-block:: java -jar sqloader.jar 2. You may customize the data load by using the following parameters: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Is case sensitive? Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. Default is ``collist.txt`` * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Configuration file. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Count table rows before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Activate cdc deletes? Default is ``false`` * - ``-drop=<drop>`` - Drop/Create target table? Default is ``false`` * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - SQL Filter for source table select statement. Default is ``1=1`` * - ``-h, --help`` - Display this help and exit * - ``-limit=<limit>`` - Number of limited rows. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-lock_check=<lockCheck>`` - Check or skip lock status before start load operation? Default is ``true`` * - ``-lock_table=<lockTable>`` - Lock target table for another load operations during the load? Default is ``true`` * - ``-log_dir=<Log directory> path`` - Log directory path. Default is ``logs`` * - ``-partition=partition name`` - Partition name of the table * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<dummyTargetDb>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Defualt is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr func for CLOB/BLOB data types? Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Table types =========== There are three types of data loading. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - This is a full load. The entire source table will be loaded into SQreamDB. * - Change Data Capture (CDC) - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``, ``UPDATE``, and ``DELETE``. SQLoader recognizes the table by the table name and metadata. * - Incremental - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``. SQLoader recognizes the table by the table name and metadata. Mapping Data Types ================== Examples ======== Creating a cdc table using the ``type`` parameter: code-block:: sql \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. SQreamDB supports Oracle and Postgres tables only. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * configuration files * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration files, run the ``sqloader.jar`` file using the following command: .. code-block:: java -jar sqloader.jar 2. You may customize the data load by using either the following parameters or the ``properties`` file you had downloaded: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters during table creation. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using CDC will take deleted rows under consideration. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table is created. Default is ``true``. If ``false``, you will need to configure a target table name. * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - Loads records where SQL condition exists. Default is ``1=1``. * - ``-h, --help`` - Displays help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading to the target table. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not checking if table is locked before loading starts. Default is ``true``. * - ``-lock_table=<lockTable>`` - Defines whether or not to lock target table before loading operation starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - If table is partitioned, this parameter defines the partition to load the data from. * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Default is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr function for CLOB/BLOB data types? Default is ``true``. * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Loading types ============= There are three types of data loading. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - This is a full load. The entire source table will be loaded into SQreamDB. * - Change Data Capture (CDC) - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``, ``UPDATE``, and ``DELETE``. SQLoader recognizes the table by the table name and metadata. Supported for Oracle only. * - Incremental - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``. SQLoader recognizes the table by the table name and metadata. Supported for Oracle only. Mapping Data Types ================== Examples ======== Creating a CDC table using the ``type`` and ``limit`` parameters: code-block:: console java -jar [sqloader_jar_name] -table [source_table_name] -type <full/cdc/inc> -limit 100 Creating a table using your own configuration file: This will override the default configuration file you had already downloaded. code-block:: console java -jar [sqloader_jar_name] -config <config file path> Creating a parameters: code-block:: console -config DBUtils.configFilePath -source_db ORCL -table SMSDW.sltest_fullload_partition -type full -target SMSDW.sltest_fullload_partition -drop true -lock_check false -partition P20230101 Creating a table using a the ``filter`` parameter: code-block:: console java -jar [sqloader_jar_name] -table [source_table_name] -filter column_name>50 \ No newline at end of file From 2fcdaa49d9ba90133fabc083a3a302a5fa7c26fe Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:00:26 +0300 Subject: [PATCH 0656/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index ba8401ede..cf4aac88e 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** enables you to transfer data into SQreamDB from other databases. It operates using the CLI. SQreamDB supports Oracle and Postgres tables only. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * configuration files * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Transferring Data into SQreamDB Tables ====================================== 1. After you have downloaded the configuration files, run the ``sqloader.jar`` file using the following command: .. code-block:: java -jar sqloader.jar 2. You may customize the data load by using either the following parameters or the ``properties`` file you had downloaded: .. list-table:: SQLoader Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``-batchsize=<batchSize>`` - Number of records to insert target database at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters during table creation. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - Number of records to read from source database at once. Default ``0`` * - ``-columnlist=<columnFilePath>`` - Name of file contains column names. * - ``-columns=<columns>`` - Name of columns to be ingested ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before ingestion? Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using CDC will take deleted rows under consideration. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table is created. Default is ``true``. If ``false``, you will need to configure a target table name. * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - Loads records where SQL condition exists. Default is ``1=1``. * - ``-h, --help`` - Displays help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading to the target table. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not checking if table is locked before loading starts. Default is ``true``. * - ``-lock_table=<lockTable>`` - Defines whether or not to lock target table before loading operation starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - If table is partitioned, this parameter defines the partition to load the data from. * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full),cdc,incremental]. Default is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr function for CLOB/BLOB data types? Default is ``true``. * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Loading types ============= There are three types of data loading. You can define the type of table using the ``type`` parameter. .. list-table:: :widths: auto :header-rows: 1 * - Table Type - Description * - Full Table - This is a full load. The entire source table will be loaded into SQreamDB. * - Change Data Capture (CDC) - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``, ``UPDATE``, and ``DELETE``. SQLoader recognizes the table by the table name and metadata. Supported for Oracle only. * - Incremental - This loads changes made to the last time you loaded a specific table. Changes are ``INSERT``. SQLoader recognizes the table by the table name and metadata. Supported for Oracle only. Mapping Data Types ================== Examples ======== Creating a CDC table using the ``type`` and ``limit`` parameters: code-block:: console java -jar [sqloader_jar_name] -table [source_table_name] -type <full/cdc/inc> -limit 100 Creating a table using your own configuration file: This will override the default configuration file you had already downloaded. code-block:: console java -jar [sqloader_jar_name] -config <config file path> Creating a parameters: code-block:: console -config DBUtils.configFilePath -source_db ORCL -table SMSDW.sltest_fullload_partition -type full -target SMSDW.sltest_fullload_partition -drop true -lock_check false -partition P20230101 Creating a table using a the ``filter`` parameter: code-block:: console java -jar [sqloader_jar_name] -table [source_table_name] -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load by either using the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - Loads records where SQL condition exists. Default is ``1=1``. * - ``-h, --help`` - Displays help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading to the target table. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not checking if table is locked before loading starts. Default is ``true``. * - ``-lock_table=<lockTable>`` - Defines whether or not to lock target table before loading operation starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - If table is partitioned, this parameter defines the partition to load the data from. * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full, cdc, incremental]. Default is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr function for CLOB/BLOB data types? Default is ``true``. * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps the data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 9cab4d89919b95c07fe97c489424620b3bdc580d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:18:28 +0300 Subject: [PATCH 0657/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index cf4aac88e..3769d393a 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load by either using the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - Number of records to read from source database at once. Default is ``100000`` * - ``-filter=<filter>`` - Loads records where SQL condition exists. Default is ``1=1``. * - ``-h, --help`` - Displays help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading to the target table. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not checking if table is locked before loading starts. Default is ``true``. * - ``-lock_table=<lockTable>`` - Defines whether or not to lock target table before loading operation starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - If table is partitioned, this parameter defines the partition to load the data from. * - ``-rowid=deprecated`` - Get row id from oracle table? Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name * - ``-target=<targetTableName>`` - Target table name. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name * - ``-thread=<thread>`` - Number of thread. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table? Default is ``false`` * - ``-type=<type>`` - Load type. [full, cdc, incremental]. Default is ``full`` * - ``-use_dbms_lob=<useDbmsLob>`` - Use dbms_lob_substr function for CLOB/BLOB data types? Default is ``true``. * - ``-use_partitions=<usePartitions>`` - Use partitions in select statements? Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps the data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load by either using the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps the data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 940178865512d693adf0984fd5034a9f4aaa525e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 15:21:52 +0300 Subject: [PATCH 0658/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 3769d393a..b617b7860 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load by either using the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps the data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From edfae4da1480ba6c189e0b91ee309d2f57798974 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:02:00 +0300 Subject: [PATCH 0659/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index b617b7860..d76766fa7 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * `SQLoader configuration files <>`_ * `SQLoader.jar file <https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.jar>`_ Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: * sqream-mapping.json * sqload-jdbc-oracle-incr.properties * reserved_words.txt * sqloader-0.0.2.jar Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From e5d4954cb545a0ba390351118d46be5f4e43bd08 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 16:07:27 +0300 Subject: [PATCH 0660/1892] SQLoader RN --- releases/4.0_index.rst | 8 ++- releases/4.4.rst | 152 +++++++++++++++++++++++++++++++++++++++++ releases/index.rst | 2 + 3 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 releases/4.4.rst diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 1413bd07b..8b40fcbd6 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -1,8 +1,9 @@ .. _4.0_index: -************************** +***************** Release Notes 4.0 -************************** +***************** + The 4.0 Release Notes describe the following releases: .. contents:: @@ -16,4 +17,5 @@ The 4.0 Release Notes describe the following releases: 4.0 4.1 4.2 - 4.3 \ No newline at end of file + 4.3 + 4.4 \ No newline at end of file diff --git a/releases/4.4.rst b/releases/4.4.rst new file mode 100644 index 000000000..afd67223c --- /dev/null +++ b/releases/4.4.rst @@ -0,0 +1,152 @@ +.. _4.4: + +***************** +Release Notes 4.4 +***************** + +The 4.4 release notes were released on xx/xx/xxxx and describe the following: + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS / REHL - 7.6 - 7.9 | +| | * IBM RedHat 7.6 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 49 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.8 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | +| | * Spark | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- + +► **SQLoader** + +The :ref:`SQLoader<ingesting_from_databases>` is a CLI program that enables you to load into SQreamDB data from other databases. + + + +Known Issues +------------ + +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. + +* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression + + +Version 4.4 resolved Issues +--------------------------- + ++--------------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+================================================================================================+ +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13210, SQ-13426 | Slow query execution time | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation case-sensitivity issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13453 | Metadata performance issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number of worker connections failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-11804 | Slow metadata optimization | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12799 | Catalog queries may not be terminated | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | ++--------------------+------------------------------------------------------------------------------------------------+ + +Configuration Adjustments +------------------------- + +► You may now configure the object access style and your endpoint URL with Virtual Private Cloud (VPC) when using AWS S3. + +Visit :ref:`s3` to learn more about how and when you should use these two new parameters: + +* ``AwsEndpointOverride`` +* ``AwsObjectAccessStyle`` + +Deprecated Features +------------------- + +► ``INT96`` + +Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. + + +► Square Brackets ``[]`` + +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, are officially deprecated to facilitate the use of the ``ARRAY`` data type. To delimit database object identifiers, use double quotes ``""``. + + +► ``VARCHAR`` + +The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. + +* Support in the ``VARCHAR`` data type ends at September 30th, 2023. +* ``VARCHAR`` is no longer supported for new customers, effective from version 2022.1.3. +* The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. + +Upgrading to v4.4 +----------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/index.rst b/releases/index.rst index 241381e3b..9c1b8d2f6 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -12,6 +12,8 @@ Release Notes * - Version - Release Date + * - :ref:`4.4` + - xxxxxxx xx, xxxx * - :ref:`4.3` - June 11, 2023 * - :ref:`4.2` From 0fc21218023b4d2525542ce39769e159412a21c8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 11 Jul 2023 17:57:20 +0300 Subject: [PATCH 0661/1892] Update index.rst --- loading_and_unloading_data/index.rst | 31 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst index bc515f023..72a698dc1 100644 --- a/loading_and_unloading_data/index.rst +++ b/loading_and_unloading_data/index.rst @@ -1,36 +1,37 @@ .. _loading_and_unloading_data: -*********************** +************************** Loading and Unloading Data -*********************** +************************** + The **Loading Data** section describes concepts and operations related to importing data into your SQream database: -* `Overview of loading data <https://docs.sqream.com/en/v2022.1/data_ingestion/inserting_data.html>`_ - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. +* :ref:`Overview of loading data <inserting_data>` - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. -* `Alternatives to loading data (foreign tables) <https://docs.sqream.com/en/v2022.1/operational_guides/foreign_tables.html>`_ - Useful for running queries directly on external data without importing into your SQream database. +* :ref:`Alternatives to loading data (foreign tables) <foreign_tables>` - Useful for running queries directly on external data without importing into your SQream database. -* `Supported data types <https://docs.sqream.com/en/v2022.1/data_type_guides/supported_data_types.html>`_ - Overview of supported data types, including descriptions, examples, and relevant aliases. +* :ref:`Supported data types <supported_data_types>` - Overview of supported data types, including descriptions, examples, and relevant aliases. -* `Ingesting data from external sources <https://docs.sqream.com/en/v2022.1/data_ingestion/index.html>`_ - List of data ingestion sources that SQream supports. +* :ref:`Ingesting data from external sources <data_ingestion>` - List of data ingestion sources that SQream supports. -* `Inserting data from external tables <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/insert.html#insert>`_ - Inserts one or more rows into a table. +* :ref:`Inserting data from external tables <insert>` - Inserts one or more rows into a table. -* `Ingesting data from third party client platforms <https://docs.sqream.com/en/v2022.1/third_party_tools/client_platforms/index.html>`_ - Gives you direct access to a variety of drivers, connectors, tools, vizualisers, and utilities.. +* :ref:`Ingesting data from third party client platforms <client_platforms>` - Gives you direct access to a variety of drivers, connectors, tools, visualizers, and utilities.. -* `Using the COPY FROM statement <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/copy_from.html>`_ - Used for loading data from files located on a filesystem into SQream tables. +* :ref:`Using the COPY FROM statement <copy_from>` - Used for loading data from files located on a filesystem into SQream tables. -* `Importing data using Studio <https://docs.sqream.com/en/v2022.1/sqream_studio_5.4.3/executing_statements_and_running_queries_from_the_editor.html#performing-statement-related-operations-from-the-database-tree>`_ - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. +* :ref:`Importing data using Studio <executing_statements_and_running_queries_from_the_editor>` - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. -* `Loading data using Amazon S3 <https://docs.sqream.com/en/v2022.1/operational_guides/s3.html>`_ - Used for loading data from Amazon S3. +* :ref:`Loading data using Amazon S3 <s3>` - Used for loading data from Amazon S3. * Troubleshooting - Describes troubleshooting solutions related to importing data from the following: - * `SAS Viya <https://docs.sqream.com/en/v2022.1/troubleshooting/sas_viya_related_issues.html>`_ + * :ref:`SAS Viya <connect_to_sas_viya>` - * `Tableau <https://docs.sqream.com/en/v2022.1/troubleshooting/tableau_related_issues.html>`_ + * :ref:`Tableau <tableau>` The **Unloading Data** section describes concepts and operations related to exporting data from your SQream database: -* `Overview of unloading data <https://docs.sqream.com/en/v2022.1/operational_guides/external_tables.html>`_ - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. +* :ref:`Overview of unloading data <foreign_tables>` - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. -* `The COPY TO statement <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/copy_to.html>`_ - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file +* :ref:`The COPY TO statement <copy_to>` - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file From 822db714c08bf4ab11ffb2a23fe5152a6c590585 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 09:44:47 +0300 Subject: [PATCH 0662/1892] Update automatic_foreign_table_ddl_resolution.rst --- ...automatic_foreign_table_ddl_resolution.rst | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/feature_guides/automatic_foreign_table_ddl_resolution.rst b/feature_guides/automatic_foreign_table_ddl_resolution.rst index 6c0d1605c..580acd87a 100644 --- a/feature_guides/automatic_foreign_table_ddl_resolution.rst +++ b/feature_guides/automatic_foreign_table_ddl_resolution.rst @@ -1,20 +1,18 @@ .. _automatic_foreign_table_ddl_resolution: -*********************** +************************************** Automatic Foreign Table DDL Resolution -*********************** -The **Automatic Foreign Table DDL Resolution** page describes the following: +************************************** + +SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. .. contents:: :local: - :depth: 1 - -Overview ----------- -SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. + :depth: 1 Usage Notes ----------- +=========== + The automatic foreign table DDL resolution feature supports Parquet, ORC, JSON, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. @@ -22,25 +20,28 @@ Using this feature the path you specify in the ``LOCATION`` option must point to .. note:: When using this feature, SQream assumes that all files in the path use the same schema. Syntax ----------- +====== + The following is the syntax for using the automatic foreign table DDL resolution feature: -.. code-block:: console +.. code-block:: sql CREATE FOREIGN TABLE table_name [FOREIGN DATA] WRAPPER fdw_name - [OPTIONS (...)]; + [OPTIONS (...)] Example ----------- +======= + The following is an example of using the automatic foreign table DDL resolution feature: -.. code-block:: console +.. code-block:: sql create foreign table parquet_table wrapper parquet_fdw options (location = '/tmp/file.parquet'); Permissions ----------- +=========== + The automatic foreign table DDL resolution feature requires **Read** permissions. \ No newline at end of file From be3ee5ee27214d9c1e9863daf31248c330dce074 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 10:15:37 +0300 Subject: [PATCH 0663/1892] Encryption --- feature_guides/data_encryption.rst | 34 ++++++++++++++++----- feature_guides/data_encryption_overview.rst | 28 ----------------- 2 files changed, 27 insertions(+), 35 deletions(-) delete mode 100644 feature_guides/data_encryption_overview.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst index 607d6c09a..b05ad6cbd 100644 --- a/feature_guides/data_encryption.rst +++ b/feature_guides/data_encryption.rst @@ -1,19 +1,39 @@ .. _data_encryption: -*********************** +*************** Data Encryption -*********************** -The **Data Encryption** page describes the following: +*************** -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png - :align: middle - :width: 110 +**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. + +Encryption can be used for the following: + +* Creating tables with up to three encrypted columns. + + :: + +* Joining encrypted columns with other tables. + + :: + +* Selecting data from an encrypted column. + +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT`` or ``INSERT INTO TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. + +For more information on the encryption syntax, see :ref:`data_encryption_syntax`. + +For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. +.. rubric:: In This Section: + .. toctree:: :maxdepth: 1 :titlesonly: - data_encryption_overview data_encryption_methods data_encryption_types data_encryption_syntax diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst deleted file mode 100644 index 256e3d718..000000000 --- a/feature_guides/data_encryption_overview.rst +++ /dev/null @@ -1,28 +0,0 @@ -.. _data_encryption_overview: - -*********************** -Overview -*********************** -**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - -Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. - -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. - -Encryption can be used for the following: - -* Creating tables with up to three encrypted columns. - - :: - -* Joining encrypted columns with other tables. - - :: - -* Selecting data from an encrypted column. - -.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT`` or ``INSERT INTO TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. - -For more information on the encryption syntax, see :ref:`data_encryption_syntax`. - -For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. \ No newline at end of file From 336554527bfd0ddba0fd69bef203859e0a5bc2b4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 15:57:09 +0300 Subject: [PATCH 0664/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 9d67d9baf..82dd026d3 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -6,7 +6,11 @@ Array The ``ARRAY`` data type offers a convenient way to store ordered collections of elements in a single column. It provides storage efficiency by allowing multiple values of the same data type to be compactly stored, optimizing space utilization and enhancing database performance. Working with arrays simplifies queries as operations and manipulations can be performed on the entire array, resulting in more concise and readable code. -Each data type has its companion array type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. An array represents a sequence of zero or more elements of the same data type. Arrays in the same column can contain varying numbers of elements across different rows. Arrays can include null values, eliminating the need for separate SQL declarations. +An array represents a sequence of zero or more elements of the same data type. Arrays in the same column can contain varying numbers of elements across different rows. Arrays can include null values, eliminating the need for separate SQL declarations. + +Each data type has its companion array type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. + +.. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. Syntax ====== @@ -17,7 +21,7 @@ Defining an array is done by appending the ``[]`` notation to a supported data t CREATE TABLE <table_name> (<column1> TEXT[], <column2> INT[]) - INSERT INTO TABLE <table_name> VALUES ARRAY[<'a','b','c'>], ARRAY[<1,2,3>] + INSERT INTO TABLE <table_name> VALUES ARRAY[<'a','b','c'>], ARRAY[<1,2,NULL>] Size ==== @@ -33,18 +37,18 @@ Supported Operators * - Operator - Description - * - Literals + * - Literals ``ARRAY []`` - An array literal can be created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3];`` * - Mapping - Parquet, ORC, JSON, and AVRO array types may be mapped into SQreamDB arrays * - Indexing - - Access to specific elements within the array by using a zero-based index. For example, ``arr[2]`` returns the second array element + - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT <column_name>[2] FROM <table_name>`` returns the third array element of the specified column * - ``UNNEST`` - - Converts arrayed elements into a set of rows + - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST <column_name> FROM <table_name>`` * - Concatenate ``||`` - - Converts arrayed elements into one string - * - - - + - Converts arrayed elements into one string. For example, + * - ``array_length`` + - Returns the number of arrayed elements within the specified column. For Example, ``SELECT array_length(<column_name>) FROM <table_name>`` * - - * - @@ -62,6 +66,7 @@ Supported Operators Examples ======== + Creating a table with arrayed columns: .. code-block:: From e67b8ee8ebfd2c5cad0e1d90ebf96c6a07f9db07 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:22:07 +0300 Subject: [PATCH 0665/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 82dd026d3..97cf07ea0 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -38,7 +38,7 @@ Supported Operators * - Operator - Description * - Literals ``ARRAY []`` - - An array literal can be created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3];`` + - An array literal can be created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3]`` * - Mapping - Parquet, ORC, JSON, and AVRO array types may be mapped into SQreamDB arrays * - Indexing @@ -46,7 +46,7 @@ Supported Operators * - ``UNNEST`` - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST <column_name> FROM <table_name>`` * - Concatenate ``||`` - - Converts arrayed elements into one string. For example, + - Converts arrayed elements into one string. For example, ``SELECT <column_name> || <column2_name> FROM <table_name>`` * - ``array_length`` - Returns the number of arrayed elements within the specified column. For Example, ``SELECT array_length(<column_name>) FROM <table_name>`` * - From d5d9b6473d8012917f9cd5ca8034c2ad52a15f0c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 16:33:26 +0300 Subject: [PATCH 0666/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 97cf07ea0..5ff108c3f 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -49,8 +49,8 @@ Supported Operators - Converts arrayed elements into one string. For example, ``SELECT <column_name> || <column2_name> FROM <table_name>`` * - ``array_length`` - Returns the number of arrayed elements within the specified column. For Example, ``SELECT array_length(<column_name>) FROM <table_name>`` - * - - - + * - ``array_position`` + - Locates the position of the specified value within the specified array. For example, ``SELECT array_position(<column_name>,<value>) FROM <table_name>; * - - * - From ba0942105a9a51470ec57f90ed4d50f23b939351 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jul 2023 17:16:57 +0300 Subject: [PATCH 0667/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 5ff108c3f..155952fab 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -48,13 +48,13 @@ Supported Operators * - Concatenate ``||`` - Converts arrayed elements into one string. For example, ``SELECT <column_name> || <column2_name> FROM <table_name>`` * - ``array_length`` - - Returns the number of arrayed elements within the specified column. For Example, ``SELECT array_length(<column_name>) FROM <table_name>`` + - Returns the number of arrayed elements within the specified column. For example, ``SELECT array_length(<column_name>) FROM <table_name>`` * - ``array_position`` - - Locates the position of the specified value within the specified array. For example, ``SELECT array_position(<column_name>,<value>) FROM <table_name>; - * - - - - * - - - + - Locates the position of the specified value within the specified array. For example, ``SELECT array_position(<column_name>,<value>) FROM <table_name>;``. Returns ``NULL`` if the value is not found. + * - ``array_remove`` + - Returns the specified array column with the specified value deducted. For example, ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` + * - ``array_replace`` + - Enables replacing values within an ``ARRAY`` column. For example, ``SELECT array_replace(<column_name>,<value_to_replace>,<value_that_replaces>) FROM <table_name>;`` * - - * - From 131ad9d2507f1646ae9c2b40be6af71504af83cb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 10:09:06 +0300 Subject: [PATCH 0668/1892] 404 --- 404.rst | 16 ++++++------ troubleshooting/information_for_support.rst | 28 ++++++++++----------- 2 files changed, 21 insertions(+), 23 deletions(-) diff --git a/404.rst b/404.rst index aa18f4738..f119ea065 100644 --- a/404.rst +++ b/404.rst @@ -1,18 +1,16 @@ :orphan: -********************************* - Couldn't find the page - 404 -********************************* +************************** +Page Cannot Be Found - 404 +************************** -Unfortunately we could not find this page. +Use the **Search docs** bar, or use the navigation sidebar to find what you're looking for. -Use the **search bar**, or use the navigation sidebar to find what you're looking for. +.. rubric:: Looking for older documentation? -.. rubric:: Looking for the old documentation? - -If you're looking for an older version of the documentation, versions 1.10 through 2019.2.1 are available at http://previous.sqream.com . +Try http://previous.sqream.com .. rubric:: Need help? -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://support.sqream.com>`_ for additional support. +If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional support. diff --git a/troubleshooting/information_for_support.rst b/troubleshooting/information_for_support.rst index fd1cab1fa..159247c95 100644 --- a/troubleshooting/information_for_support.rst +++ b/troubleshooting/information_for_support.rst @@ -1,15 +1,15 @@ .. _information_for_support: -******************************************* +**************************************** Gathering Information for SQream Support -******************************************* +**************************************** .. contents:: :local: :depth: 1 Getting Support and Reporting Bugs -======================================= +================================== When contacting `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_, we recommend reporting the following information: @@ -25,10 +25,10 @@ When possible, please attach as many of the following: * Screen captures if relevant How SQream Debugs Issues -=================================== +======================== Reproduce --------------- +--------- If we are able to easily reproduce your issue in our testing lab, this greatly improves the speed at which we can fix it. @@ -43,7 +43,7 @@ Reproducing an issue consists of understanding: See the :ref:`reproducible_statement` section ahead for information about collecting a full reproducible example. Logs --------- +---- The logs produced by SQream DB contain a lot of information that may be useful for debugging. @@ -53,7 +53,7 @@ See the :ref:`collecting_logs` section ahead for information about collecting a Fix ---------- +--- Once we have a fix, this can be issued as a hotfix to an existing version, or as part of a bigger major release. @@ -62,14 +62,14 @@ Your SQream account manager will keep you up-to-date about the status of the iss .. _reproducible_statement: Collecting a Reproducible Example of a Problematic Statement -=============================================================== +============================================================ SQream DB contains an SQL utility that can help SQream support reproduce a problem with a query or statement. This utility compiles and executes a statement, and collects the relevant data in a small database which can be used to recreate and investigate the issue. SQL Syntax ---------------- +---------- .. code-block:: postgres @@ -81,7 +81,7 @@ SQL Syntax Parameters ---------------- +---------- .. list-table:: :widths: auto @@ -95,7 +95,7 @@ Parameters - Statements to analyze. Example ------------ +------- .. code-block:: postgres @@ -104,14 +104,14 @@ Example .. _collecting_logs: Collecting Logs and Metadata Database -============================================= +===================================== SQream DB comes bundled with a data collection utility and an SQL utility intended for collecting logs and additional information that can help SQream support drill down into possible issues. See more information in the :ref:`Collect logs from your cluster<collecting_logs2>` section of the :ref:`logging` guide. Examples ------------------ +-------- Write an archive to ``/home/rhendricks``, containing log files: @@ -129,7 +129,7 @@ Write an archive to ``/home/rhendricks``, containing log files and metadata data Using the Command Line Utility: -============================================= +=============================== .. code-block:: console From 1cdcb5f2faea61048a8a9d22d5d160fa7193b3c7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 10:12:19 +0300 Subject: [PATCH 0669/1892] Update 404.rst --- 404.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/404.rst b/404.rst index f119ea065..44f92acfd 100644 --- a/404.rst +++ b/404.rst @@ -6,11 +6,9 @@ Page Cannot Be Found - 404 Use the **Search docs** bar, or use the navigation sidebar to find what you're looking for. -.. rubric:: Looking for older documentation? - -Try http://previous.sqream.com - .. rubric:: Need help? -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional support. +If you couldn't find what you're looking for, we're always happy to help. + +Visit the `SQreamDB support portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional help. From 2d43ddec65f1bc81ffdccf24e9e16b55d60667b4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 11:22:57 +0300 Subject: [PATCH 0670/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index d76766fa7..9a3c6c3e6 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: * sqream-mapping.json * sqload-jdbc-oracle-incr.properties * reserved_words.txt * sqloader-0.0.2.jar Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<caseSensitive>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=config file name`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<count>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<cdcDelete>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<drop>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<loadDttm>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<lockCheck>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<lockTable>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<Log directory> path`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=partition name`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<splitByColumn>`` - Column name for split (required for multi thread loads) * - ``-table=<sourceTableName>`` - Source table name to load data from * - ``-target=<targetTableName>`` - Target table name to load data into. Default is same as source table * - ``-target_db=<deprecated>`` - Target DB name to load data into * - ``-thread=<thread>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<type>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<useDbmsLob>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<usePartitions>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: * sqream-mapping.json * sqload-jdbc-oracle-incr.properties * reserved_words.txt * sqloader-0.0.2.jar Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From b96a4d7498a87158eb1ff9af70d41ca3195a00f2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:16:51 +0300 Subject: [PATCH 0671/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 9a3c6c3e6..3007f656c 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: * sqream-mapping.json * sqload-jdbc-oracle-incr.properties * reserved_words.txt * sqloader-0.0.2.jar Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Pre-configured data loading configuration file. * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 1e67549d983a485c2f013c3c669179967a8421aa Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 12:59:37 +0300 Subject: [PATCH 0672/1892] alter permissions --- data_ingestion/ingesting_from_databases.rst | 2 +- .../alter_default_permissions.rst | 55 ++++++++++--------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 3007f656c..f331a1016 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Pre-configured data loading configuration file. * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes the table by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Pre-configured data loading configuration file. * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 95c5acfd0..3a9f08adc 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -1,27 +1,27 @@ .. _alter_default_permissions: -***************************** +************************* ALTER DEFAULT PERMISSIONS -***************************** +************************* -.. contents:: - :local: - :depth: 1 - -Overview -============= The ``ALTER DEFAULT PERMISSIONS`` command lets you grant automatic permissions to future objects. By default, users do not have ``SELECT`` permissions on tables created by other users. Database administrators can grant access to other users by modifying the target role default permissions. For more information about access control, see :ref:`Access Control<access_control>`. +.. contents:: + :local: + :depth: 1 + Permissions -============= +=========== + The ``SUPERUSER`` permission is required to alter default permissions. Syntax -========== +====== + The following is the syntax for altering default permissions: .. code-block:: postgres @@ -54,7 +54,8 @@ The following is the syntax for altering default permissions: Supported Permissions -======================= +===================== + The following table describes the supported permissions: .. list-table:: @@ -93,37 +94,38 @@ The following table describes the supported permissions: Examples -============ +======== .. contents:: :local: :depth: 1 Granting Default Table Permissions -------------------------------------------------- +---------------------------------- + This example is based on the roles **r1** and **r2**, created as follows: .. code-block:: postgres - create role r1; - create role r2; - alter default permissions for r1 for tables grant select to r2; + CREATE ROLE r1; + CREATE ROLE r2; + ALTER DEFAULT PERMISSIONS FOR r1 FOR TABLES GRANT SELECT TO r2; Once created, you can build and run the following query based on the above: .. code-block:: postgres - select + SELECT tdp.database_name as "database_name", ss.schema_name as "schema_name", rs1.name as "table_creator", rs2.name as "grant_to", pts.name as "permission_type" - from sqream_catalog.table_default_permissions tdp - inner join sqream_catalog.roles rs1 on tdp.modifier_role_id = rs1.role_id - inner join sqream_catalog.roles rs2 on tdp.getter_role_id = rs2.role_id - left join sqream_catalog.schemas ss on tdp.schema_id = ss.schema_id - inner join sqream_catalog.permission_types pts on pts.permission_type_id=tdp.permission_type + FROM sqream_catalog.table_default_permissions tdp + INNER JOIN sqream_catalog.roles rs1 on tdp.modifier_role_id = rs1.role_id + INNER JOIN sqream_catalog.roles rs2 on tdp.getter_role_id = rs2.role_id + LEFT JOIN sqream_catalog.schemas ss on tdp.schema_id = ss.schema_id + INNER JOIN sqream_catalog.permission_types pts on pts.permission_type_id=tdp.permission_type ; The following is an example of the output generated from the above queries: @@ -137,7 +139,8 @@ The following is an example of the output generated from the above queries: For more information about default permissions, see `Default Permissions <https://docs.sqream.com/en/latest/reference/catalog_reference_catalog_tables.html#default-permissions.html>`_. Granting Automatic Permissions for Newly Created Schemas -------------------------------------------------- +-------------------------------------------------------- + When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE`` and ``CREATE`` permissions in the new schema, as shown below: .. code-block:: postgres @@ -145,7 +148,8 @@ When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; Granting Automatic Permissions for Newly Created Tables in a Schema ----------------------------------------------------------------- +------------------------------------------------------------------- + When the role ``demo`` creates a new table in schema ``s1``, roles **u1,u2** are granted ``SELECT`` permissions, as shown below: .. code-block:: postgres @@ -153,7 +157,8 @@ When the role ``demo`` creates a new table in schema ``s1``, roles **u1,u2** are ALTER DEFAULT PERMISSIONS FOR demo IN s1 FOR TABLES GRANT SELECT TO u1,u2; Revoking Permissions from Newly Created Tables ---------------------------------------------------------------- +---------------------------------------------- + Revoking permissions refers to using the ``DROP GRANT`` command, as shown below: .. code-block:: postgres From 6090f704f3bbd0bb00dc21a04e7eada6325a75f8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 14:04:22 +0300 Subject: [PATCH 0673/1892] Update alter_default_permissions.rst --- .../access_control_commands/alter_default_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 3a9f08adc..4d9afb893 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -103,7 +103,7 @@ Examples Granting Default Table Permissions ---------------------------------- -This example is based on the roles **r1** and **r2**, created as follows: +Altering the default permissions of **r1** so that **r2** is able to execute ``SELECT`` on **r1** tables: .. code-block:: postgres From f7bc3f0ef429ead253e659e2a0dfc813b70ed658 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 14:38:00 +0300 Subject: [PATCH 0674/1892] Update alter_default_permissions.rst --- .../access_control_commands/alter_default_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 4d9afb893..6d5208e98 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -103,7 +103,7 @@ Examples Granting Default Table Permissions ---------------------------------- -Altering the default permissions of **r1** so that **r2** is able to execute ``SELECT`` on **r1** tables: +Altering the default permissions of **r1** so that **r2** is able to execute ``SELECT`` on tables created by **r1**: .. code-block:: postgres From f9c8b6cae8d30e8a121a0fd59dc088bbfa515592 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 15:24:00 +0300 Subject: [PATCH 0675/1892] Update index.rst --- loading_and_unloading_data/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst index 72a698dc1..88ee2d47a 100644 --- a/loading_and_unloading_data/index.rst +++ b/loading_and_unloading_data/index.rst @@ -6,7 +6,7 @@ Loading and Unloading Data The **Loading Data** section describes concepts and operations related to importing data into your SQream database: -* :ref:`Overview of loading data <inserting_data>` - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. +* :ref:`Overview of loading data <ingesting_data>` - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. * :ref:`Alternatives to loading data (foreign tables) <foreign_tables>` - Useful for running queries directly on external data without importing into your SQream database. From 726c6e6436be72cf4c798a093bb2366351183fbb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jul 2023 17:29:30 +0300 Subject: [PATCH 0676/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 26 ++++++++++++------------ 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 155952fab..8eff1b894 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -32,7 +32,7 @@ Supported Operators =================== .. list-table:: - :widths: auto + :widths: 8 40 :header-rows: 1 * - Operator @@ -54,11 +54,11 @@ Supported Operators * - ``array_remove`` - Returns the specified array column with the specified value deducted. For example, ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` * - ``array_replace`` - - Enables replacing values within an ``ARRAY`` column. For example, ``SELECT array_replace(<column_name>,<value_to_replace>,<value_that_replaces>) FROM <table_name>;`` - * - - - - * - - - + - Enables replacing values within an ``ARRAY`` column. For example, ``SELECT array_replace(<column_name>,<value_to_replace>,<replacing_value>) FROM <table_name>;`` + * - Limiting number of arrayed elements + - You may limit the number of arrayed elements within an ``ARRAY``. For example, ``CREATE TABLE <table_name> (<column1> TEXT[]);`` + * - Creating different column types + - You may create a table that has arrayed columns and non-arrayed columns. For example, ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` * - - * - @@ -71,33 +71,33 @@ Creating a table with arrayed columns: .. code-block:: - CREATE TABLE array (column1 TEXT[], column2 INT[]); + CREATE TABLE array (column1 TEXT[], column2 TEXT[], column3 INT[]); Inserting array values into a table: .. code-block:: - INSERT INTO TABLE array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; + INSERT INTO array VALUES (ARRAY['1','2','3'], ARRAY['4','5','6'], ARRAY[7,8,9,10]); Converting arrayed elements into a set of rows: .. code-block:: - SELECT UNNEST(ARRAY['a','b','c'], ARRAY[1,2,3]); + SELECT UNNEST(ARRAY['1','2','3'], ARRAY['4','5','6']); .. code-block:: column1 | column2 --------+---------- - a | 1 - b | 2 - c | 3 + 1 | 4 + 2 | 5 + 3 | 6 Updating table values: .. code-block:: - INSERT INTO TABLE array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; + INSERT INTO array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; UPDATE array SET arr[0] = '{7,8,9}'; From 9b6887b1df5502ac5ebe661a73d0cb41d2b7a844 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:21:09 +0300 Subject: [PATCH 0677/1892] Update installing_sqream.rst --- getting_started/installing_sqream.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/getting_started/installing_sqream.rst b/getting_started/installing_sqream.rst index 2ed54c1ab..fef12ab36 100644 --- a/getting_started/installing_sqream.rst +++ b/getting_started/installing_sqream.rst @@ -1,11 +1,18 @@ .. _installing_sqream: -**************************** -Installing SQream -**************************** +******************* +Installing SQreamDB +******************* -The **Installing SQream** section includes the following SQream installation methods: +You may choose one of the following installation methods: -* `Installing SQream natively <https://docs.sqream.com/en/latest/installation_guides/installing_sqream_with_binary.html>`_ - Describes installing SQream using binary packages provided by SQream. -* `Installing SQream with Kubernetes <https://docs.sqream.com/en/latest/installation_guides/installing_sqream_with_kubernetes.html>`_ - Describes installing SQream using the Kubernetes open source platform. -* `Installing and running SQream in a Docker container <https://docs.sqream.com/en/latest/installation_guides/running_sqream_in_a_docker_container.html>`_ - Describes how to run SQream in a Docker container. \ No newline at end of file +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Method + - Description + * - :ref:`Installing SQreamDB natively <installing_sqream_with_binary>` + - Describes installing SQreamDB using binary packages provided by SQreamDB + * - :ref:`Installing SQreamDB with Kubernetes <installing_sqream_with_kubernetes>` + - Describes installing SQreamDB using the Kubernetes open source platform From ab60b93c59b5e486be4382f0d66c2f0d1cf8471d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:37:57 +0300 Subject: [PATCH 0678/1892] CEO --- .../executing_statements_in_sqream.rst | 21 ++++++--- reference/cli/sqream_sql.rst | 46 +++++++++---------- sqream_studio_5.4.7/index.rst | 7 +-- 3 files changed, 42 insertions(+), 32 deletions(-) diff --git a/getting_started/executing_statements_in_sqream.rst b/getting_started/executing_statements_in_sqream.rst index 26916f1e6..a9fb5e7a5 100644 --- a/getting_started/executing_statements_in_sqream.rst +++ b/getting_started/executing_statements_in_sqream.rst @@ -1,10 +1,19 @@ .. _executing_statements_in_sqream: -**************************** -Executing Statements in SQream -**************************** -You can execute statements in SQream using one of the following tools: +******************************** +Executing Statements in SQreamDB +******************************** -* `SQream SQL CLI <https://docs.sqream.com/en/latest/reference/cli/sqream_sql.html>`_ - a command line interface -* `SQream Acceleration Studio <https://docs.sqream.com/en/latest/sqream_studio_5.4.3/index.html>`_ - an intuitive and easy-to-use interface. +You may choose one of the following tools for executing statements in SQreamDB: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Tool + - Description + * - :ref:`SQream SQL CLI <sqream_sql_cli_reference>` + - A command line interface + * - :ref:`SQreamDB Acceleration Studio <sqream_studio_>` + - An intuitive and easy-to-use interface diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index a4af489cf..b9feff992 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -1,8 +1,8 @@ .. _sqream_sql_cli_reference: -********************************* +************************ Sqream SQL CLI Reference -********************************* +************************ SQream DB comes with a built-in client for executing SQL statements either interactively or from the command-line. @@ -12,7 +12,7 @@ This page serves as a reference for the options and parameters. Learn more about :local: Installing Sqream SQL -========================= +===================== If you have a SQream DB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. @@ -41,7 +41,7 @@ To run ``sqream sql`` on any other Linux host: master=> _ Troubleshooting Sqream SQL Installation -------------------------------------------- +--------------------------------------- Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. @@ -70,12 +70,12 @@ Solving this error requires installing the ncruses or libtinfo libraries, depend ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` Using Sqream SQL -================= +================ By default, sqream sql runs in interactive mode. You can issue commands or SQL statements. Running Commands Interactively (SQL shell) --------------------------------------------- +------------------------------------------ When starting sqream sql, after entering your password, you are presented with the SQL shell. @@ -139,7 +139,7 @@ The prompt for a multi-line statement will change from ``=>`` to ``.``, to alert Executing Batch Scripts (``-f``) ---------------------------------- +-------------------------------- To run an SQL script, use the ``-f <filename>`` argument. @@ -152,7 +152,7 @@ For example, .. tip:: Output can be saved to a file by using redirection (``>``). Executing Commands Immediately (``-c``) -------------------------------------------- +--------------------------------------- To run a statement from the console, use the ``-c <statement>`` argument. @@ -173,10 +173,10 @@ For example, Examples -=========== +======== Starting a Regular Interactive Shell ------------------------------------ +------------------------------------ Connect to local server 127.0.0.1 on port 5000, to the default built-in database, `master`: @@ -203,7 +203,7 @@ Connect to local server 127.0.0.1 via the built-in load balancer on port 3108, t master=>_ Executing Statements in an Interactive Shell ------------------------------------------------ +-------------------------------------------- Note that all SQL commands end with a semicolon. @@ -256,7 +256,7 @@ Executing SQL Statements from the Command Line .. _controlling_output: Controlling the Client Output ----------------------------------------- +----------------------------- Two parameters control the dispay of results from the client: @@ -264,7 +264,7 @@ Two parameters control the dispay of results from the client: * ``--delimiter`` - changes the record delimiter Exporting SQL Query Results to CSV -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Using the ``--results-only`` flag removes the row counts and timing. @@ -278,7 +278,7 @@ Using the ``--results-only`` flag removes the row counts and timing. 4,bull ,1 Changing a CSV to a TSV -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^ The ``--delimiter`` parameter accepts any printable character. @@ -318,7 +318,7 @@ Assuming a file containing SQL statements (separated by semicolons): time: 0.090697s Connecting Using Environment Variables -------------------------------------- +-------------------------------------- You can save connection parameters as environment variables: @@ -329,7 +329,7 @@ You can save connection parameters as environment variables: $ sqream sql --port=3105 --clustered --username=$SQREAM_USER -d $SQREAM_DATABASE Connecting to a Specific Queue ------------------------------------ +------------------------------ When using the :ref:`dynamic workload manager<workload_manager>` - connect to ``etl`` queue instead of using the default ``sqream`` queue. @@ -345,10 +345,10 @@ When using the :ref:`dynamic workload manager<workload_manager>` - connect to `` Operations and Flag References -=============================== +============================== Command Line Arguments ------------------------ +---------------------- **Sqream SQL** supports the following command line arguments: @@ -401,7 +401,7 @@ Command Line Arguments .. _supported_record_delimiters: Supported Record Delimiters -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^ The supported record delimiters are printable ASCII values (32-126). @@ -410,7 +410,7 @@ The supported record delimiters are printable ASCII values (32-126). * The following characters are **not supported**: ``\``, ``N``, ``-``, ``:``, ``"``, ``\n``, ``\r``, ``.``, lower-case latin letters, digits (0-9) Meta-Commands ----------------- +------------- * Meta-commands in Sqream SQL start with a backslash (``\``) @@ -436,7 +436,7 @@ Meta-Commands - Changes the current connection to an alternate database Basic Commands ------------------------ +-------------- .. list-table:: :widths: 20 30 50 @@ -456,7 +456,7 @@ Basic Commands Moving Around the Command Line ---------------------------------- +------------------------------ .. list-table:: :widths: 17 83 @@ -498,7 +498,7 @@ Moving Around the Command Line - Swaps a character at the cursor with the previous character. Searching ------------- +--------- .. list-table:: :widths: 17 83 diff --git a/sqream_studio_5.4.7/index.rst b/sqream_studio_5.4.7/index.rst index 17c7ae05c..de8138b89 100644 --- a/sqream_studio_5.4.7/index.rst +++ b/sqream_studio_5.4.7/index.rst @@ -1,9 +1,10 @@ .. _sqream_studio_: -********************************** +******************************** SQream Acceleration Studio 5.4.7 -********************************** -The SQream Acceleration Studio 5.4.7 is a web-based client for use with SQream. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQream clusters. +******************************** + +The SQreamDB Acceleration Studio 5.4.7 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. This section describes how to use the SQream Accleration Studio version 5.4.7: From dd34f9b29a91a047f81475a9ccc4411eb2b95104 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jul 2023 09:53:09 +0300 Subject: [PATCH 0679/1892] SEO --- getting_started/index.rst | 7 ++- ...ts_and_running_queries_from_the_editor.rst | 58 ++++++++++++------- 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/getting_started/index.rst b/getting_started/index.rst index 87b98870d..36f2c3296 100644 --- a/getting_started/index.rst +++ b/getting_started/index.rst @@ -1,9 +1,10 @@ .. _getting_started: -************************* +*************** Getting Started -************************* -The **Getting Started** page describes the following things you need to start using SQream: +*************** + +The **Getting Started** page describes the following things you need to start using SQreamDB: .. toctree:: :maxdepth: 1 diff --git a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst index 882b226e0..22666c2bd 100644 --- a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst @@ -2,9 +2,10 @@ .. _editor_top_5.4.7: -**************************** +******************************************************** Executing Statements and Running Queries from the Editor -**************************** +******************************************************** + The **Editor** is used for the following: * Selecting an active database and executing queries. @@ -42,7 +43,8 @@ The following is a brief description of the Editor panels: .. _studio_5.4.7_editor_toolbar: Executing Statements from the Toolbar -================ +===================================== + You can access the following from the Toolbar pane: * **Database dropdown list** - select a database that you want to run statements on. @@ -82,7 +84,8 @@ For more information on stopping active statements, see the :ref:`STOP_STATEMENT .. _studio_5.4.7_editor_db_tree: Performing Statement-Related Operations from the Database Tree -================ +============================================================== + From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). @@ -207,8 +210,9 @@ The database object functions are used to perform the following: - The `DDL Optimizer <https://docs.sqream.com/en/latest/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.html#optimizing-database-tables-using-the-ddl-optimizer>`_ lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer ------------------------ -The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQream's best practices. +-------------------------------------------------- + +The **DDL Optimizer** tab analyzes database tables and recommends possible optimizations according to SQreamDB's best practices. As described in the previous table, you can access the DDL Optimizer by clicking the **additional options icon** and selecting **DDL Optimizer**. @@ -232,21 +236,23 @@ Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimiz For more information, see `Optimization and Best Practices <https://docs.sqream.com/en/latest/operational_guides/optimization_best_practices.html>`_. Executing Pre-Defined Queries from the System Queries Panel ---------------- +----------------------------------------------------------- + The **System Queries** panel lets you execute predefined queries and includes the following system query types: * **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. :: -* **Admin queries** - Queries useful for SQream database management. +* **Admin queries** - Queries useful for SQreamDB database management. Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. .. _studio_5.4.7_editor_statement_area: Writing Statements and Queries from the Statement Panel -============== +======================================================= + The multi-tabbed statement area is used for writing queries and statements, and is used in tandem with the toolbar. When writing and executing statements, you must first select a database from the **Database** dropdown menu in the toolbar. When you execute a statement, it passes through a series of statuses until completed. Knowing the status helps you with statement maintenance, and the statuses are shown in the **Results panel**. The auto-complete feature assists you when writing statements by suggesting statement options. @@ -274,11 +280,11 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQream, see `Getting Started <https://docs.sqream.com/en/latest/first_steps.html#first-steps>`_. +.. tip:: If this is your first time using SQreamDB, see :ref:`Getting Started <getting_started>`. .. Keyboard shortcuts -.. ^^^^^^^^^^^^^^^^^^^^^^^^^ +.. ^^^^^^^^^^^^^^^^^^ .. :kbd:`Ctrl` +: kbd:`Enter` - Execute all queries in the statement area, or just the highlighted part of the query. @@ -297,7 +303,8 @@ You can also rename the default tab name by double-clicking it and typing a new .. _results_panel_5.4.7: Viewing Statement and Query Results from the Results Panel -============== +========================================================== + The results panel shows statement and query results. By default, only the first 10,000 results are returned, although you can modify this from the :ref:`studio_editor_toolbar`, as described above. By default, executing several statements together opens a separate results tab for each statement. Executing statements together executes them serially, and any failed statement cancels all subsequent executions. .. image:: /_static/images/results_panel.png @@ -323,7 +330,8 @@ The following is a brief description of the Results panel views highlighted in t :ref:`Back to Executing Statements and Running Queries from the Editor<editor_top_5.4.7>` Searching Query Results in the Results View ----------------- +------------------------------------------- + The **Results view** lets you view search query results. From this view you can also do the following: @@ -335,13 +343,15 @@ From this view you can also do the following: * Sort column results. Saving Results to the Clipboard -^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. .. _save_results_to_local_file_5.4.7: Saving Results to a Local File -^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The **Save results to local file** functions lets you save your search query results to a local file. Clicking **Save results to local file** downloads the contents of the Results panel to an Excel sheet. You can then use copy and paste this content into other editors as needed. In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. @@ -349,7 +359,8 @@ In the Results view you can also run parallel statements, as described in **Runn .. _running_parallel_statements_5.4.7: Running Parallel Statements -^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + While Studio's default functionality is to open a new tab for each executed statement, Studio supports running parallel statements in one statement tab. Running parallel statements requires using macros and is useful for advanced users. The following shows the syntax for running parallel statements: @@ -371,7 +382,8 @@ The following shows the syntax for running parallel statements: .. _execution_tree_5.4.7: Execution Details View --------------- +---------------------- + The **Execution Details View** section describes the following: .. contents:: @@ -379,7 +391,8 @@ The **Execution Details View** section describes the following: :depth: 1 Overview -^^^^^^^^^^^^ +^^^^^^^^ + Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. .. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. @@ -415,7 +428,8 @@ Each node displays a number displaying its **node ID**, its **type**, **table na .. image:: /_static/images/nodes.png Viewing Query Statistics -^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^ + The following statistical information is displayed in the top left corner, as shown in the figure above: * **Query Statistics**: @@ -460,7 +474,8 @@ Note that you can scroll the Node Statistics table. You can also download the ex :align: middle Using the Plain View -^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^ + You can use the **Plain View** instead of viewing the execution tree by clicking **Plain View** |icon-plain| in the top right corner. The plain view displays the same information as shown in the execution tree in table format. .. |icon-plain| image:: /_static/images/studio_icon_plain.png @@ -482,7 +497,8 @@ This can be seen in the **timeSum** column as follows: .. _sql_view_5.4.7: Viewing Wrapped Strings in the SQL View ------------------- +--------------------------------------- + The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. .. _save_results_to_clipboard_5.4.7: From e4f8a4aecfb53aabc909172068db1a9864b95b70 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jul 2023 10:53:35 +0300 Subject: [PATCH 0680/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 70 ++++++++++++------------ 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 8eff1b894..2de01f563 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -4,20 +4,20 @@ Array ***** -The ``ARRAY`` data type offers a convenient way to store ordered collections of elements in a single column. It provides storage efficiency by allowing multiple values of the same data type to be compactly stored, optimizing space utilization and enhancing database performance. Working with arrays simplifies queries as operations and manipulations can be performed on the entire array, resulting in more concise and readable code. +The ``ARRAY`` data type offers a convenient way to store ordered collections of elements in a single column. It provides storage efficiency by allowing multiple values of the same data type to be compactly stored, optimizing space utilization and enhancing database performance. Working with ``ARRAY`` simplifies queries as operations and manipulations can be performed on the entire ``ARRAY``, resulting in more concise and readable code. -An array represents a sequence of zero or more elements of the same data type. Arrays in the same column can contain varying numbers of elements across different rows. Arrays can include null values, eliminating the need for separate SQL declarations. +An ``ARRAY`` represents a sequence of zero or more elements of the same data type. Arrays in the same column can contain varying numbers of elements across different rows. Arrays can include null values, eliminating the need for separate SQL declarations. -Each data type has its companion array type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. +Each data type has its companion ``ARRAY`` type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. .. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. Syntax ====== -Defining an array is done by appending the ``[]`` notation to a supported data type, for example, ``int[]`` for an array of integers. +Defining an ``ARRAY`` is done by appending the ``[]`` notation to a supported data type, for example, ``INT[]`` for an array of integers. -.. code-block:: +.. code-block:: sql CREATE TABLE <table_name> (<column1> TEXT[], <column2> INT[]) @@ -26,7 +26,7 @@ Defining an array is done by appending the ``[]`` notation to a supported data t Size ==== -The maximum size of an array, indicating the number of elements it can hold, is 65535. You have the option to specify the array size, providing a maximum allowed size, while each row can have a different number of elements up to the specified maximum. If the array size is not specified, the maximum size is assumed. +The maximum size of an ``ARRAY``, indicating the number of elements it can hold, is 65535. You have the option to specify the size of an ``ARRAY``, providing a maximum allowed size, while each row can have a different number of elements up to the specified maximum. If the ``ARRAY`` size is not specified, the maximum size is assumed. Supported Operators =================== @@ -38,11 +38,11 @@ Supported Operators * - Operator - Description * - Literals ``ARRAY []`` - - An array literal can be created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3]`` + - Literals are created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3]`` * - Mapping - - Parquet, ORC, JSON, and AVRO array types may be mapped into SQreamDB arrays + - Parquet, ORC, JSON, and AVRO ``ARRAY`` types may be mapped into SQreamDB ``ARRAY`` * - Indexing - - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT <column_name>[2] FROM <table_name>`` returns the third array element of the specified column + - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT <column_name>[2] FROM <table_name>`` returns the third element of the specified column * - ``UNNEST`` - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST <column_name> FROM <table_name>`` * - Concatenate ``||`` @@ -52,60 +52,58 @@ Supported Operators * - ``array_position`` - Locates the position of the specified value within the specified array. For example, ``SELECT array_position(<column_name>,<value>) FROM <table_name>;``. Returns ``NULL`` if the value is not found. * - ``array_remove`` - - Returns the specified array column with the specified value deducted. For example, ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` + - Returns the specified ``ARRAY`` column with the specified value deducted. For example, ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` * - ``array_replace`` - Enables replacing values within an ``ARRAY`` column. For example, ``SELECT array_replace(<column_name>,<value_to_replace>,<replacing_value>) FROM <table_name>;`` * - Limiting number of arrayed elements - You may limit the number of arrayed elements within an ``ARRAY``. For example, ``CREATE TABLE <table_name> (<column1> TEXT[]);`` * - Creating different column types - You may create a table that has arrayed columns and non-arrayed columns. For example, ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` - * - - - - * - - - + Examples ======== Creating a table with arrayed columns: -.. code-block:: +.. code-block:: sql - CREATE TABLE array (column1 TEXT[], column2 TEXT[], column3 INT[]); + CREATE TABLE my_array (clmn1 TEXT[], clmn2 TEXT[], clmn3 INT[]); -Inserting array values into a table: +Inserting arrayed values into a table: -.. code-block:: +.. code-block:: sql - INSERT INTO array VALUES (ARRAY['1','2','3'], ARRAY['4','5','6'], ARRAY[7,8,9,10]); + INSERT INTO my_array VALUES (ARRAY['1','2','3'], ARRAY['4','5','6'], ARRAY[7,8,9,10]); Converting arrayed elements into a set of rows: -.. code-block:: +.. code-block:: sql SELECT UNNEST(ARRAY['1','2','3'], ARRAY['4','5','6']); -.. code-block:: +.. code-block:: console - column1 | column2 - --------+---------- - 1 | 4 - 2 | 5 - 3 | 6 + clmn1 | clmn2 | clmn3 + ----------+-----------+----------- + "1" | "4" | [7,8,9,10] + "2" | "5" | + "3" | "6" | Updating table values: -.. code-block:: - - INSERT INTO array VALUES ARRAY['a','b','c'], ARRAY[1,2,3]; +.. code-block:: sql - UPDATE array SET arr[0] = '{7,8,9}'; + UPDATE my_array SET clmn1[0] = 'A'; - SELECT * FROM array; + SELECT * FROM my_array; -.. code-block:: +.. code-block:: console + + clmn1 | clmn2 | clmn3 + ---------------------+------------------+----------- + ["A","1","2","3"] | ["4","5","6"] | [7,8,9,10] + +Limitations +=========== - column1 | column2 - --------+---------- - - \ No newline at end of file From 3812e71bf5ad28bfa1752d777e97bd6e61accc48 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:22:24 +0300 Subject: [PATCH 0681/1892] SQLoader --- data_ingestion/connection_string.java | 19 +++++++++++++++++++ data_ingestion/ingesting_from_databases.rst | 2 +- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 data_ingestion/connection_string.java diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java new file mode 100644 index 000000000..0bcfadeb0 --- /dev/null +++ b/data_ingestion/connection_string.java @@ -0,0 +1,19 @@ +##Postgresql, Oracle, and SQreamDB Connection Strings - mandatory! + +#postgres +source.jdbc.connectionstring=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> + +#oracle +source.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> + +#sqream +sqream.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> + + +##Optional + +#Oracle +#catalog.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> + +#SQreamDB +#catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index f331a1016..c1268ea7a 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Pre-configured data loading configuration file. * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - Description * - ``-batchsize=<batchSize>`` - The number of records to be inserted into SQreamDB at once. Default is ``10.000`` * - ``-casesensative=<true/false>`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB. Default is ``false`` * - ``-chunkSize=<chunkSize>`` - The number of records read at once from the source database. Default is ``0`` * - ``-columnlist=<columnFilePath>`` - The name of the file that contains all column names * - ``-columns=<columns>`` - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). Default is all * - ``-config=<config_file_name>`` - Defines the configuration file you wish to use. Default is ``config/sqload-jdbc-oracle-incr.properties`` * - ``-count=<true/false>`` - Defines whether or not table rows will be counted before being loaded into SQreamDB Default is ``true`` * - ``-delete=<true/false>`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows. Default is ``true`` * - ``-drop=<true/false>`` - Defines whether or not a new target table in SQreamDB is created. Default is ``true``. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - The number of records to be read at once from source database. Default is ``100000`` * - ``-filter=<filter>`` - Defines whether or not only records with SQL conditions are loaded. Default is ``1=1`` * - ``-h, --help`` - Displays the help menu and exits * - ``-limit=<limit>`` - Limits the number of rows to be loaded. Default is ``0`` * - ``-load_dttm=<true/false>`` - Add an additional ``load_dttm`` column that defines the time and date of loading. Default:true * - ``-lock_check=<true/false>`` - Defines whether or not SQLoader will check source table is locked before the loading starts. Default is ``true`` * - ``-lock_table=<true/false>`` - Defines whether or not SQLoader will lock target table before the loading starts. Default is ``true`` * - ``-log_dir=<log_directory_path>`` - Defines the path of log directory created when loading data. Default is ``logs`` * - ``-partition=<partition_name>`` - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Defines whether or not SQLoader will get row IDs from Oracle tables. Default is ``false`` * - ``-split=<split_by_column>`` - Column name for split (required for multi thread loads) * - ``-table=<source_table_name>`` - Source table name to load data from * - ``-target=<target_table_name>`` - Target table name to load data into. Default is same as source table * - ``-target_db=deprecated`` - Target DB name to load data into * - ``-thread=<number_of_threads>`` - Number of threads to be used during loading. Default is ``1`` * - ``-truncate=<true/false>`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Defines a loading type that affects the table that is created in SQreamDB. Default is ``full``. Options are ``full``, ``cdc``, or ``incremental`` * - ``-use_dbms_lob=<true/false>`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types. Default is ``true`` * - ``-use_partitions=<true/false>`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements. Default is ``true`` Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Examples ======== Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle-incr.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user=`` - Username of a role to use for connection * - ``password=`` - Specifies the password of the selected role * - ``ssl=`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize=<batchSize>`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once * - ``-casesensative=<true/false>`` - Optional - ``false`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize=<chunkSize>`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist=<columnFilePath>`` - Optional - None - The name of the file that contains all column names * - ``-columns=<columns>`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config=<config_file_name>`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count=<true/false>`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete=<true/false>`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop=<true/false>`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter=<filter>`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit=<limit>`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm=<true/false>`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir=<log_directory_path>`` - Optional - ``logs`` - Defines the path of log directory created when loading data * - ``-partition=<partition_name>`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split=<split_by_column>`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table=<source_table_name>`` - Mandatory - None - Source table name to load data from * - ``-target=<target_table_name>`` - Optional - Source table name - Target table name to load data into * - ``-target_db=deprecated`` - Optional - None - Target database name to load data into * - ``-thread=<number_of_threads>`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate=<true/false>`` - Optional - ``false`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 144e4151667fffe814bcf7c5e12d8341bd372265 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:49:22 +0300 Subject: [PATCH 0682/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 70 +++++++++++++++++++++--- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 2de01f563..a35a69cc4 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -10,6 +10,8 @@ An ``ARRAY`` represents a sequence of zero or more elements of the same data typ Each data type has its companion ``ARRAY`` type, such as ``INT[]`` for integers and ``TEXT[]`` for text values. +You may use the ``ARRAY`` data type with all :ref:`SQreamDB connectors <connecting_to_sqream>`, except for ODBC since the ODBC protocol does not support ``ARRAY``. + .. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. Syntax @@ -42,11 +44,11 @@ Supported Operators * - Mapping - Parquet, ORC, JSON, and AVRO ``ARRAY`` types may be mapped into SQreamDB ``ARRAY`` * - Indexing - - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT <column_name>[2] FROM <table_name>`` returns the third element of the specified column + - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT (<column_name>[2]) FROM <table_name>`` returns the third element of the specified column * - ``UNNEST`` - - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST <column_name> FROM <table_name>`` + - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST (<column_name>) FROM <table_name>`` * - Concatenate ``||`` - - Converts arrayed elements into one string. For example, ``SELECT <column_name> || <column2_name> FROM <table_name>`` + - Converts arrayed elements into one string. For example, ``SELECT (<column_name>) || (<column2_name>) FROM <table_name>`` * - ``array_length`` - Returns the number of arrayed elements within the specified column. For example, ``SELECT array_length(<column_name>) FROM <table_name>`` * - ``array_position`` @@ -64,6 +66,9 @@ Supported Operators Examples ======== +``ARRAY`` Statements +-------------------- + Creating a table with arrayed columns: .. code-block:: sql @@ -84,12 +89,12 @@ Converting arrayed elements into a set of rows: .. code-block:: console - clmn1 | clmn2 | clmn3 - ----------+-----------+----------- - "1" | "4" | [7,8,9,10] - "2" | "5" | - "3" | "6" | - + clmn1 | clmn2 + ----------+---------- + "1" | "4" + "2" | "5" + "3" | "6" + Updating table values: .. code-block:: sql @@ -104,6 +109,53 @@ Updating table values: ---------------------+------------------+----------- ["A","1","2","3"] | ["4","5","6"] | [7,8,9,10] +Mapping JSON Files +------------------ + + + Limitations =========== +Casting +------- + +Numeric +^^^^^^^ + +Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and ``BOOL``, must explicitly be cast. + +.. code-block:: sql + + CREATE OR REPLACE TABLE my_array (clmn1 tinyint []); + SELECT array_replace(clmn1 , 4::tinyint, 5::tinyint) from my_array; + + CREATE OR REPLACE TABLE my_array (clmn1 bool []); + SELECT array_replace(clmn1 , 0::bool, 1::bool) from my_array; + +TEXT +^^^^ + +Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not supported. + +Functions +--------- + +``||`` (Concatenate) +^^^^^^^^^^^^^^^^^^^^ + +Using the ``||`` (Concatenate) function with two different data types requires explicit casting. + +.. code-block:: sql + + SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) from my_array; + +``UNNEST`` +^^^^^^^^^^ + +It is possible to use the ``UNNEST`` operator within a statement only once. + +Window +^^^^^^ + +Window functions are not supported. \ No newline at end of file From 97ffb06a632ee477debb39e5524efc111ecdcb79 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 11:22:06 +0300 Subject: [PATCH 0683/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 39 ++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index a35a69cc4..d6d12f06d 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -109,10 +109,45 @@ Updating table values: ---------------------+------------------+----------- ["A","1","2","3"] | ["4","5","6"] | [7,8,9,10] -Mapping JSON Files ------------------- +JSON Files +---------- +Consider the following JSON file to be ingested into SQreamDB: +.. code-block:: json + + { "name":"Avery Bradley", "age":25, "position":"PG", {years_in_nba":[2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} + { "name":"Jae Crowder", "age":25, "position":"PG" }, {years_in_nba":[2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} + { "name":"John Holland", "age":27, "position":"SG" }, {years_in_nba":[2017, 2018]"} + +Execute the following statement: + +.. code-block:: sql + + CREATE FOREIGN TABLE nba + (name text not null), + (age int not null), + (position text not null), + (years_in_nba int[] not null) + + WRAPPER json_fdw + OPTIONS + ( + location = 'nba.json' + ) + ; + + SELECT * FROM nba; + +Result: + +.. code-block:: console + + name | age | position | years_in_nba + ---------------+--------+-------------+------------------------------------------------------------------------- + Avery Bradley | 25 | PG | [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] + Jae Crowder | 25 | PG | [2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] + John Holland | 27 | SG | [2017, 2018] Limitations =========== From b39b26209fcf1650c16cd9df1c1b31fa6b646e5e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 11:37:24 +0300 Subject: [PATCH 0684/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 57 ++++++++++++++---------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index d6d12f06d..2725fb631 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -34,34 +34,45 @@ Supported Operators =================== .. list-table:: - :widths: 8 40 + :widths: auto :header-rows: 1 * - Operator - Description + - Example * - Literals ``ARRAY []`` - - Literals are created using the ``ARRAY`` operator. For example, ``ARRAY[1,2,3]`` + - Literals are created using the ``ARRAY`` operator + - ``ARRAY[1,2,3]`` * - Mapping - Parquet, ORC, JSON, and AVRO ``ARRAY`` types may be mapped into SQreamDB ``ARRAY`` + - See extended section under **Examples** * - Indexing - - Access to specific elements within the array by using a **zero-based index**. For example, ``SELECT (<column_name>[2]) FROM <table_name>`` returns the third element of the specified column + - Access to specific elements within the array by using a **zero-based index** + - ``SELECT (<column_name>[2]) FROM <table_name>`` returns the third element of the specified column * - ``UNNEST`` - - Converts the arrayed elements within a single row into a set of rows. For example, ``SELECT UNNEST (<column_name>) FROM <table_name>`` + - Converts the arrayed elements within a single row into a set of rows + - ``SELECT UNNEST (<column_name>) FROM <table_name>`` * - Concatenate ``||`` - - Converts arrayed elements into one string. For example, ``SELECT (<column_name>) || (<column2_name>) FROM <table_name>`` + - Converts arrayed elements into one string + - ``SELECT (<column_name>) || (<column2_name>) FROM <table_name>`` * - ``array_length`` - - Returns the number of arrayed elements within the specified column. For example, ``SELECT array_length(<column_name>) FROM <table_name>`` + - Returns the number of arrayed elements within the specified column + - ``SELECT array_length(<column_name>) FROM <table_name>`` * - ``array_position`` - - Locates the position of the specified value within the specified array. For example, ``SELECT array_position(<column_name>,<value>) FROM <table_name>;``. Returns ``NULL`` if the value is not found. + - Locates the position of the specified value within the specified array. Returns ``NULL`` if the value is not found + - ``SELECT array_position(<column_name>,<value>) FROM <table_name>;`` * - ``array_remove`` - - Returns the specified ``ARRAY`` column with the specified value deducted. For example, ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` + - Returns the specified ``ARRAY`` column with the specified value deducted + - ``SELECT array_remove(<column_name>,<value>) FROM <table_name>;`` * - ``array_replace`` - - Enables replacing values within an ``ARRAY`` column. For example, ``SELECT array_replace(<column_name>,<value_to_replace>,<replacing_value>) FROM <table_name>;`` + - Enables replacing values within an ``ARRAY`` column + - ``SELECT array_replace(<column_name>,<value_to_replace>,<replacing_value>) FROM <table_name>;`` * - Limiting number of arrayed elements - - You may limit the number of arrayed elements within an ``ARRAY``. For example, ``CREATE TABLE <table_name> (<column1> TEXT[]);`` + - You may limit the number of arrayed elements within an ``ARRAY`` + - ``CREATE TABLE <table_name> (<column1> TEXT[]);`` * - Creating different column types - - You may create a table that has arrayed columns and non-arrayed columns. For example, ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` - + - You may create a table that has arrayed columns and non-arrayed columns + - ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` Examples ======== @@ -152,11 +163,11 @@ Result: Limitations =========== -Casting -------- +Casting Limitations +------------------- Numeric -^^^^^^^ +~~~~~~~ Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and ``BOOL``, must explicitly be cast. @@ -169,15 +180,15 @@ Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and SELECT array_replace(clmn1 , 0::bool, 1::bool) from my_array; TEXT -^^^^ +~~~~ Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not supported. -Functions ---------- +Function Limitations +-------------------- -``||`` (Concatenate) -^^^^^^^^^^^^^^^^^^^^ +|| (Concatenate) +~~~~~~~~~~~~~~~~ Using the ``||`` (Concatenate) function with two different data types requires explicit casting. @@ -185,12 +196,12 @@ Using the ``||`` (Concatenate) function with two different data types requires e SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) from my_array; -``UNNEST`` -^^^^^^^^^^ +UNNEST +~~~~~~ It is possible to use the ``UNNEST`` operator within a statement only once. Window -^^^^^^ +~~~~~~ Window functions are not supported. \ No newline at end of file From 140f1677b162cfccd4fb97b77d4025c77ee63ff9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 11:58:03 +0300 Subject: [PATCH 0685/1892] flags --- .../current_method_configuration_levels.rst | 3 +-- ...ent_method_showing_all_flags_in_the_catalog_table.rst | 9 +++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 27f8af8e9..68661fd55 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -28,8 +28,7 @@ Flag List .. list-table:: :header-rows: 1 - :widths: 1 2 1 15 1 20 - :class: my-class + :widths: auto :name: my-name * - Flag Name diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst index 647a401b6..235d2ac72 100644 --- a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -1,15 +1,16 @@ .. _current_method_showing_all_flags_in_the_catalog_table: -************************** +************************************** Showing All Flags in the Catalog Table -************************** +************************************** + SQream uses the **sqream_catalog.parameters** catalog table for showing all flags, providing the scope (default, cluster and session), description, default value and actual value. The following is the correct syntax for a catalog table query: -.. code-block:: console +.. code-block:: sql - SELECT * FROM sqream_catalog.settings + SELECT * FROM sqream_catalog.settings; The following is an example of a catalog table query: From 54701bcec1bda9cef64e922414054fad993aee71 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 12:37:48 +0300 Subject: [PATCH 0686/1892] rn --- releases/2022.1.3.rst | 29 +++++++++++++++++++---------- releases/2022.1_index.rst | 5 +++-- releases/index.rst | 4 ++-- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index e31c6728f..fa00e8fd0 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -1,8 +1,9 @@ .. _2022.1.3: -************************** +********************** Release Notes 2022.1.3 -************************** +********************** + The 2022.1.3 release notes were released on 9/20/2022 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2022.1.3 release notes were released on 9/20/2022 and describe the following :depth: 1 Version Content ----------- +--------------- + The 2022.1.3 Release Notes describes the following: * Optimize the delete operation by removing redundant calls. @@ -34,7 +36,8 @@ The storage version presently in effect is version 42. Known Issues ---------- +------------ + The following table lists the issues that are known limitations in Version 2022.1.3: +-------------+--------------------------------------------------------------------------------------------+ @@ -45,7 +48,8 @@ The following table lists the issues that are known limitations in Version 2022. Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1.3: +-------------+-------------------------------------------------------------------------------------------------+ @@ -69,15 +73,18 @@ The following table lists the issues that were resolved in Version 2022.1.3: Operations and Configuration Changes --------- +------------------------------------ + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective immediately. @@ -87,11 +94,13 @@ TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type sup As part of this release 2022.1.3, SQream provides an automated and secured migration tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information. End of Support -------- +-------------- + No End of Support changes were made. Upgrading to v2022.1.3 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst index e63294405..302ae3a96 100644 --- a/releases/2022.1_index.rst +++ b/releases/2022.1_index.rst @@ -1,8 +1,9 @@ .. _2022.1_index: -************************** +******************** Release Notes 2022.1 -************************** +******************** + The 2022.1 Release Notes describe the following releases: .. contents:: diff --git a/releases/index.rst b/releases/index.rst index 9c1b8d2f6..25b834bc6 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -1,8 +1,8 @@ .. _releases: -********** +************* Release Notes -********** +************* .. list-table:: From 4a62403df095da99884b79f6247b023525f251ce Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 13:34:45 +0300 Subject: [PATCH 0687/1892] maintenance --- architecture/index.rst | 5 +- .../processes_and_network_architecture.rst | 51 ----- connecting_to_sqream/client_drivers/index.rst | 31 +-- .../connecting_clients_to_sqream.rst | 26 --- .../installing_and_launching_sqream.rst | 5 +- ...lling_prometheus_using_binary_packages.rst | 21 +- .../monitoring_query_performance.rst | 196 +++++++++++------- .../access_control_commands/revoke.rst | 18 +- releases/2021.1_index.rst | 6 +- ...orkers_and_services_from_the_dashboard.rst | 32 +-- 10 files changed, 183 insertions(+), 208 deletions(-) delete mode 100644 architecture/processes_and_network_architecture.rst delete mode 100644 getting_started/connecting_clients_to_sqream.rst diff --git a/architecture/index.rst b/architecture/index.rst index 5e4d6c867..f4aa7072c 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -1,8 +1,8 @@ .. _architecture: -*********************** +******************* System Architecture -*********************** +******************* This topic includes guides that walk an end-user, database administrator, or system architect through the main ideas behind SQream DB. @@ -17,5 +17,4 @@ Explore the guides below for information about SQream DB's architecture. :titlesonly: internals_architecture - xxprocesses_and_network_architecture filesystem_and_filesystem_usage diff --git a/architecture/processes_and_network_architecture.rst b/architecture/processes_and_network_architecture.rst deleted file mode 100644 index 8a458f8d5..000000000 --- a/architecture/processes_and_network_architecture.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _processes_and_network_architecture: - -************************************* -Processes and network architecture -************************************* - -A SQream DB installation contains several components: - -* SQream DB workers (``sqreamd``) -* Metadata daemon (``metadata_server``) -* Load balancer (``server_picker``) - - -.. - processes in sqream: - - metadatad - server picker - sqreamd - - monit system - - pacemaker system - - vip - - ui? - - dashboard? - - mention the command line utils here? - - network - - clients connecting, the wlm redirect - - structure of a embedded metadata sqream - simple (do we need to - mention this in the docs, or is it only for troubleshooting in - production) - - single node with separate sqreamds - connections between the - components, server picker, metadata - - multiple nodes - - basic network connections/routes needed - - what's also needed for the pacemaker component - + how the vip works - - diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 5a8faeeef..41577d0b6 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -14,59 +14,50 @@ All Operating Systems The following are applicable to all operating systems: -.. _jdbc: -* **JDBC** - recommended installation via ``mvn``: +**JDBC** - recommended installation via ``mvn``: * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.9.jar>`_ - sqream-jdbc-4.5.9 (.jar) * :ref:`java_jdbc` -.. _.net: -* **.NET**: +**.NET**: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ * :ref:`net` -.. _trino: -* **Trino**: +**Trino**: * Trino Connector * :ref:`trino` -.. _spark: -* **Spark**: +**Spark**: * `Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`spark` -.. _python: -* **Python** - Recommended installation via ``pip``: +**Python** - Recommended installation via ``pip``: * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ - pysqream v3.2.5 (.tar.gz) * :ref:`pysqream` -.. _nodejs: -* **Node.JS** - Recommended installation via ``npm``: +**Node.JS** - Recommended installation via ``npm``: * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) * :ref:`nodejs` -.. _tableau_connector: -* **Tableau**: +**Tableau**: * `Tableau connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - SQream (.taco) * :ref:`tableau` - -.. _powerbi_connector: -* **Power BI**: +**Power BI**: * `Power BI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) * :ref:`power_bi` @@ -105,8 +96,4 @@ The following are applicable to Windows: .. rubric:: Need help? -If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ - -.. rubric:: Looking for older drivers? - -If you're looking for an older version of SQreamDB drivers, visit `here <https://sqream.com/product/client-drivers/>`_. \ No newline at end of file +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file diff --git a/getting_started/connecting_clients_to_sqream.rst b/getting_started/connecting_clients_to_sqream.rst deleted file mode 100644 index a1ed59cf1..000000000 --- a/getting_started/connecting_clients_to_sqream.rst +++ /dev/null @@ -1,26 +0,0 @@ -.. _connecting_clients_to_sqream: - -**************************** -Connecting Clients to SQream -**************************** -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. - -SQream supports the following client platforms: - -* Connect to SQream Using SQL Workbench -* Connecting to SQream Using Tableau -* Connect to SQream Using Pentaho Data Integration -* Connect to SQream Using MicroStrategy -* Connect to SQream Using R -* Connect to SQream Using PHP -* Connect to SQream Using SAS Viya - -SQream supports the following client drivers: - -* JDBC -* Python (pysqream) -* Node.JS -* ODBC -* C++ Driver - -For more information, see `Third Party Tools<https://docs.sqream.com/en/latest/third_party_tools/index.html>`_. \ No newline at end of file diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 6a41ba52b..478d76df1 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -1,8 +1,9 @@ .. _installing_and_launching_sqream: -************************* +******************************* Installing and Launching SQream -************************* +******************************* + The **Installing and Launching SQream** page includes the following installation guides: .. toctree:: diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst index 5031ec181..add951b1c 100644 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -2,11 +2,9 @@ .. _install_prometheus_binary_top: -*********************** +******************************************* Installing Prometheus Using Binary Packages -*********************** - - +******************************************* The **Installing Prometheus Using Binary Packages** guide includes the following sections: @@ -15,11 +13,13 @@ The **Installing Prometheus Using Binary Packages** guide includes the following :depth: 1 Overview -^^^^^^^^^^^^^^^ +^^^^^^^^ + Prometheus is an application used for event monitoring and alerting. Installing Prometheus -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ + You must install Prometheus before installing the Dashboard Data Collector. **To install Prometheus:** @@ -107,7 +107,8 @@ For more information on installing the Dashboard Data Collector, see `Installing Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Configuring Your Prometheus Settings -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + After installing Prometheus you must configure your Prometheus settings. You must perform all Prometheus configurations in the **/etc/prometheus/prometheus.yml** file. **To configure your Prometheus settings:** @@ -163,7 +164,8 @@ After installing Prometheus you must configure your Prometheus settings. You mus Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Configuring Your Prometheus Service File -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + After configuring your Prometheus settings you must configure your Prometheus service file. **To configure your Prometheus service file**: @@ -219,7 +221,8 @@ After configuring your Prometheus settings you must configure your Prometheus se Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Accessing the Prometheus User Interface -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + After configuring your prometheus service file, you can access the Prometheus user interface. You can access the Prometheus user interface by running the following command: diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index cca8eb4ea..1d10fb819 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -1,8 +1,9 @@ .. _monitoring_query_performance: -********************************* +**************************** Monitoring Query Performance -********************************* +**************************** + When analyzing options for query tuning, the first step is to analyze the query plan and execution. The query plan and execution details explain how SQream DB processes a query and where time is spent. This document details how to analyze query performance with execution plans. @@ -12,18 +13,22 @@ See also our :ref:`sql_best_practices` guide for more information about data loa .. contents:: In this section: :local: + :depths: 1 Setting Up the System for Monitoring -================================================= +==================================== + By default, SQream DB logs execution details for every statement that runs for more than 60 seconds. If you want to see the execution details for a currently running statement, see :ref:`using_show_node_info` below. Adjusting the Logging Frequency ---------------------------------------- +------------------------------- + To adjust the frequency of logging for statements, you may want to reduce the interval from 60 seconds down to, say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggingSec`` parameter as you see fit: -.. code-block:: json +.. code-block:: sql + :emphasize-lines: 7 { @@ -38,13 +43,15 @@ say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggi } } After restarting the SQream DB cluster, the execution plan details will be logged to the :ref:`standard SQream DB logs directory<logging>`, as a message of type ``200``. -You can see these messages with a text viewer or with queries on the log :ref:`external_tables`. +You can see these messages with a text viewer or with queries on the log :ref:`foreign_tables`. Reading Execution Plans with a Foreign Table ------------------------------------------------------ +-------------------------------------------- + First, create a foreign table for the logs -.. code-block:: postgres +.. code-block:: sql + CREATE FOREIGN TABLE logs ( start_marker TEXT(4), @@ -73,7 +80,8 @@ First, create a foreign table for the logs Once you've defined the foreign table, you can run queries to observe the previously logged execution plans. This is recommended over looking at the raw logs. -.. code-block:: psql +.. code-block:: sql + t=> SELECT message . FROM logs . WHERE message_type_id = 200 @@ -103,7 +111,8 @@ This is recommended over looking at the raw logs. .. _using_show_node_info: Using the ``SHOW_NODE_INFO`` Command -===================================== +==================================== + The :ref:`show_node_info` command returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. The :ref:`show_node_info` result, just like the periodically-logged execution plans described above, are an at-the-moment view of the compiler's execution plan and runtime statistics for the specified statement. @@ -111,7 +120,7 @@ To inspect a currently running statement, execute the ``show_node_info`` utility :ref:`sqream sql<sqream_sql_cli_reference>`, the :ref:`SQream Studio Editor<studio_editor>`, or any other :ref:`third party SQL terminal<third_party_tools>`. In this example, we inspect a statement with statement ID of 176. The command looks like this: -.. code-block:: psql +.. code-block:: sql t=> SELECT SHOW_NODE_INFO(176); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum @@ -129,7 +138,8 @@ In this example, we inspect a statement with statement ID of 176. The command lo 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 Understanding the Query Execution Plan Output -================================================== +============================================= + Both :ref:`show_node_info` and the logged execution plans represents the query plan as a graph hierarchy, with data separated into different columns. Each row represents a single logical database operation, which is also called a **node** or **chunk producer**. A node reports several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. @@ -186,13 +196,15 @@ When using :ref:`show_node_info`, a tabular representation of the currently runn See the examples below to understand how the query execution plan is instrumental in identifying bottlenecks and optimizing long-running statements. Information Presented in the Execution Plan ----------------------------------------------------- +------------------------------------------- + .. include:: /reference/sql/sql_statements/monitoring_commands/show_node_info.rst :start-line: 47 :end-line: 78 Commonly Seen Nodes ----------------------- +------------------- + .. list-table:: Node types :widths: auto :header-rows: 1 @@ -297,15 +309,18 @@ Commonly Seen Nodes .. tip:: The full list of nodes appears in the :ref:`Node types table<node_types>`, as part of the :ref:`show_node_info` reference. Examples -================== +======== + In general, looking at the top three longest running nodes (as is detailed in the ``timeSum`` column) can indicate the biggest bottlenecks. In the following examples you will learn how to identify and solve some common issues. .. contents:: In this section: :local: + :depths: 1 + +Spooling to Disk +---------------- -1. Spooling to Disk ------------------------ When there is not enough RAM to process a statement, SQream DB will spill over data to the ``temp`` folder in the storage disk. While this ensures that a statement can always finish processing, it can slow down the processing significantly. It's worth identifying these statements, to figure out if the cluster is configured correctly, as well as potentially reduce @@ -315,13 +330,14 @@ A node that spools will have a value, shown in megabytes in the ``write`` column Common nodes that write spools include ``Join`` or ``LoopJoin``. Identifying the Offending Nodes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. Run a query. For example, a query from the TPC-H benchmark: - .. code-block:: postgres + .. code-block:: sql SELECT o_year, SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share @@ -347,7 +363,8 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``LoopJoin``: - .. code-block:: psql + .. code-block:: sql + :emphasize-lines: 33,35,37,39 t=> SELECT message FROM logs WHERE message_type_id = 200 LIMIT 1; @@ -396,7 +413,8 @@ Identifying the Offending Nodes The total spool used by this query is around 20GB (1915MB + 2191MB + 3064MB + 12860MB). Common Solutions for Reducing Spool -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Increase the amount of spool memory available for the workers, as a proportion of the maximum statement memory. When the amount of spool memory is increased, SQream DB may not need to write to disk. @@ -405,19 +423,22 @@ Common Solutions for Reducing Spool * Reduce the amount of **workers** per host, and increase the amount of spool available to the (now reduced amount of) active workers. This may reduce the amount of concurrent statements, but will improve performance for heavy statements. -2. Queries with Large Result Sets ------------------------------------- + +Queries with Large Result Sets +------------------------------ + When queries have large result sets, you may see a node called ``DeferredGather``. This gathering occurs when the result set is assembled, in preparation for sending it to the client. Identifying the Offending Nodes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #. Run a query. For example, a modified query from the TPC-H benchmark: - .. code-block:: postgres + .. code-block:: sql SELECT s.*, l.*, @@ -446,7 +467,8 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``DeferredGather``: - .. code-block:: psql + .. code-block:: sql + :emphasize-lines: 7,9,11 t=> SELECT show_node_info(494); @@ -469,7 +491,7 @@ Identifying the Offending Nodes #. Modify the statement to see the difference Altering the select clause to be more restrictive will reduce the deferred gather time back to a few milliseconds. - .. code-block:: postgres + .. code-block:: sql SELECT DATEPART(year, o_orderdate) AS o_year, l_extendedprice * (1 - l_discount / 100.0) as volume, @@ -477,19 +499,22 @@ Identifying the Offending Nodes FROM ... Common Solutions for Reducing Gather Time -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Reduce the effect of the preparation time. Avoid selecting unnecessary columns (``SELECT * FROM...``), or reduce the result set size by using more filters. .. `` -3. Inefficient Filtering --------------------------------- +Inefficient Filtering +--------------------- + When running statements, SQream DB tries to avoid reading data that is not needed for the statement by :ref:`skipping chunks<chunks_and_extents>`. If statements do not include efficient filtering, SQream DB will read a lot of data off disk. In some cases, you need the data and there's nothing to do about it. However, if most of it gets pruned further down the line, it may be efficient to skip reading the data altogether by using the :ref:`metadata<metadata_system>`. Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + We consider the filtering to be inefficient when the ``Filter`` node shows that the number of rows processed is less than a third of the rows passed into it by the ``ReadTable`` node. For example: @@ -499,7 +524,7 @@ For example: In this example, we execute a modified query from the TPC-H benchmark. Our ``lineitem`` table contains 600,037,902 rows. - .. code-block:: postgres + .. code-block:: sql SELECT o_year, SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share @@ -526,7 +551,8 @@ For example: The execution below has been shortened, but note the highlighted rows for ``ReadTable`` and ``Filter``: - .. code-block:: psql + .. code-block:: sql + :linenos: :emphasize-lines: 9,17,19,27 @@ -571,7 +597,8 @@ For example: #. Modify the statement to see the difference Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQream DB skip reading the data. - .. code-block:: postgres + .. code-block:: sql + :emphasize-lines: 15 SELECT o_year, @@ -594,7 +621,8 @@ For example: GROUP BY o_year ORDER BY o_year; - .. code-block:: psql + .. code-block:: sql + :linenos: :emphasize-lines: 5,13 @@ -619,20 +647,24 @@ For example: The metadata skipping has performed very well, and has pre-filtered the data for us by pruning unnecessary chunks. Common Solutions for Improving Filtering -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * Use :ref:`clustering keys and naturally ordered data<data_clustering>` in your filters. * Avoid full table scans when possible -4. Joins with ``text`` Keys ------------------------------------ +Joins with ``text`` Keys +------------------------ + Joins on long text keys do not perform as well as numeric data types or very short text keys. Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. For example, consider these two table structures: -.. code-block:: postgres +.. code-block:: sql + CREATE TABLE t_a ( amt FLOAT NOT NULL, @@ -653,7 +685,7 @@ For example, consider these two table structures: In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``TEXT(50)``. - .. code-block:: postgres + .. code-block:: sql SELECT AVG(t_b.j :: BIGINT), t_a.country_code @@ -668,7 +700,8 @@ For example, consider these two table structures: The ``Join`` node is by far the most time-consuming part of this statement - clocking in at 69.7 seconds joining 1.5 billion records. - .. code-block:: psql + .. code-block:: sql + :linenos: :emphasize-lines: 8 @@ -689,7 +722,8 @@ For example, consider these two table structures: 5 | 42 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 41 | 14MB | | public.t_a | 0 Improving Query Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. * Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text @@ -697,7 +731,7 @@ Improving Query Performance For example: - .. code-block:: postgres + .. code-block:: sql SELECT AVG(t_b.j :: BIGINT), t_a.country_code @@ -707,7 +741,8 @@ Improving Query Performance The execution below has been shortened, but note the highlighted rows for ``Join``. The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. - .. code-block:: psql + .. code-block:: sql + :linenos: :emphasize-lines: 8 @@ -728,13 +763,15 @@ Improving Query Performance * You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. -5. Sorting on big ``TEXT`` fields ---------------------------------------- +Sorting on big ``TEXT`` fields +------------------------------ + In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. When running a ``GROUP BY`` on large ``TEXT`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + When running a statement, inspect it with :ref:`show_node_info`. If you see ``Sort`` and ``Reduce`` among your top five longest running nodes, there is a potential issue. For example: @@ -744,7 +781,8 @@ For example: Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: - .. code-block:: postgres + .. code-block:: sql + :emphasize-lines: 5 CREATE TABLE t_inefficient ( @@ -775,7 +813,8 @@ For example: [...] - .. code-block:: psql + .. code-block:: sql + :emphasize-lines: 8,9 t=> select show_node_info(30); @@ -796,7 +835,7 @@ For example: #. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key - .. code-block:: psql + .. code-block:: sql t=> SELECT MAX(LEN(country_code)) FROM t_inefficient; max @@ -806,7 +845,8 @@ For example: #. We can recreate the table with a more restrictive ``TEXT(3)``, and can examine the difference in performance: - .. code-block:: psql + .. code-block:: sql + t=> CREATE TABLE t_efficient . AS SELECT i, . amt, @@ -833,7 +873,8 @@ For example: This time, the entire query took just 4.75 seconds, or just about 91% faster. Improving Sort Performance on Text Keys -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + When using TEXT, ensure that the maximum length defined in the table structure is as small as necessary. For example, if you're storing phone numbers, don't define the field as ``TEXT(255)``, as that affects sort performance. @@ -841,8 +882,9 @@ You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))` .. _high_selectivity_data_opt: -6. High Selectivity Data --------------------------- +High Selectivity Data +--------------------- + Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` SQream DB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk @@ -852,11 +894,12 @@ the results into fewer, fuller chunks. well-clustered data, which is the more common scenario. Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + This is easily identifiable - when the amount of average of rows in a chunk is small, following a ``Filter`` operation. Consider this execution plan: -.. code-block:: psql +.. code-block:: sql t=> select show_node_info(30); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum @@ -870,25 +913,28 @@ The filter node reduced the output to just 18,160 relevant rows, but they're dis All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. Improving Performance with High Selectivity Hints -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Use when there's a ``WHERE`` condition on an :ref:`unclustered column<data_clustering>`, and when you expect the filter to cut out more than 60% of the result set. * Use when the data is uniformly distributed or random -7. Performance of unsorted data in joins ------------------------------------------- +Performance of unsorted data in joins +------------------------------------- + When data is not well-clustered or naturally ordered, a join operation can take a long time. Identifying the Situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + When running a statement, inspect it with :ref:`show_node_info`. If you see ``Join`` and ``DeferredGather`` among your top five longest running nodes, there is a potential issue. In this case, we're also interested in the number of chunks produced by these nodes. Consider this execution plan: -.. code-block:: psql +.. code-block:: sql + :emphasize-lines: 6,11 t=> select show_node_info(30); @@ -914,13 +960,15 @@ The filter node reduced the output to just 18,160 relevant rows, but they're dis All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. Improving Join Performance when Data is Sparse -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + You can tell SQream DB to reduce the amount of chunks involved, if you know that the filter is going to be quite agressive by using the :ref:`HIGH_SELECTIVITY<high_selectivity>` hint described :ref:`above<high_selectivity_data_opt>`. This forces the compiler to rechunk the data into fewer chunks. To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: -.. code-block:: postgres +.. code-block:: sql + :emphasize-lines: 13 -- Without the hint @@ -939,16 +987,19 @@ To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HI AND EnterpriseID=1150 AND MSISDN='9724871140341'; -8. Manual Join Reordering --------------------------------- +Manual Join Reordering +---------------------- + When joining multiple tables, you may wish to change the join order to join the smallest tables first. Identifying the situation -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^ + When joining more than two tables, the ``Join`` nodes will be the most time-consuming nodes. Changing the Join Order -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^ + Always prefer to join the smallest tables first. .. note:: We consider small tables to be tables that only retain a small amount of rows after conditions @@ -956,7 +1007,8 @@ Always prefer to join the smallest tables first. Changing the join order can reduce the query runtime significantly. In the examples below, we reduce the time from 27.3 seconds to just 6.4 seconds. -.. code-block:: postgres +.. code-block:: sql + :caption: Original query -- This variant runs in 27.3 seconds @@ -975,7 +1027,8 @@ from 27.3 seconds to just 6.4 seconds. AND l_shipdate <= dateadd(DAY,122,'1994-01-01') GROUP BY c_nationkey -.. code-block:: postgres +.. code-block:: sql + :caption: Modified query with improved join order -- This variant runs in 6.4 seconds @@ -995,5 +1048,6 @@ from 27.3 seconds to just 6.4 seconds. GROUP BY c_nationkey Further Reading -================== +=============== + See our :ref:`sql_best_practices` guide for more information about query optimization and data loading considerations. \ No newline at end of file diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index fbeee701d..3e61d9e87 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -1,8 +1,8 @@ .. _revoke: -***************** +****** REVOKE -***************** +****** The ``REVOKE`` statement removes permissions from a role. It allows for removing permissions to specific objects. @@ -11,12 +11,12 @@ Learn more about the permission system in the :ref:`access control guide<access_ See also :ref:`grant`, :ref:`drop_role`. Permissions -============= +=========== To revoke permissions, the current role must have the ``SUPERUSER`` permission, or have the ``ADMIN OPTION``. Syntax -========== +====== .. code-block:: postgres @@ -99,7 +99,7 @@ Syntax schema_name ::= identifier Parameters -============ +========== .. list-table:: :widths: auto @@ -125,10 +125,10 @@ Parameters Examples -=========== +======== Prevent a role from modifying table contents ----------------------------------------------- +-------------------------------------------- If you don't trust user ``shifty``, reokve DDL and INSERT permissions. @@ -138,7 +138,7 @@ If you don't trust user ``shifty``, reokve DDL and INSERT permissions. REVOKE DDL ON TABLE important_table FROM shifty; Demoting a user from superuser -------------------------------------- +------------------------------ .. code-block:: postgres @@ -146,7 +146,7 @@ Demoting a user from superuser REVOKE SUPERUSER FROM new_role; Revoking admin option ------------------------------- +--------------------- If ``WITH ADMIN OPTION`` is specified, the role that has the admin option can in turn grant membership in the role to others, and revoke membership in the role as well. diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst index 64b06e1d1..ce573329a 100644 --- a/releases/2021.1_index.rst +++ b/releases/2021.1_index.rst @@ -1,8 +1,9 @@ .. _2021.1_index: -************************** +******************** Release Notes 2021.1 -************************** +******************** + The 2021.1 Release Notes describe the following releases: .. contents:: @@ -14,5 +15,4 @@ The 2021.1 Release Notes describe the following releases: :glob: 2021.1.2 - 2021.1.1 2021.1 \ No newline at end of file diff --git a/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst index b24736945..ad0667975 100644 --- a/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst +++ b/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst @@ -2,9 +2,10 @@ .. _back_to_dashboard_: -**************************** +************************************************** Monitoring Workers and Services from the Dashboard -**************************** +************************************************** + The **Dashboard** is used for the following: * Monitoring system health. @@ -46,7 +47,8 @@ The following is a brief description of the Dashboard panels: .. _services_panel_: Subscribing to Workers from the Services Panel --------------------------- +---------------------------------------------- + Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined :ref:`service queues<workload_manager>`. @@ -71,7 +73,8 @@ The following is a brief description of each pane: - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). Adding A Service -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^ + You can add a service by clicking **+ Add** and defining the service name. .. note:: If you do not associate a worker with the new service, it will not be created. @@ -86,7 +89,8 @@ You can manage workers from the **Workers** panel. For more information about ma .. _workers_panel_: Managing Workers from the Workers Panel ------------- +--------------------------------------- + From the **Workers** panel you can do the following: * :ref:`View workers <view_workers_>` @@ -97,7 +101,8 @@ From the **Workers** panel you can do the following: .. _view_workers_: Viewing Workers -^^^^^^^^ +^^^^^^^^^^^^^^^ + The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. From the **Scale** dropdown menu you can set the time scale of the displayed information @@ -112,7 +117,8 @@ You can hover over segments in the status bar to see the date and time correspon .. _add_worker_to_service_: Adding A Worker to A Service -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + You can add a worker to a service by clicking the **add** button. @@ -123,14 +129,15 @@ Clicking the **add** button shows the selected service's workers. You can add th .. _view_worker_query_information_: Viewing A Worker's Active Query Information -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan <view_worker_execution_plan_>` below. Viewing A Worker's Host Utilization -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. @@ -144,7 +151,7 @@ Error notifications related to statements are displayed, and you can hover over .. _view_worker_execution_plan_: Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Clicking the ellipsis in a service shows the following additional options: @@ -158,7 +165,7 @@ For more information on the current query plan, see :ref:`SHOW_NODE_INFO<show_no :end-line: 84 Managing Worker Status -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^ In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. @@ -253,7 +260,8 @@ Starting or restarting workers terminates all queries related to that worker. Wh .. _license_information_: License Information ----------------------- +------------------- + The license information section shows the following: * The amount of time in days remaining on the license. From e8ab553c55c1100d43ec461cfb817f94dd4d3b64 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 13:35:28 +0300 Subject: [PATCH 0688/1892] maintenance --- configuration_guides/bin_sizes.rst | 5 +++-- installation_guides/installing_and_launching_sqream.rst | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/bin_sizes.rst b/configuration_guides/bin_sizes.rst index 9cdd8e0e8..8338dcc35 100644 --- a/configuration_guides/bin_sizes.rst +++ b/configuration_guides/bin_sizes.rst @@ -1,8 +1,9 @@ .. _bin_sizes: -************************* +**************** Setting Bin Size -************************* +**************** + The ``binSizes`` flag sets the custom bin size in the cache to enable high granularity over bin control. The following describes the ``binSizes`` flag: diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 478d76df1..ee03a8922 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -12,7 +12,6 @@ The **Installing and Launching SQream** page includes the following installation recommended_pre-installation_configurations installing_sqream_with_binary - running_sqream_in_a_docker_container installing_sqream_with_kubernetes installing_monit launching_sqream_with_monit \ No newline at end of file From ce18fa3760e5f8ac1996a308afb7d6c97a2d9a6b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 13:51:01 +0300 Subject: [PATCH 0689/1892] Update subqueries.rst --- reference/sql/sql_syntax/subqueries.rst | 58 +++++++++++++++++-------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 7f788ff46..739098db6 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -1,26 +1,22 @@ .. _subqueries: -*************************** +********** Subqueries -*************************** +********** -Subqueries allows you to reuse of results from another query. +Subqueries enable the reuse of results of other queries. -SQream DB supports relational (also called *derived table*) subqueries, which appear as :ref:`select` queries as part of a table expression. +SQreamDB supports relational (also called *derived table*) subqueries, which appear as :ref:`select` queries as part of a table expression. -SQream DB also supports :ref:`common_table_expressions`, which are a form of subquery. With CTEs, a subquery can be named for reuse in a query. +SQreamDB also supports :ref:`common_table_expressions`, which are a form of subquery. With CTEs, a subquery can be named for reuse in a query. .. note:: - * SQream DB does not currently support correlated subqueries or scalar subqueries. - * There is no limit to the number of subqueries or nesting limits in a statement - - - + You may include an unlimited number of subqueries within a single SQL statement, and you can also nest subqueries to an unlimited depth Table Subqueries -=========================== +================ The following is an example of table named ``nba`` with the following structure: @@ -48,13 +44,14 @@ To see the table contents, click :download:`Download nba.csv </_static/samples/n :header-rows: 1 Scalar Subqueries -=================== +================= + The following are examples of scalar subqueries. Simple Subquery ------------------- +--------------- -.. code-block:: psql +.. code-block:: sql t=> SELECT AVG("Age") FROM . (SELECT "Name","Team","Age" FROM nba WHERE "Height" > '7-0'); @@ -63,9 +60,9 @@ Simple Subquery 26 Combining a Subquery with a Join ----------------------------------- +-------------------------------- -.. code-block:: psql +.. code-block:: sql t=> SELECT * FROM . (SELECT "Name" FROM nba WHERE "Height" > '7-0') AS t(name) @@ -89,11 +86,11 @@ Combining a Subquery with a Join Walter Tavares | Walter Tavares | Atlanta Hawks | 22 | C | 24 | 7-3 | 260 | \N | 1000000 ``WITH`` subqueries ---------------------- +------------------- See :ref:`common_table_expressions` for more information. -.. code-block:: psql +.. code-block:: sql nba=> WITH . nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), @@ -102,4 +99,27 @@ See :ref:`common_table_expressions` for more information. Name | Team | name0 | team0 ----------------+-----------------+----------------+---------------- Stanley Johnson | Detroit Pistons | Andre Drummond | Detroit Pistons - Aaron Gordon | Orlando Magic | Shabazz Napier | Orlando Magic \ No newline at end of file + Aaron Gordon | Orlando Magic | Shabazz Napier | Orlando Magic + +Correlated subqueries +===================== + +Correlated subqueries are currently not supported. However, you may use the following workaround: + +.. code-block:: sql + + # Unsupported correlated subquery + + SELECT + x,y,z + FROM + t + where x in ( select x from t1 ); + + # Correlated subquery workaround + + SELECT + x,y,z + FROM + t + JOIN (select x from t1) t1 on t.x = t1.x; \ No newline at end of file From 4501e2759eb2b47ce7b57b5d2db527d87444c500 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 14:19:49 +0300 Subject: [PATCH 0690/1892] SEO --- configuration_guides/login_max_retries.rst | 5 ++- glossary.rst | 4 +- .../user_defined_functions/scalar_sql_udf.rst | 2 +- releases/2022.1.1.rst | 42 ++++++++++++------- releases/2022.1.2.rst | 31 +++++++++----- 5 files changed, 52 insertions(+), 32 deletions(-) diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst index bf3ae6d40..90f5e077f 100644 --- a/configuration_guides/login_max_retries.rst +++ b/configuration_guides/login_max_retries.rst @@ -1,8 +1,9 @@ .. _login_max_retries: -************************* +*********************************** Adjusting Permitted Log-in Attempts -************************* +*********************************** + The ``loginMaxRetries`` flag sets the permitted log-in attempts. The following describes the ``loginMaxRetries`` flag: diff --git a/glossary.rst b/glossary.rst index fd3cb246e..f4634d712 100644 --- a/glossary.rst +++ b/glossary.rst @@ -1,7 +1,7 @@ .. glossary: Glossary -===================================== +======== The following table shows the **Glossary** descriptions: @@ -27,7 +27,7 @@ The following table shows the **Glossary** descriptions: +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Node | A machine used to run SQream workers. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Role | A group or a user. For more information see `SQream Studio <https://docs.sqream.com/en/latest/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.html>`_. | +| Role | A group or a user. For more information see :ref:`SQream Studio <creating_assigning_and_managing_roles_and_permissions>`. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Storage cluster | The directory where SQream stores data. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst index 67b23248c..84f48f971 100644 --- a/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst +++ b/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.rst @@ -87,7 +87,7 @@ Usage Notes Since SQL UDF's are one type of supported UDFs, the following Python UDF characteristics apply: -* UDF permission rules - see `Access Control <https://docs.sqream.com/en/latest/guides/features/access_control.html#access-control>`_. +* UDF permission rules - see :ref:`Access Control <access_control>`. * The ``get_function_ddl`` utility function works on these functions - see `Getting the DDL for a Function <https://docs.sqream.com/en/latest/guides/features/python_functions.html#getting-the-ddl-for-a-function>`_. diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 3ba0cb8b6..db64d9b6c 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -1,8 +1,9 @@ .. _2022.1.1: -************************** +********************** Release Notes 2022.1.1 -************************** +********************** + The 2022.1.1 release notes were released on 7/19/2022 and describe the following: .. contents:: @@ -10,11 +11,12 @@ The 2022.1.1 release notes were released on 7/19/2022 and describe the following :depth: 1 Version Content ----------- +--------------- + The 2022.1.1 Release Notes describes the following: * Enhanced security features -* For more information, see `SQream Acceleration Studio 5.4.7 <https://docs.sqream.com/en/v2022.1.1/sqream_studio_5.4.7/index.html>`_. +* For more information, see :ref:`SQream Acceleration Studio 5.4.7 <sqream_studio_>`. Storage Version --------------- @@ -22,7 +24,8 @@ Storage Version The storage version presently in effect is version 40. New Features ----------- +------------ + The 2022.1.1 Release Notes include the following new features: .. contents:: @@ -33,14 +36,16 @@ Password Security Compliance ************ In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. -For more information, see `Password Policy <https://docs.sqream.com/en/v2022.1.1/operational_guides/access_control_password_policy.html>`_. +For more information, see :ref:`Password Policy <access_control_password_policy>`. Known Issues ---------- +------------ + There were no known issues in Version 2022.1.1. Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1.1: +-------------+------------------------------------------------------------------------------------------------+ @@ -54,25 +59,30 @@ The following table lists the issues that were resolved in Version 2022.1.1: +-------------+------------------------------------------------------------------------------------------------+ Operations and Configuration Changes --------- +------------------------------------ + The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. -For more information, see `Adjusting the Permitted Log-In Attempts <https://docs.sqream.com/en/v2022.1.1/configuration_guides/login_max_retries.html>`_. +For more information, see :ref:`Adjusting the Permitted Log-In Attempts <login_max_retries>`. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- -In `SQream Acceleration Studio 5.4.7 <https://docs.sqream.com/en/v2022.1.1/sqream_studio_5.4.7/index.html>`_, the **Configuration** section has been temporarily disabled and will be enabled at a later date. In addition, the **Log Lines** tab in the **Log** section has been removed. +------------------- + +In :ref:`SQream Acceleration Studio 5.4.7 <sqream_studio_>`, the **Configuration** section has been temporarily disabled and will be enabled at a later date. In addition, the **Log Lines** tab in the **Log** section has been removed. End of Support -------- +-------------- + The End of Support section is not relevant to Version 2022.1.1. Upgrading to v2022.1.1 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -105,7 +115,7 @@ Upgrading to v2022.1.1 $ ./upgrade_storage <levelDB path> - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. .. toctree:: :maxdepth: 2 diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index cbefa3f00..d19f8aa60 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -1,8 +1,9 @@ .. _2022.1.2: -************************** +********************** Release Notes 2022.1.2 -************************** +********************** + The 2022.1.2 release notes were released on 8/24/2022 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2022.1.2 release notes were released on 8/24/2022 and describe the following :depth: 1 Version Content ----------- +--------------- + The 2022.1.2 Release Notes describes the following: * Automatic schema identification. @@ -25,7 +27,8 @@ Storage Version The storage version presently in effect is version 41. New Features ----------- +------------ + The 2022.1.2 Release Notes include the following new features: .. contents:: @@ -37,7 +40,8 @@ Parquet Read Optimization Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1.2: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ @@ -49,23 +53,28 @@ The following table lists the issues that were resolved in Version 2022.1.2: +-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes --------- +------------------------------------ + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + No features were deprecated for Version 2022.1.2. End of Support -------- +-------------- + The End of Support section is not relevant to Version 2022.1.2. Upgrading to v2022.1.2 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -98,7 +107,7 @@ Upgrading to v2022.1.2 $ ./upgrade_storage <levelDB path> - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1.2/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. .. toctree:: :maxdepth: 2 From f103cf1834846fd8e39d70fe4a704727b11c1c0c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:10:10 +0300 Subject: [PATCH 0691/1892] Maintenance --- releases/2020.1.rst | 22 +++++++------- releases/2020.2.rst | 22 +++++++------- releases/2020.3.1.rst | 19 +++++++----- releases/2020.3.2.1.rst | 16 ++++++---- releases/2020.3.2.rst | 12 ++++---- releases/2020.3.rst | 20 ++++++++----- releases/2020.3_index.rst | 5 ++-- releases/2021.1.2.rst | 23 ++++++++++----- releases/2021.1.rst | 62 +++++++++++++++++++++++---------------- releases/2021.2.1.24.rst | 29 +++++++++++------- releases/2021.2.1.rst | 33 ++++++++++++++------- releases/2021.2.rst | 46 +++++++++++++++++++---------- releases/2022.1.1.rst | 6 ---- releases/2022.1.2.rst | 6 ---- releases/2022.1.3.rst | 6 ---- releases/2022.1.4.rst | 29 +++++++++++------- releases/2022.1.5.rst | 32 ++++++++++++-------- releases/2022.1.6.rst | 30 +++++++++++-------- releases/2022.1.7.rst | 27 ++++++++++------- releases/2022.1.rst | 49 ++++++++++++++++++------------- 20 files changed, 289 insertions(+), 205 deletions(-) diff --git a/releases/2020.1.rst b/releases/2020.1.rst index 769fa0ebb..ddc5702d4 100644 --- a/releases/2020.1.rst +++ b/releases/2020.1.rst @@ -1,8 +1,8 @@ .. _2020.1: -************************** +******************** Release Notes 2020.1 -************************** +******************** SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. @@ -14,10 +14,10 @@ The core of SQream DB v2020.1 contains new integration features, more analytics New features -================ +============ -Integrations ------------------ +Integration +----------- * Load files directly from :ref:`S3 buckets<inserting_data>`. Customers with columnar data in S3 data lakes can now access the data directly. All that is needed is to simply point an external table to an S3 bucket with Parquet, ORC, or CSV objects. This feature is available on all deployments of SQream DB – in the cloud and on-prem. @@ -36,7 +36,7 @@ Integrations SQL support ---------------- +----------- * Added frames and frame exclusions to :ref:`window_functions`. This is available for preview, with more features coming in the next version. @@ -54,7 +54,7 @@ SQL support Improvements and fixes -======================== +====================== SQream DB v2020.1 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. Existing SQream DB users can expect to see a general speedup of around 10% on most statements and queries! @@ -95,7 +95,7 @@ SQream DB v2020.1 includes hundreds of small new features and tunable parameters * Additional CSV date formats (date parsers) added for compatibility Behaviour changes -======================== +================= * ``ClientCmd`` is now known as :ref:`sqream sql<sqream_sql_cli_reference>` @@ -128,7 +128,7 @@ Behaviour changes - ``useMemFactorInJoinOutput`` Operations -======================== +========== * The client-server protocol has been updated to support faster data flow, and more reliable memory allocations on the client side. End users are required to use only the latest :ref:`sqream sql<sqream_sql_cli_reference>`, :ref:`java_jdbc`, and :ref:`odbc` drivers delivered with this version. See the :ref:`client driver download page<client_drivers>` for the latest drivers and connectors. @@ -163,7 +163,7 @@ Operations Known Issues & Limitations -================================ +========================== * An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. @@ -181,7 +181,7 @@ Known Issues & Limitations Upgrading to v2020.1 -======================== +==================== Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.2.rst b/releases/2020.2.rst index 5a66e99bd..c512ecb32 100644 --- a/releases/2020.2.rst +++ b/releases/2020.2.rst @@ -1,8 +1,8 @@ .. _2020.2: -************************** +******************** Release Notes 2020.2 -************************** +******************** SQream v2020.2 contains some new features, improved performance, and bug fixes. @@ -12,20 +12,20 @@ As always, the latest release improves reliability and performance, and makes ge New Features -================ +============ UI ----------- +-- * New :ref:`sqream_studio` replaces the previous Statement Editor. -Integrations ------------------ +Integration +----------- * Our :ref:`Python driver (pysqream)<pysqream>` now has an SQLAlchemy dialect. Customers can write high-performance Python applications that make full use of SQream - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. SQL Support ---------------- +----------- * Added :ref:`lag`/:ref:`lead` ranking functions to our :ref:`window_functions` support. We will have more features coming in the next version. @@ -48,7 +48,7 @@ SQL Support Improvements and Fixes -======================== +====================== SQream v2020.2 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. @@ -65,7 +65,7 @@ SQream v2020.2 includes hundreds of small new features and tunable parameters th Operations -======================== +========== * When upgrading from a previous version of SQream (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` @@ -98,7 +98,7 @@ Operations Known Issues and Limitations -================================ +============================ * An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. @@ -108,7 +108,7 @@ Known Issues and Limitations Upgrading to Version 2020.2 -======================== +============================ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst index 9fa40cbb0..cbd0ee613 100644 --- a/releases/2020.3.1.rst +++ b/releases/2020.3.1.rst @@ -1,8 +1,9 @@ .. _2020.3.1: -************************** +********************** Release Notes 2020.3.1 -************************** +********************** + The 2020.3.1 release notes were released on October 8, 2020 and describe the following: .. contents:: @@ -12,7 +13,8 @@ The 2020.3.1 release notes were released on October 8, 2020 and describe the fol New Features -------------- +------------ + The following list describes the new features: @@ -39,7 +41,8 @@ The following list describes the new features: Performance Enhancements -------------- +------------------------ + The following list describes the performance enhancements: @@ -49,7 +52,8 @@ The following list describes the performance enhancements: Resolved Issues -------------- +--------------- + The following list describes the resolved issues: @@ -60,12 +64,13 @@ The following list describes the resolved issues: Known Issues and Limitations -------------- +---------------------------- + No known issues and limitations. Upgrading to v2020.3.1 ----------------- +---------------------- Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst index 29f3b3e88..8a62ac0a3 100644 --- a/releases/2020.3.2.1.rst +++ b/releases/2020.3.2.1.rst @@ -1,8 +1,9 @@ .. _2020.3.2.1: -************************** +************************ Release Notes 2020.3.2.1 -************************** +************************ + The 2020.3.2.1 release notes were released on October 8, 2020 and describe the following: .. contents:: @@ -11,20 +12,23 @@ The 2020.3.2.1 release notes were released on October 8, 2020 and describe the f Overview ------------------ +-------- + SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. Performance Enhancements -------------- +------------------------ + * Metadata on Demand optimization resulting in reduced latency and improved overall performance. Known Issues and Limitations -------------- +---------------------------- + * Multiple count distinct operations is enabled for all data types. Upgrading to v2020.3.2.1 -------------- +------------------------ Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.3.2.rst b/releases/2020.3.2.rst index c97e2bd47..d4e15e7fb 100644 --- a/releases/2020.3.2.rst +++ b/releases/2020.3.2.rst @@ -1,18 +1,20 @@ .. _2020.3.2: -************************** +********************** What's new in 2020.3.2 -************************** +********************** SQream DB v2020.3.2 contains major performance improvements and some bug fixes. Performance Enhancements -========================= +======================== + * Metadata on Demand optimization resulting in reduced latency and improved overall performance Known Issues & Limitations -================================ +========================== + * Bug with STDDEV_SAMP,STDDEV_POP and STDEV functions * Window function query returns wrong results * rank() in window function sometimes returns garbage @@ -21,7 +23,7 @@ Known Issues & Limitations * Performance degradation when using "groupby" or outer_join Upgrading to v2020.3.2 -======================== +====================== Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.3.rst b/releases/2020.3.rst index eb8ca8f62..ec3c96e96 100644 --- a/releases/2020.3.rst +++ b/releases/2020.3.rst @@ -1,8 +1,9 @@ .. _2020.3: -************************** +******************** Release Notes 2020.3 -************************** +******************** + The 2020.3 release notes were released on October 8, 2020 and describes the following: .. contents:: @@ -11,12 +12,14 @@ The 2020.3 release notes were released on October 8, 2020 and describes the foll Overview ------------- +-------- + SQream DB v2020.3 contains new features, performance enhancements, and resolved issues. New Features ----------- +------------ + The following list describes the new features: @@ -46,7 +49,8 @@ The following list describes the new features: Performance Enhancements ----------- +------------------------ + The following list describes the performance enhancements: @@ -61,6 +65,7 @@ The following list describes the performance enhancements: Resolved Issues --------------- + The following list describes the resolved issues: @@ -84,7 +89,8 @@ The following list describes the resolved issues: * ``TEXT`` columns cannot be used with an outer join together with an inequality check (!= , <>). This was fixed. Known Issues And Limitations ----------- +---------------------------- + The following list describes the known issues and limitations: @@ -98,7 +104,7 @@ The following list describes the known issues and limitations: Upgrading to v2020.3 ----------- +-------------------- Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst index a662cb48a..e2066e8a6 100644 --- a/releases/2020.3_index.rst +++ b/releases/2020.3_index.rst @@ -1,8 +1,9 @@ .. _2020.3_index: -************************** +******************** Release Notes 2020.3 -************************** +******************** + The 2020.3 release notes describe the following releases: .. contents:: diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst index ee33cfbd8..a8c279981 100644 --- a/releases/2021.1.2.rst +++ b/releases/2021.1.2.rst @@ -1,8 +1,9 @@ .. _2021.1.2: -************************** +********************** Release Notes 2021.1.2 -************************** +********************** + The 2021.1.2 release notes were released on 8/9/2021 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2021.1.2 release notes were released on 8/9/2021 and describe the following: :depth: 1 New Features -------------- +------------ + The 2021.1.2 Release Notes include the following new features: .. contents:: @@ -18,7 +20,8 @@ The 2021.1.2 Release Notes include the following new features: :depth: 1 Aliases Added to SUBSTRING Function and Length Argument -************ +******************************************************* + The following aliases have been added: * length - ``len`` @@ -37,23 +40,27 @@ The following data type aliases have been added: * NATIONAL CHARACTER VARYING/NATIONAL CHAR VARYING/NCHAR VARYING - ``text`` String Literals Containing ASCII Characters Interepreted as TEXT -************ +**************************************************************** + SQream now interprets all string literals, including those containing ASCII characters, as ``text``. For more information, see `String Types <https://docs.sqream.com/en/v2021.1.2/data_type_guides/sql_data_types_string.html>`_. Decimal Literals Interpreted as Numeric Columns -************ +*********************************************** + SQream now interprets literals containing decimal points as ``numeric`` instead of as ``double``. For more information, see `Data Types <https://docs.sqream.com/en/v2021.1.2/data_type_guides/index.html>`_. Roles Area Added to Studio Version 5.4.3 -**************** +**************************************** + The **Roles** area has been added to `Studio version 5.4.3 <https://docs.sqream.com/en/v2021.1.2/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.html>`_. From the Roles area users can create and assign roles and manage user permissions. Resolved Issues -------------- +--------------- + The following list describes the resolved issues: * In Parquet files, ``float`` columns could not be mapped to SQream ``double`` columns. This was fixed. diff --git a/releases/2021.1.rst b/releases/2021.1.rst index 02d5377d5..ebf839f21 100644 --- a/releases/2021.1.rst +++ b/releases/2021.1.rst @@ -1,8 +1,9 @@ .. _2021.1: -************************** +******************** Release Notes 2021.1 -************************** +******************** + The 2021.1 release notes were released on 6/13/2021 and describe the following: .. contents:: @@ -11,7 +12,8 @@ The 2021.1 release notes were released on 6/13/2021 and describe the following: Version Content ----------- +--------------- + The 2021.1 Release Notes describes the following: * Major feature release targeted for all on-premises customers. @@ -19,7 +21,8 @@ The 2021.1 Release Notes describes the following: New Features ----------- +------------ + The 2021.1 Release Notes include the following new features: @@ -29,11 +32,13 @@ The 2021.1 Release Notes include the following new features: :depth: 1 SQream DB on Cloud -************ +****************** + SQream DB can now be run on AWS, GCP, and Azure. Numeric Data Types -************ +****************** + SQream now supports Numeric Data types for the following operations: * All join types. @@ -43,7 +48,8 @@ SQream now supports Numeric Data types for the following operations: For more information, see `Numeric Data Types <https://docs.sqream.com/en/v2021.1/reference/sql_data_types.html#numeric-data-types.html>`_. Text Data Type -************ +************** + SQream now supports TEXT data types in all operations, which is default string data type for new projects. @@ -58,18 +64,20 @@ For more information, see `String Types <https://docs.sqream.com/en/v2021.1/data Supports Scalar Subqueries -************ +************************** + SQream now supports running initial scalar subqueries. For more information, see `Subqueries <https://docs.sqream.com/en/v2021.1/reference/sql/sql_syntax/subqueries.html>`_. Literal Arguments -************ +***************** SQream now supports literal arguments for functions in all cases where column/scalar arguments are supported. Simple Scalar SQL UDFs -************ +********************** + SQream now supports simple scalar SQL UDF's. For more information, see `Simple Scalar SQL UDF’s <https://docs.sqream.com/en/v2021.1/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.html>`_. @@ -97,7 +105,8 @@ For more information, see `GET_LICENSE_INFO <https://docs.sqream.com/en/v2021.1/ Optimized Foreign Data Wrapper Export -************ +************************************* + Sqream now supports exporting to multiple files concurrently. This is useful when you need to reduce file size to more easily export multiple files. The following is the correct syntax for exporting multiple files concurrently: @@ -121,7 +130,8 @@ The following apply: * When the ``enforce_single_file`` value is set to ``TRUE``, only one file is created, and its size is not limited by the ``max_file_size`` value. Its default value is ``TRUE``. Main Features --------- +------------- + The following list describes the main features: * SQreamDB available on AWS. @@ -141,7 +151,8 @@ The following list describes the main features: Resolved Issues ---------- +--------------- + The following list describes the resolved issues: * Copying text from a CSV file to the TEXT column without closing quotes caused SQream to crash. This was fixed. @@ -160,16 +171,11 @@ The following list describes the resolved issues: - - - - - - Operations and Configuration Changes --------- +------------------------------------ + Recommended SQream Configuration on Cloud -************ +***************************************** For more information about AWS, see `Amazon S3 <https://docs.sqream.com/en/v2021.1/operational_guides/s3.html>`_. @@ -177,7 +183,7 @@ For more information about AWS, see `Amazon S3 <https://docs.sqream.com/en/v2021 Optimized Foreign Data Wrapper Export Configuration Flag -************ +******************************************************** SQream now has a new ``runtimeGlobalFlags`` flag called ``WriteToFileThreads``. @@ -189,15 +195,18 @@ For more information about the ``runtimeGlobalFlags`` flag, see the **Runtime Gl Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + No features were depecrated. Known Issues and Limitations --------- +---------------------------- + The the list below describes the following known issues and limitations: * In cases when selecting top 1 from foreign table using the Parquet format with an hdfs path, SQream experienced an error. @@ -209,6 +218,7 @@ The the list below describes the following known issues and limitations: * Deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. Upgrading to v2021.1 -------- +-------------------- + Due to the known issue of a limitation on the amount of access requests that can be simultaneously sent to AWS, deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index 2016dd564..b43594976 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -1,8 +1,9 @@ .. _2021.2.1.24: -************************** +************************* Release Notes 2021.2.1.24 -************************** +************************* + The 2021.2.1.24 release notes were released on 7/28/2022 and describe the following: .. contents:: @@ -10,11 +11,13 @@ The 2021.2.1.24 release notes were released on 7/28/2022 and describe the follow :depth: 1 Version Content ----------- +--------------- + The 2021.2.1.24 Release Notes includes a query maintenance feature. New Features ----------- +------------ + The 2021.2.1.24 Release Notes include the following new features: .. contents:: @@ -28,7 +31,8 @@ The new **Query Healer** feature periodically examines the progress of running s For more information, see `Query Healer <https://docs.sqream.com/en/v2021.2.1.24/feature_guides/query_healer.html>`_. Resolved Issues ---------- +--------------- + The following table lists the resolved issues for Version 2021.2.1.24: +-------------+------------------------------------------------------------------------------------------------------------------------------------+ @@ -44,7 +48,8 @@ The following table lists the resolved issues for Version 2021.2.1.24: +-------------+------------------------------------------------------------------------------------------------------------------------------------+ Known Issues ---------- +------------ + The following table lists the known issues for Version 2021.2.1.24: +-------------+------------------------------------------------------------------------------------------------------------------------------------+ @@ -58,7 +63,8 @@ The following table lists the known issues for Version 2021.2.1.24: +-------------+------------------------------------------------------------------------------------------------------------------------------------+ Operations and Configuration Changes --------- +------------------------------------ + The following worker level configuration flags were added: * :ref:`is_healer_on` @@ -72,14 +78,17 @@ The following worker level configuration flags were added: * :ref:`healer_detection_frequency_seconds` Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + Version 2021.2.1.24 includes no deprecated features. End of Support -------- +-------------- + The End of Support section is not relevant to Version 2021.2.1.24. diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst index d50f1084e..1f427df49 100644 --- a/releases/2021.2.1.rst +++ b/releases/2021.2.1.rst @@ -1,8 +1,9 @@ .. _2021.2.1: -************************** +********************** Release Notes 2021.2.1 -************************** +********************** + The 2021.2.1 release notes were released on 15/12/2021 and describes the following: .. contents:: @@ -10,7 +11,8 @@ The 2021.2.1 release notes were released on 15/12/2021 and describes the followi :depth: 1 New Features -------------- +------------ + The 2021.2.1 Release Notes include the following new features: .. contents:: @@ -19,6 +21,7 @@ The 2021.2.1 Release Notes include the following new features: CREATE TABLE ************ + SQream now supports duplicating the column structure of an existing table using the ``LIKE`` clause. For more information, see `Duplicating the Column Structure of an Existing Table <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_statements/ddl_commands/create_table.html#duplicating-the-column-structure-of-an-existing-table>`_. @@ -32,13 +35,15 @@ SQream now supports the following aggregation functions: * `MODE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/aggregate_functions/mode.html>`_ REGEX REPLACE -************ +************* + SQream now supports the ``REGEXP_REPLACE`` function for finding and replacing text column substrings. For more information, see `REGEX_REPLACE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/scalar_functions/string/regexp_replace.html>`_. Delete Optimization -************ +******************* + The ``DELETE`` statement can now delete values that contain multi-table conditions. For more information, see `Deleting Values that Contain Multi-Table Conditions <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_statements/dml_commands/delete.html#deleting-values-that-contain-multi-table-conditions>`_. @@ -46,11 +51,13 @@ For more information, see `Deleting Values that Contain Multi-Table Conditions < For more information, see `REGEX_REPLACE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/scalar_functions/string/regexp_replace.html>`_. Performance Enhancements ------- +------------------------ + The **Performance Enhancements** section is not relevant to Version 2021.2.1. Resolved Issues -------------- +--------------- + The following table lists the issues that were resolved in Version 2021.2.1: .. list-table:: @@ -63,18 +70,22 @@ The following table lists the issues that were resolved in Version 2021.2.1: - A method has been provided for including the ``GROUP BY`` and ``DISTINCT COUNT`` statements. Known Issues ------- +------------ + The **Known Issues** section is not relevant to 2021.2.1. Naming Convention Modifications ------- +------------------------------- + The **Naming Convention Modifications** section is not relevant to Version 2021.2.1. End of Support ------- +-------------- + The **End of Support** section is not relevant to Version 2021.2.1. Deprecated Features ------- +------------------- + The **Deprecated Components** section is not relevant to Version 2021.2.1. diff --git a/releases/2021.2.rst b/releases/2021.2.rst index f95de16a5..790c33956 100644 --- a/releases/2021.2.rst +++ b/releases/2021.2.rst @@ -1,8 +1,9 @@ .. _2021.2: -************************** +******************** Release Notes 2021.2 -************************** +******************** + The 2021.2 release notes were released on 13/9/2021. .. contents:: @@ -10,7 +11,8 @@ The 2021.2 release notes were released on 13/9/2021. :depth: 1 New Features ----------- +------------ + The 2021.2 Release Notes include the following new features: .. contents:: @@ -18,7 +20,8 @@ The 2021.2 Release Notes include the following new features: :depth: 1 New Driver Compatibility -************ +************************ + The 2021.2 release supports the following drivers: * **JDBC** - new driver version (JDBC 4.5) with important bug fixes. @@ -28,22 +31,25 @@ The 2021.2 release supports the following drivers: * **Pysqream** - pysqream 3.1.2 Centralized Configuration System -************ +******************************** + SQream now uses a new configuration system based on centralized configuration accessible from SQream Studio. For more information, see the following: -* `Configuration <https://docs.sqream.com/en/v2021.2/guides/operations/configuration.html>`_ - describes how to configure your instance of SQream from a centralized location. +* `Configuration <https://docs.sqream.com/en/v2021.2/guides/operations/configuration.html>` - describes how to configure your instance of SQream from a centralized location. * `SQream Studio 5.4.3 <https://docs.sqream.com/en/v2021.2/sqream_studio_5.4.3/index.html>`_ - configure your instance of SQream from Studio. Qualifying Schemas Without Providing an Alias -************ +********************************************* + When running queries, SQream now supports qualifying schemas without providing an alias. For more information, see `SQream Studio 5.4.3 <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/ddl_commands/create_schema.html>`_. Double-Quotations Supported When Importing and Exporting CSVs -************ +************************************************************* + When importing and exporting CSVs, SQream now supports using quotation characters other than double quotation marks (``"``). For more information, see the following: @@ -94,11 +100,13 @@ For more information, see the following statements: * `CREATE_FOREIGN_TABLE <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/ddl_commands/create_foreign_table.html>`_ Performance Enhancements ------- +------------------------ + In Version 2021.2, an advanced smart spooling mechanism splits spool memory based on required CP usage. Resolved Issues ------- +--------------- + The following table lists the issues that were resolved in Version 2021.2: .. list-table:: @@ -116,12 +124,14 @@ The following table lists the issues that were resolved in Version 2021.2: Known Issues ------- +------------ + The **Known Issues** section is not relevant to Version 2021.2. Naming Convention Modifications ------- +------------------------------- + The **Naming Convention Modifications** describes SQream features, such as data types or statements, that have been renamed. NVARCHAR Data Type Renamed TEXT @@ -132,15 +142,18 @@ The ``NVARCHAR`` data type has been renamed ``TEXT``. For more information on the ``TEXT`` data type, see `String (TEXT) <https://docs.sqream.com/en/v2021.2/data_type_guides/sql_data_types_string.html>`_ End of Support ------- +-------------- + The **End of Support** section is not relevant to Version 2021.2. Deprecated Features ------- +------------------- + The **Deprecated Components** section is not relevant to Version 2021.2. Upgrading Your SQream Version ------- +----------------------------- + The **Upgrading Your SQream Version** section describes the following: .. contents:: @@ -148,7 +161,8 @@ The **Upgrading Your SQream Version** section describes the following: :depth: 1 Upgrading Your Storage Version -************ +****************************** + When upgrading from a SQream version earlier than 2021.2 you must upgrade your storage version, as shown in the following example: .. code-block:: console diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index db64d9b6c..662b38ed7 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -117,9 +117,3 @@ Upgrading to v2022.1.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.1 \ No newline at end of file diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index d19f8aa60..529d35248 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -109,9 +109,3 @@ Upgrading to v2022.1.2 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.2 \ No newline at end of file diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index fa00e8fd0..d1de10668 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -135,9 +135,3 @@ Upgrading to v2022.1.3 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1.3 \ No newline at end of file diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 30a81b231..9b0ce45fe 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -1,8 +1,9 @@ .. _2022.1.4: -************************** +********************** Release Notes 2022.1.4 -************************** +********************** + The 2022.1.4 release notes were released on 10/11/2022 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2022.1.4 release notes were released on 10/11/2022 and describe the followin :depth: 1 Version Content ----------- +--------------- + The 2022.1.4 Release Notes describes the following: * Security enhancement - Disable Python UDFs by default. @@ -24,12 +26,14 @@ Storage Version The storage version presently in effect is version 42. Known Issues ---------- +------------ + No relevant Known Issues. Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1.4: +---------------------+------------------------------------------------------------------------------------------------------------------+ @@ -50,15 +54,18 @@ The following table lists the issues that were resolved in Version 2022.1.4: Operations and Configuration Changes --------- +------------------------------------ + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -67,11 +74,13 @@ TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type sup End of Support -------- +-------------- + No End of Support changes were made. Upgrading to v2022.1.4 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 2c3149039..376a69b67 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -1,8 +1,9 @@ .. _2022.1.5: -************************** +********************** Release Notes 2022.1.5 -************************** +********************** + The 2022.1.5 release notes were released on 11/02/2022 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2022.1.5 release notes were released on 11/02/2022 and describe the followin :depth: 1 New Features ----------- +------------ + The 2022.1.5 Release Notes include the following new features: * keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. @@ -30,12 +32,14 @@ The storage version presently in effect is version 42. Known Issues ---------- +------------ + Recently discovered issue with the encryption feature, at this time SQream recommends to avoid using this feature - a fix will be introduced in the near future. Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1.5: +--------------+------------------------------------------------------------------------------------------+ @@ -57,19 +61,19 @@ The following table lists the issues that were resolved in Version 2022.1.5: +--------------+------------------------------------------------------------------------------------------+ - - - Operations and Configuration Changes --------- +------------------------------------ + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -78,11 +82,13 @@ TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type sup End of Support -------- +-------------- + No End of Support changes were made. Upgrading to v2022.1.5 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index efd0a4ab2..0f9c13336 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -1,8 +1,9 @@ .. _2022.1.6: -************************** +********************** Release Notes 2022.1.6 -************************** +********************** + The 2022.1.6 release notes were released on 12/11/2022 and describe the following: .. contents:: @@ -10,7 +11,7 @@ The 2022.1.6 release notes were released on 12/11/2022 and describe the followin :depth: 1 New Features ----------- +------------ * :ref:`.Net Driver<net>` now supports .NET version 6 or newer. @@ -22,11 +23,12 @@ Storage Version The storage version presently in effect is version 42. Known Issues ---------- +------------ + :ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 2022.1.6 resolved Issues ---------- +-------------------------------- +--------------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -48,21 +50,21 @@ Version 2022.1.6 resolved Issues | SQ-12204 | Possible issue when trying to INSERT Unicode data using .Net client | +--------------------------------+------------------------------------------------------------------------------------------+ - - - Configuration Changes --------- +--------------------- + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -71,11 +73,13 @@ TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR End of Support -------- +-------------- + No End of Support changes were made. Upgrading to v2022.1.6 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index c5f738eba..cd24a1e62 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -1,8 +1,9 @@ .. _2022.1.7: -************************** +********************** Release Notes 2022.1.7 -************************** +********************** + The 2022.1.7 release notes were released on 12/15/2022 and describe the following: .. contents:: @@ -10,7 +11,7 @@ The 2022.1.7 release notes were released on 12/15/2022 and describe the followin :depth: 1 New Features ----------- +------------ * Ingesting data from :ref:`JSON<json>` files. @@ -26,11 +27,12 @@ Storage Version The storage version presently in effect is version 43. Known Issues ---------- +------------ + :ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 2022.1.7 resolved Issues ---------- +-------------------------------- +------------------+-----------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -43,15 +45,18 @@ Version 2022.1.7 resolved Issues +------------------+-----------------------------------------------------------------------+ Configuration Changes --------- +--------------------- + No configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -60,11 +65,13 @@ TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR End of Support -------- +-------------- + No End of Support changes were made. Upgrading to v2022.1.7 -------- +---------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console diff --git a/releases/2022.1.rst b/releases/2022.1.rst index be50ab11b..77386a5ae 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -1,8 +1,9 @@ .. _2022.1: -************************** +******************** Release Notes 2022.1 -************************** +******************** + The 2022.1 release notes were released on 7/19/2022 and describe the following: .. contents:: @@ -10,7 +11,8 @@ The 2022.1 release notes were released on 7/19/2022 and describe the following: :depth: 1 Version Content ----------- +--------------- + The 2022.1 Release Notes describes the following: * Enhanced security features. @@ -23,7 +25,8 @@ Storage Version The storage version presently in effect is version 40. New Features ----------- +------------ + The 2022.1 Release Notes include the following new features: .. contents:: @@ -31,7 +34,8 @@ The 2022.1 Release Notes include the following new features: :depth: 1 Data Encryption -************ +*************** + SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. @@ -39,19 +43,22 @@ Using the data encryption feature may lead to a maximum of a 10% increase in per For more information, see `Data Encryption <https://docs.sqream.com/en/v2022.1/feature_guides/data_encryption.html>`_. Update Feature -************ +************** + SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. For more information, see `UPDATE <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/update.html#update>`_. Avro Ingestion -************ +************** + SQream now supports ingesting data from Avro files. For more information, see `Inserting Data from Avro <https://docs.sqream.com/en/v2022.1/data_ingestion/avro.html>`_. Known Issues ---------- +------------ + The following table lists the known issues for Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ @@ -71,7 +78,8 @@ The following table lists the known issues for Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ Resolved Issues ---------- +--------------- + The following table lists the issues that were resolved in Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ @@ -81,25 +89,30 @@ The following table lists the issues that were resolved in Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ Operations and Configuration Changes --------- +------------------------------------ + No relevant operations and configuration changes were made. Naming Changes -------- +-------------- + No relevant naming changes were made. Deprecated Features -------- +------------------- + In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. -If you are using an earlier version of SQream, see the `Using Legacy String Literals <https://docs.sqream.com/en/v2022.1/configuration_guides/use_legacy_string_literals.html>`_ configuration flag. +If you are using an earlier version of SQream, see the :ref:`Using Legacy String Literals <use_legacy_string_literals>` configuration flag. End of Support -------- +-------------- + The End of Support section is not relevant to Version 2022.1. Upgrading to v2022.1 -------- +-------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -134,9 +147,3 @@ Upgrading to v2022.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - - 2022.1 From 52eeb16e67c37401e699cb569c03f89f19f215f1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Jul 2023 09:46:59 +0300 Subject: [PATCH 0692/1892] Update 2022.1.5.rst --- releases/2022.1.5.rst | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index 376a69b67..e6324e9cb 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -15,15 +15,19 @@ New Features The 2022.1.5 Release Notes include the following new features: -* keys_evaluate utility function enhancement - add problematic chunk ID to the function's output report. +* ``keys_evaluate`` utility function enhancement - add problematic chunk ID to the function's output report :: -* Automatically close database client connections that have been open for 24 hours without any active statements. +* Automatically close database client connections that have been open for 24 hours without any active statements :: -* release_defunct_locks utility function enhancement to receive new optional input parameter to specify timeout - for more details see `Lock Related Issues <../troubleshooting/lock_related_issues.html>`_. +* ``release_defunct_locks`` utility function enhancement to receive new optional input parameter to specify timeout - for more details see :ref:`Lock Related Issues <lock_related_issues>`. + + :: + +* Metadata scale up process improvement through RocksDB configuration improvements Storage Version --------------- @@ -59,6 +63,14 @@ The following table lists the issues that were resolved in Version 2022.1.5: +--------------+------------------------------------------------------------------------------------------+ | SQ-11905 | GetDate casting to as text returns DATE with 0s in the time part or no time part at all | +--------------+------------------------------------------------------------------------------------------+ +| SQ-12580 | Server Picker and Meta Data server may not be deployed on servers without GPU | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-12690 | Worker thread increase | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-13775 | Worker down issue | ++--------------+------------------------------------------------------------------------------------------+ +| SQ-13947 | Non-Unicode character query execution error | ++--------------+------------------------------------------------------------------------------------------+ Operations and Configuration Changes From e20a8d67fa83ee7919426a60a26cfc72274fa2f5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Jul 2023 12:13:12 +0300 Subject: [PATCH 0693/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index c1268ea7a..f5bbeedfa 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.2.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.2.tar.gz A folder named ``sqloader-0.0.2`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.2.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle-incr.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user=`` - Username of a role to use for connection * - ``password=`` - Specifies the password of the selected role * - ``ssl=`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize=<batchSize>`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once * - ``-casesensative=<true/false>`` - Optional - ``false`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize=<chunkSize>`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist=<columnFilePath>`` - Optional - None - The name of the file that contains all column names * - ``-columns=<columns>`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config=<config_file_name>`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count=<true/false>`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete=<true/false>`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop=<true/false>`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target=<targetTableName>`` parameter * - ``-fetchsize=<fetchSize>`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter=<filter>`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit=<limit>`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm=<true/false>`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir=<log_directory_path>`` - Optional - ``logs`` - Defines the path of log directory created when loading data * - ``-partition=<partition_name>`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid=deprecated`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split=<split_by_column>`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table=<source_table_name>`` - Mandatory - None - Source table name to load data from * - ``-target=<target_table_name>`` - Optional - Source table name - Target table name to load data into * - ``-target_db=deprecated`` - Optional - None - Target database name to load data into * - ``-thread=<number_of_threads>`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate=<true/false>`` - Optional - ``false`` - Truncate target table. Default is ``false`` * - ``-type=<full/inc/cdc>`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions=<true/false>`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.2.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.2.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table. Default is ``false`` * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 9141d19277c024dfb6983de0ab703962c56e0e81 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Jul 2023 15:47:32 +0300 Subject: [PATCH 0694/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index f5bbeedfa..61b259a9f 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.x.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - Keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table. Default is ``false`` * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path\to\your\config\file Loading data into a table using a custom configuration file: .. code-block:: console -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file From b1797518d6abcb39114260137af891d7f360325d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:27:38 +0300 Subject: [PATCH 0695/1892] Update connection_string.java --- data_ingestion/connection_string.java | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java index 0bcfadeb0..3f4c414d4 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.java @@ -1,4 +1,6 @@ -##Postgresql, Oracle, and SQreamDB Connection Strings - mandatory! +####mandatory! + +##Postgresql, Oracle, and SQreamDB Connection Strings #postgres source.jdbc.connectionstring=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> @@ -9,11 +11,21 @@ #sqream sqream.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> +##CDC and Incremental Parameter + +cdc_catalog_table=SMSDW.CDC_TABLES +cdc_tracking_table=SMSDW.CDC_TRACKING +cdc_primary_keys_table=SMSDW.CDC_TABLE_PRIMARY_KEYS + -##Optional + +####Optional! -#Oracle +#Oracle Catalog #catalog.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> -#SQreamDB -#catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> \ No newline at end of file +#SQreamDB Catalog +#catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> + +#Summary Parameter +#load_summary_table=SMSDW.SQLOAD_SUMMARY \ No newline at end of file From b189a427aacfa1426f9d144da918aa8c65990759 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 24 Jul 2023 16:32:23 +0300 Subject: [PATCH 0696/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 61b259a9f..f822a1159 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle-incr.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 9283499e422fe79e68742482f261c17465349d52 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 09:32:08 +0300 Subject: [PATCH 0697/1892] Update sql_data_types_string.rst --- data_type_guides/sql_data_types_string.rst | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/data_type_guides/sql_data_types_string.rst b/data_type_guides/sql_data_types_string.rst index df4261d8f..c8986a088 100644 --- a/data_type_guides/sql_data_types_string.rst +++ b/data_type_guides/sql_data_types_string.rst @@ -1,32 +1,35 @@ .. _sql_data_types_string: -************************* +****** String -************************* -``TEXT`` is designed for storing text or strings of characters. +****** -SQream UTF-8 representations (``TEXT``). +``TEXT`` is designed for storing text or strings of characters. SQreamDB blocks non-UTF8 string inputs. Length -^^^^^^^^^ +^^^^^^ + When using ``TEXT``, specifying a size is optional. If not specified, the text field carries no constraints. To limit the size of the input, use ``TEXT(n)``, where ``n`` is the permitted number of characters. The following apply to setting the String type length: -* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQream DB will return an error. +* If the data exceeds the column length limit on ``INSERT`` or ``COPY`` operations, SQreamDB will return an error. * When casting or converting, the string has to fit in the target. For example, ``'Kiwis are weird birds' :: TEXT(5)`` will return an error. Use ``SUBSTRING`` to truncate the length of the string. Syntax -^^^^^^^^ +^^^^^^ + String types can be written with standard SQL string literals, which are enclosed with single quotes, such as ``'Kiwi bird'``. To include a single quote in the string, use double quotations, such as ``'Kiwi bird''s wings are tiny'``. String literals can also be dollar-quoted with the dollar sign ``$``, such as ``$$Kiwi bird's wings are tiny$$`` is the same as ``'Kiwi bird''s wings are tiny'``. Size -^^^^^^ -``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQream. +^^^^ + +``TEXT(n)`` can occupy up to *4*n* bytes. However, the size of strings is variable and is compressed by SQreamDB. String Examples -^^^^^^^^^^ +^^^^^^^^^^^^^^^ + The following is an example of the String syntax: .. code-block:: postgres @@ -49,7 +52,8 @@ The following is an example of the correct output: .. note:: Most clients control the display precision of floating point numbers, and values may appear differently in some clients. String Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following table shows the possible String value conversions: .. list-table:: From 3954db77eb25afb398fe9364d615f2b911b3dc88 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 10:08:34 +0300 Subject: [PATCH 0698/1892] Update index.rst --- data_type_guides/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/data_type_guides/index.rst b/data_type_guides/index.rst index 9d9ceeadd..910ad0afb 100644 --- a/data_type_guides/index.rst +++ b/data_type_guides/index.rst @@ -3,6 +3,7 @@ ********** Data Types ********** + This section describes the following: .. toctree:: From 9cd02a8cad4848a2b84e9f984663fcc6f57b4e48 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:09:26 +0300 Subject: [PATCH 0699/1892] Denodo --- .../client_platforms/denodo.rst | 75 +++++++++++++++++++ .../client_platforms/index.rst | 1 + .../client_platforms/tableau.rst | 4 +- 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 connecting_to_sqream/client_platforms/denodo.rst diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst new file mode 100644 index 000000000..341a8e410 --- /dev/null +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -0,0 +1,75 @@ +.. _denodo: + +*************** +Denodo Platform +*************** + + + +.. contents:: + :local: + :depth: 1 + +Prerequisites +============= + +It is essential that you have the following installed: + +* Denodo 8.0 + +Setting Up a Connection to SQreamDB +=================================== + +#. Under ``Denodo\DenodoPlatform8.0\lib\extensions\jdbc-drivers``, create a directory named ``sqream``. + +#. Download the SQreamDB JDBC Connector :ref:`.jar file <client_drivers>` and save it under the newly created ``sqream`` directory. + +#. In the Denodo Platform menu, go to **File** > **New** > **Data Source** > **JDBC**. + + A connection dialog box is displayed. + +#. Under the **Configuration** tab, select the **Connection** tab and fill in the data source information: + + .. list-table:: + :widths: auto + :header-rows: 1 + + * - Field name + - Description + - Value + * - Name + - The name of the data source + - ``sqream`` + * - Database adapter + - The database adapter allows Denodo Platform to communicate and interact with SQreamDB + - ``Generic`` + * - Driver class path + - The path to the location of the JDBC driver required for the connection to the data source + - sqream-4.x.x + * - Driver class + - The class name of the JDBC driver used to connect to the data source + - ``com.sqream.jdbc.SQDriver`` + * - Database URI + - The URI that specifies the location and details of the database or data source to be connected + - ``jdbc:Sream://192.168.4.93:3108/master;cluster=true`` + * - Transaction isolation + - The level of isolation used to manage concurrent transactions in the database connection, ensuring data consistency and integrity + - ``Database default`` + * - Authentication + - Authentication method + - ``Use login and password + * - Login + - The SQreamDB role + - Example: SqreamRole + * - Password + - The SQreamDB role password + - Example: SqreamRolePassword2023 + +#. To verify your newly created connection, select the **Test connection** button. + +Limitations +=========== + +* When exporting a view from Denodo to SQreamDB, if the view involves a join operation where both tables have columns with the same name, SQreamDB may encounter errors due to the ambiguity in determining which specific column to utilize. + +* \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 6b9b70efd..e241f0b66 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -36,6 +36,7 @@ If you are looking for a tool that is not listed, SQream and our partners can he tableau talend tibco_spotfire + denodo .. image:: /_static/images/connectivity_ecosystem.png diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 733efc317..4f3d60289 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -25,7 +25,7 @@ Setting Up JDBC ---------------- #. Download the SQream JDBC Connector :ref:`.jar file <client_drivers>`. -#. Place the JDBC .jar file in the Tableau driver directory. +#. Place the JDBC ``.jar`` file in the Tableau driver directory. Based on your operating system, you may find the Tableau driver directory in one of the following locations: @@ -79,7 +79,7 @@ Connecting to SQream #. Select **SQream DB by SQream Technologies**. - The connection dialog box is displayed. + A connection dialog box is displayed. :: From a267c106c80259d4ada04f9b0e0b3bb0067b0d45 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:54:20 +0300 Subject: [PATCH 0700/1892] Update keywords_and_identifiers.rst --- .../sql_syntax/keywords_and_identifiers.rst | 159 ++++++++++++------ 1 file changed, 112 insertions(+), 47 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index efe1ba42f..104689ade 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -26,50 +26,115 @@ Identifiers are different than **keywords**, which are predefined words reserved The following table shows a full list of the reserved keywords: -+-------------------------------------------------------------------------------------------------+ -| **Keywords** | -+-------------------+---------------------+--------------------+------------------+---------------+ -| **A - C** | **C - G** | **H - N** | **N - S** | **S - W** | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ALL`` | ``CURRENT_CATALOG`` | ``HASH`` | ``NOT`` | ``SIMILAR`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ANALYSE`` | ``CURRENT_ROLE`` | ``HAVING`` | ``NOTNULL`` | ``SOME`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ANALYZE`` | ``CURRENT_TIME`` | ``ILIKE`` | ``NULL`` | ``SYMMETRIC`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``AND`` | ``CURRENT_USER`` | ``IN`` | ``OFFSET`` | ``TABLE`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ANY`` | ``DEFAULT`` | ``INITIALLY`` | ``ON`` | ``THEN`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ARRAY`` | ``DEFERRABLE`` | ``INNER`` | ``ONLY`` | ``TO`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``AS`` | ``DESC`` | ``INTERSECT`` | ``OPTION`` | ``TRAILING`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``ASC`` | ``DISTINCT`` | ``INTO`` | ``OR`` | ``TRAN`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``AUTHORIZATION`` | ``DO`` | ``IS`` | ``ORDER`` | ``TRUE`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``BINARY`` | ``ELSE`` | ``ISNULL`` | ``OUTER`` | ``UNION`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``BIGINT`` | ``END`` | ``JOIN`` | ``OVER`` | ``UNIQUE`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``BOTH`` | ``EXCEPT`` | ``LEADING`` | ``OVERLAPS`` | ``USER`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``CASE`` | ``FALSE`` | ``LEFT`` | ``PLACING`` | ``USING`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``CAST`` | ``FETCH`` | ``LIKE`` | ``PRIMARY`` | ``VARIADIC`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``CHECK`` | ``FOR`` | ``LIMIT`` | ``REFERENCES`` | ``VERBOSE`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLLATE`` | ``FREEZE`` | ``LOCALTIME`` | ``RETURNING`` | ``WHEN`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``COLUMN`` | ``FROM`` | ``LOCALTIMESTAMP`` | ``RIGHT`` | ``WHERE`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONCURRENTLY`` | ``FULL`` | ``LOOP`` | ``RLIKE`` | ``WINDOW`` | -+-------------------+---------------------+--------------------+------------------+---------------+ -| ``CONSTRAINT`` | ``FUNCTION`` | ``MERGE`` | ``SELECT`` | ``WITH`` | -+-------------------+---------------------+--------------------+------------------+ | -| ``CREATE`` | ``GRANT`` | ``NATURAL`` | ``SESSION_USER`` | | -+-------------------+---------------------+--------------------+------------------+ | -| ``CROSS`` | ``GROUP`` | | | | -+-------------------+---------------------+--------------------+------------------+---------------+ + + - ``ALL`` + - ``ANALYSE`` + - ``ANALYZE`` + - ``AND`` + - ``ANY`` + - ``ARRAY`` + - ``AS`` + - ``ASC`` + - ``AUTHORIZATION`` + - ``BINARY`` + - ``BIGINT`` + - ``BOTH`` + - ``CASE`` + - ``CAST`` + - ``CHECK`` + - ``COLLATE`` + - ``COLUMN`` + - ``CONCURRENTLY`` + - ``CONSTRAINT`` + - ``CREATE`` + - ``CROSS`` + - ``CURRENT_CATALOG`` + - ``CURRENT_ROLE`` + - ``CURRENT_TIME`` + - ``CURRENT_USER`` + - ``DEFAULT`` + - ``DEFERRABLE`` + - ``DESC`` + - ``DISTINCT`` + - ``DO`` + - ``ELSE`` + - ``END`` + - ``EXCEPT`` + - ``FALSE`` + - ``FETCH`` + - ``FOR`` + - ``FREEZE`` + - ``FROM`` + - ``FULL`` + - ``FUNCTION`` + - ``GRANT`` + - ``GROUP`` + - ``HASH`` + - ``HAVING`` + - ``ILIKE`` + - ``IN`` + - ``INITIALLY`` + - ``INNER`` + - ``INTERSECT`` + - ``INTO`` + - ``IS`` + - ``ISNULL`` + - ``JOIN`` + - ``KEY`` + - ``LEADING`` + - ``LEFT`` + - ``LIKE`` + - ``LIMIT`` + - ``LOCALTIME`` + - ``LOCALTIMESTAMP`` + - ``LOOP`` + - ``MERGE`` + - ``NATURAL`` + - ``NOT`` + - ``NOTNULL`` + - ``NULL`` + - ``OFFSET`` + - ``ON`` + - ``ONLY`` + - ``OPTION`` + - ``OR`` + - ``ORDER`` + - ``OUTER`` + - ``OVER`` + - ``OVERLAPS`` + - ``PERCENT`` + - ``PLACING`` + - ``PRIMARY`` + - ``PRECISION`` + - ``PROC`` + - ``REFERENCES`` + - ``RETURNING`` + - ``RIGHT`` + - ``RLIKE`` + - ``SELECT`` + - ``SESSION_USER`` + - ``SET`` + - ``SIMILAR`` + - ``SOME`` + - ``SYMMETRIC`` + - ``TABLE`` + - ``THEN`` + - ``TO`` + - ``TRAILING`` + - ``TRAN`` + - ``TRUE`` + - ``UNION`` + - ``UNIQUE`` + - ``USER`` + - ``USING`` + - ``VARIADIC`` + - ``VERBOSE`` + - ``WHEN`` + - ``WHERE`` + - ``WINDOW`` + - ``WITH`` + + + + + From 1da06564a7b53654f383c1eba333afc31e94b2f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 12:55:36 +0300 Subject: [PATCH 0701/1892] Update keywords_and_identifiers.rst --- reference/sql/sql_syntax/keywords_and_identifiers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 104689ade..75687998c 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -24,7 +24,7 @@ Quoted identifiers must follow these rules: Identifiers are different than **keywords**, which are predefined words reserved with specific meanings in a statement. Some examples of keywords are ``SELECT``, ``CREATE``, and ``WHERE``. Note that keywords **cannot** be used as identifiers. -The following table shows a full list of the reserved keywords: +SQreamDB reserved keywords: - ``ALL`` From 7c2c7bb11b5632d707f8f90e727b7b711c95922a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 25 Jul 2023 14:31:26 +0300 Subject: [PATCH 0702/1892] Update denodo.rst --- .../client_platforms/denodo.rst | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst index 341a8e410..30f33e204 100644 --- a/connecting_to_sqream/client_platforms/denodo.rst +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -4,11 +4,7 @@ Denodo Platform *************** - - -.. contents:: - :local: - :depth: 1 +Denodo Platform is a data virtualization solution that enables integration, access, and real-time data delivery from disparate on-premises and cloud-based sources. Prerequisites ============= @@ -37,39 +33,43 @@ Setting Up a Connection to SQreamDB * - Field name - Description - Value + - Example * - Name - The name of the data source - ``sqream`` + - * - Database adapter - The database adapter allows Denodo Platform to communicate and interact with SQreamDB - ``Generic`` + - * - Driver class path - The path to the location of the JDBC driver required for the connection to the data source - - sqream-4.x.x + - + - ``path/to/jdbcdriver/sqream-jdbc-x.x.x`` * - Driver class - The class name of the JDBC driver used to connect to the data source - ``com.sqream.jdbc.SQDriver`` + - * - Database URI - The URI that specifies the location and details of the database or data source to be connected - ``jdbc:Sream://192.168.4.93:3108/master;cluster=true`` + - * - Transaction isolation - The level of isolation used to manage concurrent transactions in the database connection, ensuring data consistency and integrity - ``Database default`` + - * - Authentication - Authentication method - - ``Use login and password + - ``Use login and password`` + - * - Login - The SQreamDB role - - Example: SqreamRole + - + - ``SqreamRole`` * - Password - The SQreamDB role password - - Example: SqreamRolePassword2023 + - + - ``SqreamRolePassword2023`` -#. To verify your newly created connection, select the **Test connection** button. - -Limitations -=========== - -* When exporting a view from Denodo to SQreamDB, if the view involves a join operation where both tables have columns with the same name, SQreamDB may encounter errors due to the ambiguity in determining which specific column to utilize. +5. To verify your newly created connection, select the **Test connection** button. -* \ No newline at end of file From 3f1a2e88e0c456f8ed5ae034f50b1456e72a0aaa Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Jul 2023 08:01:48 +0300 Subject: [PATCH 0703/1892] Update char_length.rst --- .../scalar_functions/string/char_length.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/char_length.rst b/reference/sql/sql_functions/scalar_functions/string/char_length.rst index 79bbdcdbc..25e684c82 100644 --- a/reference/sql/sql_functions/scalar_functions/string/char_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/char_length.rst @@ -1,8 +1,8 @@ .. _char_length: -************************** +****************************** CHARACTER_LENGTH / CHAR_LENGTH -************************** +****************************** Calculates the number of characters in a string. @@ -11,15 +11,15 @@ Calculates the number of characters in a string. * To get the length in bytes, see :ref:`octet_length`. Syntax -========== +====== .. code-block:: postgres - CHAR_LEN( text_expr ) --> INT - CHARACTER_LEN( text_expr ) --> INT + CHAR_LENGTH( text_expr ) --> INT + CHARACTER_LENGTH( text_expr ) --> INT Arguments -============ +========= .. list-table:: :widths: auto @@ -31,19 +31,19 @@ Arguments - ``TEXT`` expression Returns -============ +======= Return an integer containing the number of characters in the string. Notes -======= +===== * To get the length in bytes, see :ref:`octet_length` * If the value is NULL, the result is NULL. Examples -=========== +======== For these examples, consider the following table and contents: @@ -56,7 +56,7 @@ For these examples, consider the following table and contents: , ('אבגדהוזחטיכלמנסעפצקרשת'); Length in characters and bytes of strings --------------------------------------------------- +----------------------------------------- ASCII characters take up 1 byte per character, while Thai takes up 3 bytes and Hebrew takes up 2 bytes. From efd08b7d0311b516b7001041b4a8b3a1878982cb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Jul 2023 08:48:08 +0300 Subject: [PATCH 0704/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index f822a1159..fc9c1a115 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ********* Databases ********* The **SQLoader** is a CLI program that enables you to load into SQreamDB data from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 60e4f7e9e36d86ffede71c410fd7a136230b7e4e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 27 Jul 2023 09:27:46 +0300 Subject: [PATCH 0705/1892] RN --- releases/4.3.rst | 4 +++- releases/4.4.rst | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 1995e7fd8..35e00d73b 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -19,7 +19,7 @@ Compatibility Matrix | Supported OS | * CentOS / REHL - 7.6 - 7.9 | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +| Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 49 | +-------------------------+------------------------------------------------------------------------+ @@ -34,6 +34,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► A new :re:`SQLoader <ingesting_from_databases>` will enable you to load data into SQreamDB from other databases. + ► Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: * VIEWS diff --git a/releases/4.4.rst b/releases/4.4.rst index afd67223c..b12c2cdc8 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -34,10 +34,6 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► **SQLoader** - -The :ref:`SQLoader<ingesting_from_databases>` is a CLI program that enables you to load into SQreamDB data from other databases. - Known Issues From 7f2c5f75960c2d2b00e3d89893b3bfb39935bba1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 30 Jul 2023 11:38:50 +0300 Subject: [PATCH 0706/1892] remove k8s --- .../installing_and_launching_sqream.rst | 7 +- .../installing_sqream_with_kubernetes.rst | 1816 ----------------- 2 files changed, 3 insertions(+), 1820 deletions(-) delete mode 100644 installation_guides/installing_sqream_with_kubernetes.rst diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index ee03a8922..2c325c3a7 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -1,9 +1,8 @@ .. _installing_and_launching_sqream: -******************************* +************************* Installing and Launching SQream -******************************* - +************************* The **Installing and Launching SQream** page includes the following installation guides: .. toctree:: @@ -12,6 +11,6 @@ The **Installing and Launching SQream** page includes the following installation recommended_pre-installation_configurations installing_sqream_with_binary - installing_sqream_with_kubernetes + running_sqream_in_a_docker_container installing_monit launching_sqream_with_monit \ No newline at end of file diff --git a/installation_guides/installing_sqream_with_kubernetes.rst b/installation_guides/installing_sqream_with_kubernetes.rst deleted file mode 100644 index 0abde10d3..000000000 --- a/installation_guides/installing_sqream_with_kubernetes.rst +++ /dev/null @@ -1,1816 +0,0 @@ -.. _installing_sqream_with_kubernetes: - -********************************************* -Installing SQream with Kubernetes -********************************************* -**Kubernetes**, also known as **k8s**, is a portable open source platform that automates Linux container operations. Kubernetes supports outsourcing data centers to public cloud service providers or can be scaled for web hosting. SQream uses Kubernetes as an orchestration and recovery solution. - -The **Installing SQream with Kubernetes** guide describes the following: - -.. contents:: - :local: - :depth: 1 - -.. _preparing_sqream_environment: - -Preparing the SQream Environment to Launch SQream Using Kubernetes -=============== - -The **Preparing the SQream environment to Launch SQream Using Kubernetes** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Overview --------------- - -A minimum of three servers is required for preparing the SQream environment using Kubernetes. - -Kubernetes uses clusters, which are sets of nodes running containterized applications. A cluster consists of at least two GPU nodes and one additional server without GPU to act as the quorum manager. - -Each server must have the following IP addresses: - -* An IP address located in the management network. -* An additional IP address from the same subnet to function as a floating IP. - -All servers must be mounted in the same shared storage folder. - -The following list shows the server host name format requirements: - -* A maximum of 253 characters. -* Only lowercase alphanumeric characters, such as ``-`` or ``.``. -* Starts and ends with alphanumeric characters. - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes<preparing_sqream_environment>` - - -Operating System Requirements ------------------------------- -The required operating system is a version of x86 CentOS/RHEL between 7.6 and 7.9. Regarding PPC64le, the required version is RHEL 7.6. - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes<preparing_sqream_environment>` - - -Compute Server Specifications ------------------------------- -Installing SQream with Kubernetes includes the following compute server specifications: - -* **CPU:** 4 cores -* **RAM:** 16GB -* **HD:** 500GB - -Go back to :ref:`Preparing the SQream Environment to Launch SQream Using Kubernetes<preparing_sqream_environment>` - -.. _set_up_your_hosts: - -Setting Up Your Hosts -=============================== -SQream requires you to set up your hosts. Setting up your hosts requires the following: - -.. contents:: - :local: - :depth: 1 - -Configuring the Hosts File --------------------------------- -**To configure the /etc/hosts file:** - -1. Edit the **/etc/hosts** file: - - .. code-block:: console - - $ sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - $ 127.0.0.1 localhost - $ <server ip> <server_name> - - -Installing the Required Packages ----------------------------------- -The first step in setting up your hosts is to install the required packages. - -**To install the required packages:** - -1. Run the following command based on your operating system: - - * RHEL: - - .. code-block:: postgres - - $ sudo yum -y install https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - * CentOS: - - .. code-block:: postgres - - $ sudo yum install epel-release - $ sudo yum install pciutils openssl-devel python36 python36-pip kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc jq net-tools ntp - -2. Verify that that the required packages were successfully installed. The following is the correct output: - - .. code-block:: postgres - - ntpq --version - jq --version - python3 --version - pip3 --version - rpm -qa |grep kernel-devel-$(uname -r) - rpm -qa |grep kernel-headers-$(uname -r) - gcc --version - -3. Enable the **ntpd (Network Time Protocol daemon)** program on all servers: - - .. code-block:: postgres - - $ sudo systemctl start ntpd - $ sudo systemctl enable ntpd - $ sudo systemctl status ntpd - $ sudo ntpq -p - -Go back to :ref:`Setting Up Your Hosts<set_up_your_hosts>` - - -Disabling the Linux UI ----------------------------------- -After installing the required packages, you must disable the Linux UI if it has been installed. - -You can disable Linux by running the following command: - - .. code-block:: postgres - - $ sudo systemctl set-default multi-user.target - -Go back to :ref:`Setting Up Your Hosts<set_up_your_hosts>` - - -Disabling SELinux ----------------------------------- -After disabling the Linux UI you must disable SELinux. - -**To disable SELinux:** - - 1. Run the following command: - - .. code-block:: postgres - - $ sed -i -e s/enforcing/disabled/g /etc/selinux/config - $ sudo reboot - - 2. Reboot the system as a root user: - - .. code-block:: postgres - - $ sudo reboot - -Go back to :ref:`Setting Up Your Hosts<set_up_your_hosts>` - -Disabling Your Firewall ----------------------------------- -After disabling SELinux, you must disable your firewall by running the following commands: - - .. code-block:: postgres - - $ sudo systemctl stop firewalld - $ sudo systemctl disable firewalld - -Go back to :ref:`Setting Up Your Hosts<set_up_your_hosts>` - - -Checking the CUDA Version ----------------------------------- -After completing all of the steps above, you must check the CUDA version. - -**To check the CUDA version:** - -1. Check the CUDA version: - - .. code-block:: postgres - - $ nvidia-smi - - The following is an example of the correct output: - - .. code-block:: postgres - - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - | | | MIG M. | - |===============================+======================+======================| - | 0 NVIDIA A100-PCI... On | 00000000:17:00.0 Off | 0 | - | N/A 34C P0 64W / 300W | 79927MiB / 80994MiB | 0% Default | - | | | Disabled | - +-------------------------------+----------------------+----------------------+ - | 1 NVIDIA A100-PCI... On | 00000000:CA:00.0 Off | 0 | - | N/A 35C P0 60W / 300W | 79927MiB / 80994MiB | 0% Default | - | | | Disabled | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -In the above output, the CUDA version is **10.1**. - -If the above output is not generated, CUDA has not been installed. To install CUDA, see :ref:`installing-the-cuda-driver`. - -Go back to :ref:`Setting Up Your Hosts<set_up_your_hosts>` - -.. _install_kubernetes_cluster: - -Installing Your Kubernetes Cluster -=================================== -After setting up your hosts, you must install your Kubernetes cluster. The Kubernetes and SQream software must be installed from the management host, and can be installed on any server in the cluster. - -Installing your Kubernetes cluster requires the following: - -.. contents:: - :local: - :depth: 1 - -Generating and Sharing SSH Keypairs Across All Existing Nodes ------------------------------------- -You can generate and share SSH keypairs across all existing nodes. Sharing SSH keypairs across all nodes enables passwordless access from the management server to all nodes in the cluster. All nodes in the cluster require passwordless access. - -.. note:: You must generate and share an SSH keypair across all nodes even if you are installing the Kubernetes cluster on a single host. - -**To generate and share an SSH keypair:** - -1. Switch to root user access: - - .. code-block:: postgres - - $ sudo su - - -2. Generate an RSA key pair: - - .. code-block:: postgres - - $ ssh-keygen - -The following is an example of the correct output: - - .. code-block:: postgres - - $ ssh-keygen - $ Generating public/private rsa key pair. - $ Enter file in which to save the key (/root/.ssh/id_rsa): - $ Created directory '/root/.ssh'. - $ Enter passphrase (empty for no passphrase): - $ Enter same passphrase again: - $ Your identification has been saved in /root/.ssh/id_rsa. - $ Your public key has been saved in /root/.ssh/id_rsa.pub. - $ The key fingerprint is: - $ SHA256:xxxxxxxxxxxxxxdsdsdffggtt66gfgfg root@localhost.localdomain - $ The key's randomart image is: - $ +---[RSA 2048]----+ - $ | =*. | - $ | .o | - $ | ..o o| - $ | . .oo +.| - $ | = S =...o o| - $ | B + *..o+.| - $ | o * *..o .+| - $ | o * oo.E.o| - $ | . ..+..B.+o| - $ +----[SHA256]-----+ - -The generated file is ``/root/.ssh/id_rsa.pub``. - -3. Copy the public key to all servers in the cluster, including the one that you are running on. - - .. code-block:: postgres - - $ ssh-copy-id -i ~/.ssh/id_rsa.pub root@remote-host - -4. Replace the ``remote host`` with your host IP address. - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Installing and Deploying a Kubernetes Cluster Using Kubespray ------------------------------------- -SQream uses the Kubespray software package to install and deploy Kubernetes clusters. - -**To install and deploy a Kubernetes cluster using Kubespray:** - - -1. Clone Kubernetes: - - 1. Clone the **kubespray.git** repository: - - .. code-block:: postgres - - $ git clone https://github.com/kubernetes-incubator/kubespray.git - - 2. Nagivate to the **kubespray** directory: - - .. code-block:: postgres - - $ cd kubespray - - 3. Install the **requirements.txt** configuration file: - - .. code-block:: postgres - - $ pip3 install -r requirements.txt - -2. Create your SQream inventory directory: - - 1. Run the following command: - - .. code-block:: postgres - - $ cp -rp inventory/sample inventory/sqream - - 2. Replace the **<cluster node IP>** with the defined cluster node IP address(es). - - .. code-block:: postgres - - $ declare -a IPS=(<host>, <cluster node IP address>) - - For example, the following replaces ``192.168.0.93`` with ``192.168.0.92``: - - .. code-block:: postgres - - $ declare -a IPS=(host-93,192.168.0.93 host-92,192.168.0.92) - -Note the following: - * Running a declare requires defining a pair (host name and cluster node IP address), as shown in the above example. - * You can define more than one pair. - -3. When the reboot is complete, switch back to the root user: - - .. code-block:: postgres - - $ sudo su - - -4. Navigate to **root/kubespray**: - - .. code-block:: postgres - - $ cd /root/kubespray - -5. Copy ``inventory/sample`` as ``inventory/sqream``: - - .. code-block:: postgres - - $ cp -rfp inventory/sample inventory/sqream - -6. Update the Ansible inventory file with the inventory builder: - - .. code-block:: postgres - - $ declare -a IPS=(<hostname1>,<IP1> <hostname2>,<IP2> <hostname3>,<IP3>) - -7. In the **kubespray hosts.yml** file, set the node IP's: - - .. code-block:: postgres - - $ CONFIG_FILE=inventory/sqream/hosts.yml python3 contrib/inventory_builder/inventory.py ${IPS[@]} - - If you do not set a specific hostname in declare, the server hostnames will change to ``node1``, ``node2``, etc. To maintain specific hostnames, run declare as in the following example: - - .. code-block:: postgres - - $ declare -a IPS=(eks-rhl-1,192.168.5.81 eks-rhl-2,192.168.5.82 eks-rhl-3,192.168.5.83) - - Note that the declare must contain pairs (hostname,ip). - -:: - -8. Verify that the following have been done: - - * That the **hosts.yml** file is configured correctly. - * That all children are included with their relevant nodes. - -You can save your current server hostname by replacing <nodeX> with your server hostname. - -9. Generate the content output of the **hosts.yml** file. Make sure to include the file's directory: - - .. code-block:: postgres - - $ cat inventory/sqream/hosts.yml - -The hostname can be lowercase and contain ``-`` or ``.`` only, and must be aligned with the server's hostname. - -The following is an example of the correct output. Each host and IP address that you provided in Step 2 should be displayed once: - - .. code-block:: postgres - - $ all: - $ hosts: - $ node1: - $ ansible_host: 192.168.5.81 - $ ip: 192.168.5.81 - $ access_ip: 192.168.5.81 - $ node2: - $ ansible_host: 192.168.5.82 - $ ip: 192.168.5.82 - $ access_ip: 192.168.5.82 - $ node3: - $ ansible_host: 192.168.5.83 - $ ip: 192.168.5.83 - $ access_ip: 192.168.5.83 - $ children: - $ kube-master: - $ hosts: - $ node1: - $ node2: - $ node3: - $ kube-node: - $ hosts: - $ node1: - $ node2: - $ node3: - $ etcd: - $ hosts: - $ node1: - $ node2: - $ node3: - $ k8s-cluster: - $ children: - $ kube-master: - $ kube-node: - $ calico-rr: - $ hosts: {} - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Adjusting Kubespray Deployment Values -------------------------------------- -After downloading and configuring Kubespray, you can adjust your Kubespray deployment values. A script is used to modify how the Kubernetes cluster is deployed, and you must set the cluster name variable before running this script. - -.. note:: The script must be run from the **kubespray** folder. - -**To adjust Kubespray deployment values:** - -1. Add the following export to the local user’s **~/.bashrc** file by replacing the <VIP IP> with the user's Virtual IP address: - - .. code-block:: postgres - - $ export VIP_IP=<VIP IP> - -2. Logout, log back in, and verify the following: - - .. code-block:: postgres - - $ echo $VIP_IP - -3. Make the following replacements to the **kubespray.settings.sh** file: - - .. code-block:: postgres - - $ cat <<EOF > kubespray_settings.sh - $ sed -i "/cluster_name: cluster.local/c \cluster_name: cluster.local.$cluster_name" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ sed -i "/dashboard_enabled/c \dashboard_enabled\: "false"" inventory/sqream/group_vars/k8s-cluster/addons.yml - $ sed -i "/kube_version/c \kube_version\: "v1.18.3"" inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ sed -i "/metrics_server_enabled/c \metrics_server_enabled\: "true"" inventory/sample/group_vars/k8s-cluster/addons.yml - $ echo 'kube_apiserver_node_port_range: "3000-6000"' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_node_monitor_grace_period: 20s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_node_monitor_period: 2s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kube_controller_pod_eviction_timeout: 30s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'kubelet_status_update_frequency: 4s' >> inventory/sqream/group_vars/k8s-cluster/k8s-cluster.yml - $ echo 'ansible ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers - $ EOF - -.. note:: In most cases, the Docker data resides on the system disk. Because Docker requires a high volume of data (images, containers, volumes, etc.), you can change the default Docker data location to prevent the system disk from running out of space. - -4. *Optional* - Change the default Docker data location: - - .. code-block:: postgres - - $ sed -i "/docker_daemon_graph/c \docker_daemon_graph\: "</path/to/desired/location>"" inventory/sqream/group_vars/all/docker.yml - -5. Make the **kubespray_settings.sh** file executable for your user: - - .. code-block:: postgres - - $ chmod u+x kubespray_settings.sh && ./kubespray_settings.sh - -6. Run the following script: - - .. code-block:: postgres - - $ ./kubespray_settings.sh - -7. Run a playbook on the **inventory/sqream/hosts.yml cluster.yml** file: - - .. code-block:: postgres - - $ ansible-playbook -i inventory/sqream/hosts.yml cluster.yml -v - -The Kubespray installation takes approximately 10 - 15 minutes. - -The following is an example of the correct output: - - .. code-block:: postgres - - $ PLAY RECAP - $ ********************************************************************************************* - $ node-1             : ok=680  changed=133  unreachable=0    failed=0 - $ node-2             : ok=583  changed=113  unreachable=0    failed=0 - $ node-3             : ok=586  changed=115  unreachable=0    failed=0 - $ localhost          : ok=1    changed=0    unreachable=0    failed=0 - -In the event that the output is incorrect, or a failure occurred during the installation, please contact a SQream customer support representative. - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>`. - -Checking Your Kubernetes Status -------------------------------- -After adjusting your Kubespray deployment values, you must check your Kubernetes status. - -**To check your Kuberetes status:** - -1. Check the status of the node: - - .. code-block:: postgres - - $ kubectl get nodes - -The following is an example of the correct output: - - .. code-block:: postgres - - $ NAME STATUS ROLES AGE VERSION - $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-3 Ready <none> 28m v1.21.1 - -2. Check the status of the pod: - - .. code-block:: postgres - - $ kubectl get pods --all-namespaces - - The following is an example of the correct output: - - .. code-block:: postgres - - $ NAMESPACE NAME READY STATUS RESTARTS AGE - $ kube-system calico-kube-controllers-68dc8bf4d5-n9pbp 1/1 Running 0 160m - $ kube-system calico-node-26cn9 1/1 Running 1 160m - $ kube-system calico-node-kjsgw 1/1 Running 1 160m - $ kube-system calico-node-vqvc5 1/1 Running 1 160m - $ kube-system coredns-58687784f9-54xsp 1/1 Running 0 160m - $ kube-system coredns-58687784f9-g94xb 1/1 Running 0 159m - $ kube-system dns-autoscaler-79599df498-hlw8k 1/1 Running 0 159m - $ kube-system kube-apiserver-k8s-host-1-134 1/1 Running 0 162m - $ kube-system kube-apiserver-k8s-host-194 1/1 Running 0 161m - $ kube-system kube-apiserver-k8s-host-68 1/1 Running 0 161m - $ kube-system kube-controller-manager-k8s-host-1-134 1/1 Running 0 162m - $ kube-system kube-controller-manager-k8s-host-194 1/1 Running 0 161m - $ kube-system kube-controller-manager-k8s-host-68 1/1 Running 0 161m - $ kube-system kube-proxy-5f42q 1/1 Running 0 161m - $ kube-system kube-proxy-bbwvk 1/1 Running 0 161m - $ kube-system kube-proxy-fgcfb 1/1 Running 0 161m - $ kube-system kube-scheduler-k8s-host-1-134 1/1 Running 0 161m - $ kube-system kube-scheduler-k8s-host-194 1/1 Running 0 161m - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Adding a SQream Label to Your Kubernetes Cluster Nodes -------------------------------------------------- -After checking your Kubernetes status, you must add a SQream label on your Kubernetes cluster nodes. - -**To add a SQream label on your Kubernetes cluster nodes:** - -1. Get the cluster node list: - - .. code-block:: postgres - - $ kubectl get nodes - - The following is an example of the correct output: - - .. code-block:: postgres - - $ NAME        STATUS   ROLES    AGE   VERSION - $ eks-rhl-1 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-2 Ready control-plane,master 29m v1.21.1 - $ eks-rhl-3 Ready <none> 28m v1.21.1 - -2. Set the node label, change the ``node-name`` to the node NAME(s) in the above example: - - .. code-block:: postgres - - $ kubectl label nodes <node-name> cluster=sqream - - The following is an example of the correct output: - - .. code-block:: postgres - - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-1 cluster=sqream - $ node/eks-rhl-1 labeled - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-2 cluster=sqream - $ node/eks-rhl-2 labeled - $ [root@edk-rhl-1 kubespray]# kubectl label nodes eks-rhl-3 cluster=sqream - $ node/eks-rhl-3 labeled - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Copying Your Kubernetes Configuration API File to the Master Cluster Nodes -------------------------------------------------- -After adding a SQream label on your Kubernetes cluster nodes, you must copy your Kubernetes configuration API file to your Master cluster nodes. - -When the Kubernetes cluster installation is complete, an API configuration file is automatically created in the **.kube** folder of the root user. This file enables the **kubectl** command access Kubernetes' internal API service. Following this step lets you run **kubectl** commands from any node in the cluster. - - -.. warning:: You must perform this on the management server only! - -**To copy your Kubernetes configuration API file to your Master cluster nodes:** - -1. Create the **.kube** folder in the **local user** directory: - - .. code-block:: postgres - - $ mkdir /home/<local user>/.kube - -2. Copy the configuration file from the root user directory to the <local user> directory: - - .. code-block:: postgres - - $ sudo cp /root/.kube/config /home/<local user>/.kube - -3. Change the file owner from **root user** to the <local user>: - - .. code-block:: postgres - - $ sudo chown <local user>.<local user> /home/<local user>/.kube/config - -4. Create the **.kube** folder in the other nodes located in the <local user> directory: - - .. code-block:: postgres - - $ ssh <local user>@<node name> mkdir .kube - -5. Copy the configuration file from the management node to the other nodes: - - .. code-block:: postgres - - $ scp /home/<local user>/.kube/config <local user>@<node name>:/home/<local user>/.kube/ - -6. Under local user on each server you copied **.kube** to, run the following command: - - .. code-block:: postgres - - $ sudo usermod -aG docker $USER - -This grants the local user the necessary permissions to run Docker commands. - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Creating an env_file in Your Home Directory -------------------------------------------------- -After copying your Kubernetes configuration API file to your Master cluster nodes, you must create an **env_file** in your home directory, and must set the VIP address as a variable. - -.. warning:: You must perform this on the management server only! - - - -**To create an env_file for local users in the user's home directory:** - -1. Set a variable that includes the VIP IP address: - - .. code-block:: postgres - - $ export VIP_IP=<VIP IP> - -.. note:: If you use Kerberos, replace the ``KRB5_SERVER`` value with the IP address of your Kerberos server. - -2. Do one of the following: - - * For local users: - - .. code-block:: postgres - - $ mkdir /home/$USER/.sqream - -3. Make the following replacements to the **kubespray.settings.sh** file, verifying that the ``KRB5_SERVER`` parameter is set to your server IP: - - - .. code-block:: postgres - - $ cat <<EOF > /home/$USER/.sqream/env_file - SQREAM_K8S_VIP=$VIP_IP - SQREAM_ADMIN_UI_PORT=8080 - SQREAM_DASHBOARD_DATA_COLLECTOR_PORT=8100 - SQREAM_DATABASE_NAME=master - SQREAM_K8S_ADMIN_UI=sqream-admin-ui - SQREAM_K8S_DASHBOARD_DATA_COLLECTOR=dashboard-data-collector - SQREAM_K8S_METADATA=sqream-metadata - SQREAM_K8S_NAMESPACE=sqream - SQREAM_K8S_PICKER=sqream-picker - SQREAM_K8S_PROMETHEUS=prometheus - SQREAM_K8S_REGISTRY_PORT=6000 - SQREAM_METADATA_PORT=3105 - SQREAM_PICKER_PORT=3108 - SQREAM_PROMETHEUS_PORT=9090 - SQREAM_SPOOL_MEMORY_RATIO=0.25 - SQREAM_WORKER_0_PORT=5000 - KRB5CCNAME=FILE:/tmp/tgt - KRB5_SERVER=kdc.sq.com:<server IP>1 - KRB5_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/krb5 - KRB5_CONFIG_FILE=${KRB5_CONFIG_DIR}/krb5.conf - HADOOP_CONFIG_DIR=${ $ SQREAM_MOUNT_DIR}/hadoop - HADOOP_CORE_XML=${HADOOP_CONFIG_DIR}/core-site.xml - HADOOP_HDFS_XML=${HADOOP_CONFIG_DIR}/hdfs-site.xml - EOF - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - - - - - -Creating a Base Kubernetes Namespace ------------------------------------- -After creating an env_file in the user's home directory, you must create a base Kubernetes namespace. - -You can create a Kubernetes namespace by running the following command: - -.. code-block:: postgres - - $ kubectl create namespace sqream-init - -The following is an example of the correct output: - -.. code-block:: postgres - - $ namespace/sqream-init created - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - - -Pushing the **env_file** File to the Kubernetes Configmap --------------------------------------- -After creating a base Kubernetes namespace, you must push the **env_file** to the Kubernetes configmap. You must push the **env_file** file to the Kubernetes **configmap** in the **sqream-init** namespace. - -This is done by running the following command: - -.. code-block:: postgres - - $ kubectl create configmap sqream-init -n sqream-init --from-env-file=/home/$USER/.sqream/env_file - -The following is an example of the correct output: - -.. code-block:: postgres - - $ configmap/sqream-init created - - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - - -Installing the NVIDIA Docker2 Toolkit -------------------------------------- -After pushing the **env_file** file to the Kubernetes configmap, you must install the NVIDIA Docker2 Toolkit. The **NVIDIA Docker2 Toolkit** lets users build and run GPU-accelerated Docker containers, and must be run only on GPU servers. The NVIDIA Docker2 Toolkit includes a container runtime library and utilities that automatically configure containers to leverage NVIDIA GPUs. - - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on CentOS:** - -1. Add the repository for your distribution: - - .. code-block:: postgres - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.repo | \ - $ sudo tee /etc/yum.repos.d/nvidia-docker.repo - -2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: - - .. code-block:: postgres - - $ sudo yum install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Verify that the **nvidia-docker2** package has been installed correctly: - - .. code-block:: postgres - - $ docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi - - The following is an example of the correct output: - - .. code-block:: postgres - - docker run --runtime=nvidia --rm nvidia/cuda:10.1.3-base-centos7 nvidia-smi - Unable to find image 'nvidia/cuda:10.1.3-base-centos7' locally - 10.1.3-base-centos7: Pulling from nvidia/cuda - d519e2592276: Pull complete - d22d2dfcfa9c: Pull complete - b3afe92c540b: Pull complete - 13a10df09dc1: Pull complete - 4f0bc36a7e1d: Pull complete - cd710321007d: Pull complete - Digest: sha256:635629544b2a2be3781246fdddc55cc1a7d8b352e2ef205ba6122b8404a52123 - Status: Downloaded newer image for nvidia/cuda:10.1.3-base-centos7 - Sun Feb 14 13:27:58 2021 - +-----------------------------------------------------------------------------+ - | NVIDIA-SMI 470.82.01 Driver Version: 470.82.01 CUDA Version: 10.1 | - |-------------------------------+----------------------+----------------------+ - | GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC | - | Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. | - | | | MIG M. | - |===============================+======================+======================| - | 0 NVIDIA A100-PCI... On | 00000000:17:00.0 Off | 0 | - | N/A 34C P0 64W / 300W | 79927MiB / 80994MiB | 0% Default | - | | | Disabled | - +-------------------------------+----------------------+----------------------+ - | 1 NVIDIA A100-PCI... On | 00000000:CA:00.0 Off | 0 | - | N/A 35C P0 60W / 300W | 79927MiB / 80994MiB | 0% Default | - | | | Disabled | - +-------------------------------+----------------------+----------------------+ - - +-----------------------------------------------------------------------------+ - | Processes: GPU Memory | - | GPU PID Type Process name Usage | - |=============================================================================| - | No running processes found | - +-----------------------------------------------------------------------------+ - -For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on CentOS, see `NVIDIA Docker Installation - CentOS distributions <https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)#centos-distributions-1>`_ - -Installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To install the NVIDIA Docker2 Toolkit on an x86_64 bit processor on Ubuntu:** - -1. Add the repository for your distribution: - - .. code-block:: postgres - - $ curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | \ - $ sudo apt-key add - - $ distribution=$(. /etc/os-release;echo $ID$VERSION_ID) - $ curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | \ - $ sudo tee /etc/apt/sources.list.d/nvidia-docker.list - $ sudo apt-get update - -2. Install the **nvidia-docker2** package and reload the Docker daemon configuration: - - .. code-block:: postgres - - $ sudo apt-get install nvidia-docker2 - $ sudo pkill -SIGHUP dockerd - -3. Verify that the nvidia-docker2 package has been installed correctly: - - .. code-block:: postgres - - $ docker run --runtime=nvidia --rm nvidia/cuda nvidia-smi - -For more information on installing the NVIDIA Docker2 Toolkit on an x86_64 Bit Processor on Ubuntu, see `NVIDIA Docker Installation - Ubuntu distributions <https://github.com/NVIDIA/nvidia-docker/wiki/Installation-(version-2.0)#ubuntu-distributions-1>`_ - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Modifying the Docker Daemon JSON File for GPU and Compute Nodes -------------------------------------- -After installing the NVIDIA Docker2 toolkit, you must modify the Docker daemon JSON file for GPU and Compute nodes. - -Modifying the Docker Daemon JSON File for GPU Nodes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - -**To modify the Docker daemon JSON file for GPU nodes:** - -1. Enable GPU and set HTTP access to the local Kubernetes Docker registry. - -.. note:: The Docker daemon JSON file must be modified on all GPU nodes. - -.. note:: Contact your IT department for a virtual IP. - -2. Replace the ``VIP address`` with your assigned VIP address. - -:: - -3. Connect as a root user: - - .. code-block:: postgres - - $ sudo -i - -4. Set a variable that includes the VIP address: - - .. code-block:: postgres - - $ export VIP_IP=<VIP IP> - -5. Replace the <VIP IP> with the VIP address:  - - .. code-block:: postgres - - $ cat <<EOF > /etc/docker/daemon.json - $ { - $ "insecure-registries": ["$VIP_IP:6000"], - $ "default-runtime": "nvidia", - $ "runtimes": { - $ "nvidia": { - $ "path": "nvidia-container-runtime", - $ "runtimeArgs": [] - $ } - $ } - $ } - $ EOF - -6. Apply the changes and restart Docker: - - .. code-block:: postgres - - $ systemctl daemon-reload && systemctl restart docker - -7. Exit the root user: - - .. code-block:: postgres - - $ exit - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - - -Modifying the Docker Daemon JSON File for Compute Nodes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -You must follow this procedure only if you have a Compute node. - -**To modify the Docker daemon JSON file for Compute nodes:** - -1. Switch to a root user: - - .. code-block:: postgres - - $ sudo -i - -2. Set a variable that includes a VIP address. - -.. note:: Contact your IT department for a virtual IP. - -3. Replace the ``VIP address`` with your assigned VIP address. - - .. code-block:: postgres - - $ cat <<EOF > /etc/docker/daemon.json - $ { - $ "insecure-registries": ["$VIP_IP:6000"] - $ } - $ EOF - -4. Restart the services: - - .. code-block:: postgres - - $ systemctl daemon-reload && systemctl restart docker - -5. Exit the root user: - - - .. code-block:: postgres - - $ exit - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Installing the Nvidia-device-plugin Daemonset ----------------------------------------------- -After modifying the Docker daemon JSON file for GPU or Compute Nodes, you must installing the Nvidia-device-plugin daemonset. The Nvidia-device-plugin daemonset is only relevant to GPU nodes. - -**To install the Nvidia-device-plugin daemonset:** - -1. Set ``nvidia.com/gpu`` to ``true`` on all GPU nodes: - -.. code-block:: postgres - - $ kubectl label nodes <GPU node name> nvidia.com/gpu=true - -2. Replace the *<GPU node name>* with your GPU node name: - - For a complete list of GPU node names, run the ``kubectl get nodes`` command. - - The following is an example of the correct output: - - .. code-block:: postgres - - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-1 nvidia.com/gpu=true - $ node/eks-rhl-1 labeled - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-2 nvidia.com/gpu=true - $ node/eks-rhl-2 labeled - $ [root@eks-rhl-1 ~]# kubectl label nodes eks-rhl-3 nvidia.com/gpu=true - $ node/eks-rhl-3 labeled - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Creating an Nvidia Device Plugin ----------------------------------------------- -After installing the Nvidia-device-plugin daemonset, you must create an Nvidia-device-plugin. You can create an Nvidia-device-plugin by running the following command - -.. code-block:: postgres - - $ kubectl create -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/1.0.0-beta6/nvidia-device-plugin.yml - -If needed, you can check the status of the Nvidia-device-plugin-daemonset pod status: - -.. code-block:: postgres - - $ kubectl get pods -n kube-system -o wide | grep nvidia-device-plugin - -The following is an example of the correct output: - -.. code-block:: postgres - - $ NAME READY STATUS RESTARTS AGE - $ nvidia-device-plugin-daemonset-fxfct 1/1 Running 0 6h1m - $ nvidia-device-plugin-daemonset-jdvxs 1/1 Running 0 6h1m - $ nvidia-device-plugin-daemonset-xpmsv 1/1 Running 0 6h1m - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Checking GPU Resources Allocatable to GPU Nodes -------------------------------------- -After creating an Nvidia Device Plugin, you must check the GPU resources alloctable to the GPU nodes. Each GPU node has records, such as ``nvidia.com/gpu: <#>``. The ``#`` indicates the number of allocatable, or available, GPUs in each node. - -You can output a description of allocatable resources by running the following command: - -.. code-block:: postgres - - $ kubectl describe node | grep -i -A 7 -B 2 allocatable: - -The following is an example of the correct output: - -.. code-block:: postgres - - $ Allocatable: - $ cpu: 3800m - $ ephemeral-storage: 94999346224 - $ hugepages-1Gi: 0 - $ hugepages-2Mi: 0 - $ memory: 15605496Ki - $ nvidia.com/gpu: 1 - $ pods: 110 - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -Preparing the WatchDog Monitor ------------------------------- -SQream's deployment includes installing two watchdog services. These services monitor Kuberenetes management and the server's storage network. - -You can enable the storage watchdogs by adding entries in the **/etc/hosts** file on each server: - -.. code-block:: postgres - - $ <address 1> k8s-node1.storage - $ <address 2> k8s-node2.storage - $ <address 3> k8s-node3.storage - -The following is an example of the correct syntax: - -.. code-block:: postgres - - $ 10.0.0.1 k8s-node1.storage - $ 10.0.0.2 k8s-node2.storage - $ 10.0.0.3 k8s-node3.storage - -Go back to :ref:`Installing Your Kubernetes Cluster<install_kubernetes_cluster>` - -.. _installing_sqream_software: - -Installing the SQream Software -================================= -Once you've prepared the SQream environment for launching it using Kubernetes, you can begin installing the SQream software. - -The **Installing the SQream Software** section describes the following: - -.. contents:: - :local: - :depth: 1 - - -.. _getting_sqream_package: - -Getting the SQream Package --------------------------------- -The first step in installing the SQream software is getting the SQream package. Please contact the SQream Support team to get the **sqream_k8s-nnn-DBnnn-COnnn-SDnnn-<arch>.tar.gz** tarball file. - -This file includes the following values: - -* **sqream_k8s-<nnn>** - the SQream installer version. -* **DB<nnn>** - the SQreamDB version. -* **CO<nnn>** - the SQream console version. -* **SD<nnn>** - the SQream Acceleration Studio version. -* **arch** - the server architecture. - -You can extract the contents of the tarball by running the following command: - -.. code-block:: postgres - - $ tar -xvf sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64.tar.gz - $ cd sqream_k8s-1.0.15-DB2020.1.0.2-SD0.7.3-x86_64 - $ ls - -Extracting the contents of the tarball file generates a new folder with the same name as the tarball file. - -The following shows the output of the extracted file: - -.. code-block:: postgres - - drwxrwxr-x. 2 sqream sqream 22 Jan 27 11:39 license - lrwxrwxrwx. 1 sqream sqream 49 Jan 27 11:39 sqream -> .sqream/sqream-sql-v2020.3.1_stable.x86_64/sqream - -rwxrwxr-x. 1 sqream sqream 9465 Jan 27 11:39 sqream-install - -rwxrwxr-x. 1 sqream sqream 12444 Jan 27 11:39 sqream-start - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - -Setting Up and Configuring Hadoop --------------------------------- -After getting the SQream package, you can set up and configure Hadoop by configuring the **keytab** and **krb5.conf** files. - -.. note:: You only need to configure the **keytab** and **krb5.conf** files if you use Hadoop with Kerberos authentication. - - -**To set up and configure Hadoop:** - -1. Contact IT for the **keytab** and **krb5.conf** files. - -:: - -2. Copy both files into the respective empty **.hadoop/** and **.krb5/** directories: - -.. code-block:: postgres - - $ cp hdfs.keytab krb5.conf .krb5/ - $ cp core-site.xml hdfs-site.xml .hadoop/ - -The SQream installer automatically copies the above files during the installation process. - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - -Starting a Local Docker Image Registry --------------------------------- -After getting the SQream package, or (optionally) setting up and configuring Hadoop, you must start a local Docker image registry. Because Kubernetes is based on Docker, you must start the local Docker image registry on the host's shared folder. This allows all hosts to pull the SQream Docker images. - -**To start a local Docker image registry:** - -1. Create a Docker registry folder: - - .. code-block:: postgres - - $ mkdir <shared path>/docker-registry/ - -2. Set the ``docker_path`` for the Docker registry folder: - - .. code-block:: postgres - - $ export docker_path=<path> - -3. Apply the **docker-registry** service to the cluster: - - .. code-block:: postgres - - $ cat .k8s/admin/docker_registry.yaml | envsubst | kubectl create -f - - - The following is an example of the correct output: - - .. code-block:: postgres - - namespace/sqream-docker-registry created - configmap/sqream-docker-registry-config created - deployment.apps/sqream-docker-registry created - service/sqream-docker-registry created - -4. Check the pod status of the **docker-registry** service: - - .. code-block:: postgres - - $ kubectl get pods -n sqream-docker-registry - -The following is an example of the correct output: - - .. code-block:: postgres - - NAME READY STATUS RESTARTS AGE - sqream-docker-registry-655889fc57-hmg7h 1/1 Running 0 6h40m - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - -Installing the Kubernetes Dashboard --------------------------------- -After starting a local Docker image registry, you must install the Kubernetes dashboard. The Kubernetes dashboard lets you see the Kubernetes cluster, nodes, services, and pod status. - -**To install the Kubernetes dashboard:** - -1. Apply the **k8s-dashboard** service to the cluster: - - .. code-block:: postgres - - $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0/aio/deploy/recommended.yaml - - The following is an example of the correct output: - - .. code-block:: postgres - - namespace/kubernetes-dashboard created - serviceaccount/kubernetes-dashboard created - service/kubernetes-dashboard created - secret/kubernetes-dashboard-certs created - secret/kubernetes-dashboard-csrf created - secret/kubernetes-dashboard-key-holder created - configmap/kubernetes-dashboard-settings created - role.rbac.authorization.k8s.io/kubernetes-dashboard created - clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created - rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created - clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created - deployment.apps/kubernetes-dashboard created - service/dashboard-metrics-scraper created - deployment.apps/dashboard-metrics-scraper created - -2. Grant the user external access to the Kubernetes dashboard: - - .. code-block:: postgres - - $ cat .k8s/admin/kubernetes-dashboard-svc-metallb.yaml | envsubst | kubectl create -f - - - The following is an example of the correct output: - - .. code-block:: postgres - - service/kubernetes-dashboard-nodeport created - -3. Create the ``cluster-admin-sa.yaml`` file: - - .. code-block:: postgres - - $ kubectl create -f .k8s/admin/cluster-admin-sa.yaml - - The following is an example of the correct output: - - .. code-block:: postgres - - clusterrolebinding.rbac.authorization.k8s.io/cluster-admin-sa-cluster-admin created - -4. Check the pod status of the **K8s-dashboard** service: - - .. code-block:: postgres - - $ kubectl get pods -n kubernetes-dashboard - - The following is an example of the correct output: - - .. code-block:: postgres - - NAME READY STATUS RESTARTS AGE - dashboard-metrics-scraper-6b4884c9d5-n8p57 1/1 Running 0 4m32s - kubernetes-dashboard-7b544877d5-qc8b4 1/1 Running 0 4m32s - -5. Obtain the **k8s-dashboard** access token: - - .. code-block:: postgres - - $ kubectl -n kube-system describe secrets cluster-admin-sa-token - - The following is an example of the correct output: - - .. code-block:: postgres - - Name: cluster-admin-sa-token-rbl9p - Namespace: kube-system - Labels: <none> - Annotations: kubernetes.io/service-account.name: cluster-admin-sa - kubernetes.io/service-account.uid: 81866d6d-8ef3-4805-840d-58618235f68d - - Type: kubernetes.io/service-account-token - - Data - ==== - ca.crt: 1025 bytes - namespace: 11 bytes - token: eyJhbGciOiJSUzI1NiIsImtpZCI6IjRMV09qVzFabjhId09oamQzZGFFNmZBeEFzOHp3SlJOZWdtVm5lVTdtSW8ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJjbHVzdGVyLWFkbWluLXNhLXRva2VuLXJibDlwIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZXJ2aWNlLWFjY291bnQubmFtZSI6ImNsdXN0ZXItYWRtaW4tc2EiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI4MTg2NmQ2ZC04ZWYzLTQ4MDUtODQwZC01ODYxODIzNWY2OGQiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6a3ViZS1zeXN0ZW06Y2x1c3Rlci1hZG1pbi1zYSJ9.mNhp8JMr5y3hQ44QrvRDCMueyjSHSrmqZcoV00ZC7iBzNUqh3n-fB99CvC_GR15ys43jnfsz0tdsTy7VtSc9hm5ENBI-tQ_mwT1Zc7zJrEtgFiA0o_eyfYZOARdhdyFEJg84bzkIxJFPKkBWb4iPWU1Xb7RibuMCjNTarZMZbqzKYfQEcMZWJ5UmfUqp-HahZZR4BNbjSWybs7t6RWdcQZt6sO_rRCDrOeEJlqKKjx4-5jFZB8Du_0kKmnw2YJmmSCEOXrpQCyXIiZJpX08HyDDYfFp8IGzm61arB8HDA9dN_xoWvuz4Cj8klUtTzL9effJJPjHJlZXcEqQc9hE3jw - -6. Navigate to ``https://<VIP address>:5999``. - -:: - -7. Select the **Token** radio button, paste the token from the previous command output, and click **Sign in**. - -The Kubernetes dashboard is displayed. - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - -Installing the SQream Prometheus Package --------------------------------- -After installing the Kubernetes dashboard, you must install the SQream Prometheus package. To properly monitor the host and GPU statistics the **exporter service** must be installed on each Kubernetes cluster node. - -This section describes how to install the following: - -* **node_exporter** - collects host data, such as CPU memory usage. -* **nvidia_exporter** - collects GPU utilization data. - - -.. note:: The steps in this section must be done on **all** cluster nodes. - -To install the **sqream-prometheus** package, you must do the following: - -1. :ref:`Install the exporter service <install_exporter_service>` - -:: - -2. :ref:`Check the exporter service <check_exporter_status>` - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - - -.. _install_exporter_service: - -Installing the Exporter Service -~~~~~~~~~~~~~~~~~~~~~~~~ - -**To install the exporter service:** - -1. Create a user and group that will be used to run the exporter services: - - .. code-block:: console - - $ sudo groupadd --system prometheus && sudo useradd -s /sbin/nologin --system -g prometheus prometheus - -2. Extract the **sqream_exporters_prometheus.0.1.tar.gz** file: - - .. code-block:: console - - $ cd .prometheus - $ tar -xf sqream_exporters_prometheus.0.1.tar.gz - -3. Copy the exporter software files to the **/usr/bin** directory: - - .. code-block:: console - - $ cd sqream_exporters_prometheus.0.1 - $ sudo cp node_exporter/node_exporter /usr/bin/ - $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ - -4. Copy the exporters service file to the **/etc/systemd/system/** directory: - - .. code-block:: console - - $ sudo cp services/node_exporter.service /etc/systemd/system/ - $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ - -5. Set the permission and group of the service files: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /usr/bin/node_exporter - $ sudo chmod u+x /usr/bin/node_exporter - $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter - $ sudo chmod u+x /usr/bin/nvidia_exporter - -6. Reload the services: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -7. Start both services and set them to start when the server is booted up: - - * Node_exporter: - - .. code-block:: console - - $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter - - * Nvidia_exporter: - - .. code-block:: console - - $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter - - - -.. _check_exporter_status: - -Checking the Exporter Status -~~~~~~~~~~~~~~~~~~~~~~~~ -After installing the **exporter** service, you must check its status. - -You can check the exporter status by running the following command: - -.. code-block:: console - - $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter - -Go back to :ref:`Installing Your SQream Software<installing_sqream_software>` - - -.. _running_sqream_install_service: - -Running the Sqream-install Service -================================ -The **Running the Sqream-install Service** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Installing Your License --------------------------------- -After install the SQream Prometheus package, you must install your license. - -**To install your license:** - -1. Copy your license package to the sqream **/license** folder. - -.. note:: You do not need to untar the license package after copying it to the **/license** folder because the installer script does it automatically. - -The following flags are **mandatory** during your first run: - -.. code-block:: console - - $ sudo ./sqream-install -i -k -m <path to sqream cluster> - -.. note:: If you cannot run the script with **sudo**, verify that you have the right permission (**rwx** for the user) on the relevant directories (config, log, volume, and data-in directories). - -Go back to :ref:`Running the SQream_install Service<running_sqream_install_service>`. - -Changing Your Data Ingest Folder --------------------------------- -After installing your license, you must change your data ingest folder. - -You can change your data ingest folder by running the following command: - -.. code-block:: console - - $ sudo ./sqream-install -d /media/nfs/sqream/data_in - -Go back to :ref:`Running the SQream_install Service<running_sqream_install_service>`. - -Checking Your System Settings --------------------------------- -After changing your data ingest folder, you must check your system settings. - -The following command shows you all the variables that your SQream system is running with: - -.. code-block:: console - - $ ./sqream-install -s - -After optionally checking your system settings, you can use the **sqream-start** application to control your Kubernetes cluster. - -Go back to :ref:`Running the SQream_install Service<running_sqream_install_service>`. - -SQream Installation Command Reference --------------------------------- -If needed, you can use the **sqream-install** flag reference for any needed flags by typing: - -.. code-block:: console - - $ ./sqream-install --help - -The following shows the **sqream--install** flag descriptions: - -.. list-table:: - :widths: 22 59 25 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-i** - - Loads all the software from the hidden **.docker** folder. - - Mandatory - * - **-k** - - Loads the license package from the **/license** directory. - - Mandatory - * - **-m** - - Sets the relative path for all SQream folders under the shared filesystem available from all nodes (sqreamdb, config, logs and data_in). No other flags are required if you use this flag (such as c, v, l or d). - - Mandatory - * - **-c** - - Sets the path where to write/read SQream configuration files from. The default is **/etc/sqream/**. - - Optional - * - **-v** - - Shows the location of the SQream cluster. ``v`` creates a cluster if none exist, and mounts it if does. - - Optional - * - **-l** - - Shows the location of the SQream system startup logs. The logs contain startup and Docker logs. The default is **/var/log/sqream/**. - - Optional - * - **-d** - - Shows the folder containing data that you want to import into or copy from SQream. - - Optional - * - **-n** <Namespace> - - Sets the Kubernetes namespace. The default is **sqream**. - - Optional - * - **-N** <Namespace> - - Deletes a specific Kubernetes namespace and sets the factory default namespace (sqream). - - Optional - * - **-f** - - Overwrite existing folders and all files located in mounted directories. - - Optional - * - **-r** - - Resets the system configuration. This flag is run without any other variables. - - Optional - * - **-s** - - Shows the system settings. - - Optional - * - **-e** - - Sets the Kubernetes cluster's virtual IP address. - - Optional - * - **-h** - - Help, shows all available flags. - - Optional - -Go back to :ref:`Running the SQream_install Service<running_sqream_install_service>`. - -Controlling Your Kubernetes Cluster Using SQream Flags --------------------------------- -You can control your Kubernetes cluster using SQream flags. - -The following command shows you the available Kubernetes cluster control options: - -.. code-block:: console - - $ ./sqream-start -h - -The following describes the **sqream-start** flags: - -.. list-table:: - :widths: 22 59 25 - :header-rows: 1 - - * - Flag - - Function - - Note - * - **-s** - - Starts the sqream services, starting metadata, server picker, and workers. The number of workers started is based on the number of available GPU’s. - - Mandatory - * - **-p** - - Sets specific ports to the workers services. You must enter the starting port for the sqream-start application to allocate it based on the number of workers. - - - * - **-j** - - Uses an external .json configuration file. The file must be located in the **configuration** directory. - - The workers must each be started individually. - * - **-m** - - Allocates worker spool memory. - - The workers must each be started individually. - * - **-a** - - Starts the SQream Administration dashboard and specifies the listening port. - - - * - **-d** - - Deletes all running SQream services. - - - * - **-h** - - Shows all available flags. - - Help - -Go back to :ref:`Running the SQream_install Service<running_sqream_install_service>`. - -.. _using_sqream_start_commands: - -Using the sqream-start Commands -======================= -In addition to controlling your Kubernetes cluster using SQream flags, you can control it using **sqream-start** commands. - -The **Using the sqream-start Commands** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Starting Your SQream Services ------------------------- -You can run the **sqream-start** command with the **-s** flag to start SQream services on all available GPU's: - -.. code-block:: console - - $ sudo ./sqream-start -s - -This command starts the SQream metadata, server picker, and sqream workers on all available GPU’s in the cluster. - -The following is an example of the correct output: - -.. code-block:: console - - ./sqream-start -s - Initializing network watchdogs on 3 hosts... - Network watchdogs are up and running - - Initializing 3 worker data collectors ... - Worker data collectors are up and running - - Starting Prometheus ... - Prometheus is available at 192.168.5.100:9090 - - Starting SQream master ... - SQream master is up and running - - Starting up 3 SQream workers ... - All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 - All SQream workers are up and running, SQream-DB is available at 192.168.5.100:3108 - - -Go back to :ref:`Using the SQream-start Commands<using_sqream_start_commands>`. - -Starting Your SQream Services in Split Mode ------------------------- -Starting SQream services in split mode refers to running multiple SQream workers on a single GPU. You can do this by running the **sqream-start** command with the **-s** and **-z** flags. In addition, you can define the amount of hosts to run the multiple workers on. In the example below, the command defines to run the multiple workers on three hosts. - -**To start SQream services in split mode:** - -1. Run the following command: - -.. code-block:: console - - $ ./sqream-start -s -z 3 - -This command starts the SQream metadata, server picker, and sqream workers on a single GPU for three hosts: - -The following is an example of the correct output: - -.. code-block:: console - - Initializing network watchdogs on 3 hosts... - Network watchdogs are up and running - - Initializing 3 worker data collectors ... - Worker data collectors are up and running - - Starting Prometheus ... - Prometheus is available at 192.168.5.101:9090 - - Starting SQream master ... - SQream master is up and running - - Starting up 9 SQream workers over <#> available GPUs ... - All SQream workers are up and running, SQream-DB is available at 192.168.5.101:3108 - -2. Verify all pods are properly running in k8s cluster (**STATUS** column): - -.. code-block:: console - - kubectl -n sqream get pods - - NAME READY STATUS RESTARTS AGE - prometheus-bcf877867-kxhld 1/1 Running 0 106s - sqream-metadata-fbcbc989f-6zlkx 1/1 Running 0 103s - sqream-picker-64b8c57ff5-ndfr9 1/1 Running 2 102s - sqream-split-workers-0-1-2-6bdbfbbb86-ml7kn 1/1 Running 0 57s - sqream-split-workers-3-4-5-5cb49d49d7-596n4 1/1 Running 0 57s - sqream-split-workers-6-7-8-6d598f4b68-2n9z5 1/1 Running 0 56s - sqream-workers-start-xj75g 1/1 Running 0 58s - watchdog-network-management-6dnfh 1/1 Running 0 115s - watchdog-network-management-tfd46 1/1 Running 0 115s - watchdog-network-management-xct4d 1/1 Running 0 115s - watchdog-network-storage-lr6v4 1/1 Running 0 116s - watchdog-network-storage-s29h7 1/1 Running 0 116s - watchdog-network-storage-sx9mw 1/1 Running 0 116s - worker-data-collector-62rxs 0/1 Init:0/1 0 54s - worker-data-collector-n8jsv 0/1 Init:0/1 0 55s - worker-data-collector-zp8vf 0/1 Init:0/1 0 54s - -Go back to :ref:`Using the SQream-start Commands<using_sqream_start_commands>`. - -Starting the Sqream Studio UI --------------------------------- -You can run the following command the to start the SQream Studio UI (Editor and Dashboard): - -.. code-block:: console - - $ ./sqream-start -a - -The following is an example of the correct output: - -.. code-block:: console - - $ ./sqream-start -a - Please enter USERNAME: - sqream - Please enter PASSWORD: - ****** - Please enter port value or press ENTER to keep 8080: - - Starting up SQream Admin UI... - SQream admin ui is available at 192.168.5.100:8080 - -Go back to :ref:`Using the SQream-start Commands<using_sqream_start_commands>`. - -Stopping the SQream Services --------------------------------- -You can run the following command to stop all SQream services: - -.. code-block:: console - - $ ./sqream-start -d - -The following is an example of the correct output: - -.. code-block:: console - - $ ./sqream-start -d - $ Cleaning all SQream services in sqream namespace ... - $ All SQream service removed from sqream namespace - -Go back to :ref:`Using the SQream-start Commands<using_sqream_start_commands>`. - -Advanced sqream-start Commands --------------------------------- -Controlling Your SQream Spool Size -~~~~~~~~~~~~~~~~~~~~~~~~ -If you do not specify the SQream spool size, the console automatically distributes the available RAM between all running workers. - -You can define a specific spool size by running the following command: - -.. code-block:: console - - $ ./sqream-start -s -m 4 - -Using a Custom .json File -~~~~~~~~~~~~~~~~~~~~~~~~ -You have the option of using your own .json file for your own custom configurations. Your .json file must be placed within the path mounted in the installation. SQream recommends placing your .json file in the **configuration** folder. - -The SQream console does not validate the integrity of external .json files. - -You can use the following command (using the ``j`` flag) to set the full path of your .json file to the configuration file: - -.. code-block:: console - - $ ./sqream-start -s -f <full path>.json - -This command starts one worker with an external configuration file. - -.. note:: The configuration file must be available in the shared configuration folder. - - -Checking the Status of the SQream Services -~~~~~~~~~~~~~~~~~~~~~~~~ -You can show all running SQream services by running the following command: - -.. code-block:: console - - $ kubectl get pods -n <namespace> -o wide - -This command shows all running services in the cluster and which nodes they are running in. - -Go back to :ref:`Using the SQream-start Commands<using_sqream_start_commands>`. - -Upgrading Your SQream Version -================================ -The **Upgrading Your SQream Version** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Before Upgrading Your System ----------------------------- -Before upgrading your system you must do the following: - -1. Contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for a new SQream package tarball file. - -:: - -2. Set a maintenance window. - - -.. note:: You must stop the system while upgrading it. - - -Upgrading Your System ----------------------------- -After completing the steps in **Before Upgrading Your System** above, you can upgrade your system. - -**To upgrade your system:** - -1. Extract the contents of the tarball file that you received from SQream support. Make sure to extract the contents to the same directory as in :ref:`getting_sqream_package` and for the same user: - - .. code-block:: console - - $ tar -xvf sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - $ cd sqream_installer-2.0.5-DB2019.2.1-CO1.6.3-ED3.0.0-x86_64/ - -2. Start the upgrade process run the following command: - - .. code-block:: console - - $ ./sqream-install -i - -The upgrade process checks if the SQream services are running and will prompt you to stop them. - -3. Do one of the following: - - * Stop the upgrade by writing ``No``. - * Continue the upgrade by writing ``Yes``. - -If you continue upgrading, all running SQream workers (master and editor) are stopped. When all services have been stopped, the new version is loaded. - - -.. note:: SQream periodically upgrades its metadata structure. If an upgrade version includes an upgraded metadata service, an approval request message is displayed. This approval is required to finish the upgrade process. Because SQream supports only specific metadata versions, all SQream services must be upgraded at the same time. - - -4. When SQream has successfully upgraded, load the SQream console and restart your services. - -For questions, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. From dea0f0bce05253748ea9bd0055566a4bf3c2928c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 1 Aug 2023 11:45:10 +0300 Subject: [PATCH 0707/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 67 +++++++++++++++++------- 1 file changed, 48 insertions(+), 19 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 2725fb631..6b086c50c 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -12,6 +12,8 @@ Each data type has its companion ``ARRAY`` type, such as ``INT[]`` for integers You may use the ``ARRAY`` data type with all :ref:`SQreamDB connectors <connecting_to_sqream>`, except for ODBC since the ODBC protocol does not support ``ARRAY``. +The maximum size of an ``ARRAY``, indicating the number of elements it can hold, is 65535. You have the option to specify the size of an ``ARRAY``, providing a maximum allowed size, while each row can have a different number of elements up to the specified maximum. If the ``ARRAY`` size is not specified, the maximum size is assumed. + .. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. Syntax @@ -23,12 +25,8 @@ Defining an ``ARRAY`` is done by appending the ``[]`` notation to a supported da CREATE TABLE <table_name> (<column1> TEXT[], <column2> INT[]) - INSERT INTO TABLE <table_name> VALUES ARRAY[<'a','b','c'>], ARRAY[<1,2,NULL>] - -Size -==== + INSERT INTO TABLE <table_name> VALUES (ARRAY['a','b','c'], ARRAY[1,2,NULL]) -The maximum size of an ``ARRAY``, indicating the number of elements it can hold, is 65535. You have the option to specify the size of an ``ARRAY``, providing a maximum allowed size, while each row can have a different number of elements up to the specified maximum. If the ``ARRAY`` size is not specified, the maximum size is assumed. Supported Operators =================== @@ -51,10 +49,11 @@ Supported Operators - ``SELECT (<column_name>[2]) FROM <table_name>`` returns the third element of the specified column * - ``UNNEST`` - Converts the arrayed elements within a single row into a set of rows - - ``SELECT UNNEST (<column_name>) FROM <table_name>`` + - ``SELECT UNNEST(<column_name>) FROM <table_name>`` * - Concatenate ``||`` - Converts arrayed elements into one string - - ``SELECT (<column_name>) || (<column2_name>) FROM <table_name>`` + - * ``SELECT (<column_name>) || (<column2_name>) FROM <table_name>`` + * ``SELECT (<column_name>) || ARRAY[1,2,3] FROM <table_name>`` * - ``array_length`` - Returns the number of arrayed elements within the specified column - ``SELECT array_length(<column_name>) FROM <table_name>`` @@ -69,11 +68,33 @@ Supported Operators - ``SELECT array_replace(<column_name>,<value_to_replace>,<replacing_value>) FROM <table_name>;`` * - Limiting number of arrayed elements - You may limit the number of arrayed elements within an ``ARRAY`` - - ``CREATE TABLE <table_name> (<column1> TEXT[]);`` + - Limiting the number of arrayed elements to 4: ``CREATE TABLE <table_name> (<column1> TEXT[4]);`` * - Creating different column types - You may create a table that has arrayed columns and non-arrayed columns - ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` - + * - Compression + - You may follow SQreamDB :ref:`compression guide <compression>` for compression types and methods + - ``CREATE TABLE t (comp_dict INT[] CHECK('CS "dict"');`` + * - Aggregation + - The ``array_agg()`` function arrays groups created using the ``GROUP BY`` clause + - ``CREATE TABLE t2 (x INT, y INT);`` + + ``SELECT x, array_agg(y) FROM t2 GROUP BY x;`` + * - Sorting + - ``TEXT[]`` elements are considered together as a single text, and comparisons are made based on their lexicographic order. In contrast, for arrays of non-TEXT data types, comparisons are performed on the individual elements of the arrays + - ``CREATE TABLE t (x TEXT[]);`` + + ``INSERT INTO t VALUES (ARRAY['1']),(ARRAY['1','22']),(ARRAY['1','3']);`` + ``SELECT x FROM t ORDER BY x;`` + + Output: + + ['1'] + + ['1','22'] + + ['1','3'] + Examples ======== @@ -120,8 +141,8 @@ Updating table values: ---------------------+------------------+----------- ["A","1","2","3"] | ["4","5","6"] | [7,8,9,10] -JSON Files ----------- +Ingesting Arrayed Data from External Files +------------------------------------------ Consider the following JSON file to be ingested into SQreamDB: @@ -167,41 +188,49 @@ Casting Limitations ------------------- Numeric -~~~~~~~ +^^^^^^^ Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and ``BOOL``, must explicitly be cast. .. code-block:: sql CREATE OR REPLACE TABLE my_array (clmn1 tinyint []); - SELECT array_replace(clmn1 , 4::tinyint, 5::tinyint) from my_array; + SELECT array_replace(clmn1 , 4::tinyint, 5::tinyint) FROM my_array; CREATE OR REPLACE TABLE my_array (clmn1 bool []); - SELECT array_replace(clmn1 , 0::bool, 1::bool) from my_array; + SELECT array_replace(clmn1 , 0::bool, 1::bool) FROM my_array; TEXT -~~~~ +^^^^ Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not supported. +.. code-block:: sql + + + CREATE TABLE t_text (xtext TEXT[]); + CREATE TABLE t_int (xint INT[]); + INSERT INTO t_int VALUES (array[1,2,3]); + INSERT INTO t_text SELECT xint::TEXT[] FROM t_int; + Function Limitations -------------------- || (Concatenate) -~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^ Using the ``||`` (Concatenate) function with two different data types requires explicit casting. .. code-block:: sql - SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) from my_array; + SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) FROM my_array; UNNEST -~~~~~~ +^^^^^^ It is possible to use the ``UNNEST`` operator within a statement only once. Window -~~~~~~ +^^^^^^ Window functions are not supported. \ No newline at end of file From b01be3c9b74103945f5b76d2cc03c42361656ded Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:58:35 +0300 Subject: [PATCH 0708/1892] Update logging.rst --- operational_guides/logging.rst | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 03950784d..90499e971 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -1,11 +1,11 @@ .. _logging: -*********************** +******* Logging -*********************** +******* Locating the Log Files -========================== +====================== The :ref:`storage cluster<storage_cluster>` contains a ``logs`` directory. Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. @@ -24,7 +24,7 @@ The worker logs contain information messages, warnings, and errors pertaining to * Statement execution statistics Log Structure and Contents ---------------------------------- +-------------------------- The log is a CSV, with several fields. @@ -192,7 +192,7 @@ The log is a CSV, with several fields. - ``"Server shutdown"`` Log-Naming ---------------------------- +---------- Log file name syntax @@ -211,10 +211,10 @@ See the :ref:`log_rotation` below for information about controlling this setting Log Control and Maintenance -====================================== +=========================== Changing Log Verbosity --------------------------- +---------------------- A few configuration settings alter the verbosity of the logs: @@ -240,7 +240,7 @@ A few configuration settings alter the verbosity of the logs: .. _log_rotation: Changing Log Rotation ------------------------ +--------------------- A few configuration settings alter the log rotation policy: @@ -253,7 +253,7 @@ A few configuration settings alter the log rotation policy: - Default - Values * - ``useLogMaxFileSize`` - - Rotate log files once they reach a certain file size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. + - Rotate log files once they reach a certain file size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. When ``false`` set the ``logFileRotateTimeFrequency`` accordingly. - ``false`` - ``false`` or ``true``. * - ``logMaxFileSizeMB`` @@ -268,7 +268,7 @@ A few configuration settings alter the log rotation policy: .. _collecting_logs2: Collecting Logs from Your Cluster -==================================== +================================= Collecting logs from your cluster can be as simple as creating an archive from the ``logs`` subdirectory: ``tar -czvf logs.tgz *.log``. @@ -290,7 +290,7 @@ SQL Syntax Command Line Utility --------------------------- +-------------------- If you cannot access SQream DB for any reason, you can also use a command line toolto collect the same information: @@ -300,7 +300,7 @@ If you cannot access SQream DB for any reason, you can also use a command line t Parameters ---------------- +---------- .. list-table:: :widths: auto @@ -318,7 +318,7 @@ Parameters * ``'db_and_log'`` - Collect both log files and metadata database Example ------------------ +------- Write an archive to ``/home/rhendricks``, containing log files: @@ -343,10 +343,10 @@ Using the command line utility: Troubleshooting with Logs -=============================== +========================= Loading Logs with Foreign Tables ---------------------------------------- +-------------------------------- Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. @@ -379,13 +379,13 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas ) ; -For more information, see `Loading Logs with Foreign Tables <https://docs.sqream.com/en/latest/reference/sql/sql_statements/dml_commands/copy_from.html>`_. +For more information, see :ref:`Loading Logs with Foreign Tables <copy_from>`. Counting Message Types ------------------------------- +---------------------- .. code-block:: psql @@ -411,7 +411,7 @@ Counting Message Types 1010 | 5 Finding Fatal Errors ----------------------- +-------------------- .. code-block:: psql @@ -423,7 +423,7 @@ Finding Fatal Errors Internal Runtime Error,open cluster metadata database:IO error: lock /home/rhendricks/sqream_storage/LOCK: Resource temporarily unavailable Countng Error Events Within a Certain Timeframe ---------------------------------------------------- +----------------------------------------------- .. code-block:: psql @@ -442,7 +442,7 @@ Countng Error Events Within a Certain Timeframe .. _tracing_errors: Tracing Errors to Find Offending Statements -------------------------------------------------- +------------------------------------------- If we know an error occured, but don't know which statement caused it, we can find it using the connection ID and statement ID. From 22f7c0735dd117311aa04e4c78303727dbb44638 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 1 Aug 2023 13:10:53 +0300 Subject: [PATCH 0709/1892] Update current_method_showing_all_flags_in_the_catalog_table.rst --- .../current_method_showing_all_flags_in_the_catalog_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst index 235d2ac72..bdcbb39ff 100644 --- a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -10,7 +10,7 @@ The following is the correct syntax for a catalog table query: .. code-block:: sql - SELECT * FROM sqream_catalog.settings; + SELECT * FROM sqream_catalog.parameters; The following is an example of a catalog table query: From 3d7104bb391a803f0ee3f24007f19f330bef8d72 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 14:28:36 +0300 Subject: [PATCH 0710/1892] Update index.rst --- index.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/index.rst b/index.rst index d09ca5bdd..6a174af67 100644 --- a/index.rst +++ b/index.rst @@ -49,25 +49,13 @@ SQream DB is a columnar analytic SQL database management system. SQream DB suppo .. only:: html - .. tip:: - Want to read this offline? - `Download the documentation as a single PDF <https://docs.sqream.com/_/downloads/en/latest/pdf/>`_ . - .. only:: pdf or latex - - .. tip:: This documentation is available online at https://docs.sqream.com/ - .. rubric:: Need help? If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/>`_ for additional support. -.. rubric:: Looking for older versions? - - -If you're looking for an older version of the documentation, go to http://previous.sqream.com . - .. toctree:: :caption: Contents: :glob: From 03821fb7bb2caf80813f4e3a8ed2343771b6d254 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 14:47:01 +0300 Subject: [PATCH 0711/1892] Update sas_viya.rst --- connecting_to_sqream/client_platforms/sas_viya.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index 9815e122b..d84e9a038 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -82,7 +82,7 @@ This section describes how to use SAS Viya Visual Analytics. **To use SAS Viya Visual Analytics:** -#. Log in to `SAS Viya Visual Analytics <http://192.168.4.63/SASLogon/login>`_ using your credentials: +#. Log in to SAS Viya Visual Analytics using your credentials: :: From 91b7975a487c5f1bc24b40fa4f237d5465fa99f7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 15:03:29 +0300 Subject: [PATCH 0712/1892] Update microstrategy.rst --- connecting_to_sqream/client_platforms/microstrategy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index ff8a1f306..57afb861e 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -123,7 +123,7 @@ Connecting a Data Source odbc:Driver={SqreamODBCDriver};DSN={SQreamDB ODBC};Server=<Host>;Port=<Port>;Database=<database name>;User=<username>;Password=<password>;Cluster=<boolean>; - For more information about the available **connection parameters** and other examples, see `Connection Parameters <https://docs.sqream.com/en/latest/guides/client_drivers/jdbc/index.html#connection-parameters>`_. + For more information about the available **connection parameters** and other examples, see `Connection Parameters <java_jdbc>`. 7. In the **User** and **Password** fields, fill out your user name and password. From 6982a3a3358ce9e6c44d2c1c831cbe723a630b40 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 15:06:35 +0300 Subject: [PATCH 0713/1892] Update microstrategy.rst --- connecting_to_sqream/client_platforms/microstrategy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index 57afb861e..8947eb0e6 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -123,7 +123,7 @@ Connecting a Data Source odbc:Driver={SqreamODBCDriver};DSN={SQreamDB ODBC};Server=<Host>;Port=<Port>;Database=<database name>;User=<username>;Password=<password>;Cluster=<boolean>; - For more information about the available **connection parameters** and other examples, see `Connection Parameters <java_jdbc>`. + For more information about the available **connection parameters** and other examples, see :ref:`Connection Parameters <java_jdbc>`. 7. In the **User** and **Password** fields, fill out your user name and password. From c7800878e41ed68ec54dc4ff856e8464c1a5610b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 15:16:39 +0300 Subject: [PATCH 0714/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index e4895b3bc..2ce7c9db3 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -42,7 +42,7 @@ Other distributions may also work, but are not officially supported by SQream. Getting the ODBC driver ======================= -The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or contact your SQream account manager to get the driver. +The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQream account manager to get the driver. The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: From 3f68a54b7a9765754abfd3813fb20283688c9030 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 2 Aug 2023 16:50:33 +0300 Subject: [PATCH 0715/1892] Update power_bi.rst --- .../client_platforms/power_bi.rst | 45 ++++++------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index a299e9e4a..ec95ab7f3 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -49,46 +49,43 @@ Installing Power BI Desktop **To install Power BI Desktop:** -1. Download `Power BI Desktop 64x <https://powerbi.microsoft.com/en-us/downloads/>`_. +#. Download `Power BI Desktop 64x <https://powerbi.microsoft.com/en-us/downloads/>`_. :: -2. Download and configure your ODBC driver. +#. Download and configure your ODBC driver. - For more information about configuring your ODBC driver, see `ODBC <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/odbc/index.html>`_. + For information about downloading and configuring your ODBC driver, see :ref:`ODBC <odbc>` or contact `SQream Support <https://sqream.atlassian.net/servicedesk/>`_. -3. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. +#. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. :: - -4. In the **Power BI Desktop** folder, create a folder called **Custom Connectors**. - -5. From the Client Drivers page, download the **PowerQuery.mez** file. +#. From the Client Drivers page, download the **PowerQuery.mez** file. :: -5. Save the PowerQuery.mez file in the **Custom Connectors** folder you created in Step 3. +#. Save the PowerQuery.mez file in the **Custom Connectors** folder you created in Step 3. :: -6. Open the Power BI application. +#. Open the Power BI application. :: -7. Navigate to **File** > **Options and Settings** > **Option** > **Security** > **Data Extensions**, and select **(Not Recommended) Allow any extension to load without validation or warning**. +#. Navigate to **File** > **Options and Settings** > **Option** > **Security** > **Data Extensions**, and select **(Not Recommended) Allow any extension to load without validation or warning**. :: -8. Restart the Power BI Desktop application. +#. Restart the Power BI Desktop application. :: -9. From the **Get Data** menu, select **SQream**. +#. From the **Get Data** menu, select **SQream**. :: -10. Click **Connect** and provide the information shown in the following table: +#. Click **Connect** and provide the information shown in the following table: .. list-table:: :widths: 6 31 @@ -107,15 +104,15 @@ Installing Power BI Desktop * - Passwords - Provide a password for your user. -11. Under **Data Connectivity mode**, select **DirectQuery mode**. +#. Under **Data Connectivity mode**, select **DirectQuery mode**. :: -12. Click **Connect**. +#. Click **Connect**. :: -13. Provide your user name and password and click **Connect**. +#. Provide your user name and password and click **Connect**. Best Practices for Power BI --------------------------- @@ -132,18 +129,4 @@ SQream recommends using Power BI in the following ways for acquiring the best pe * Creating a unified view using **PowerQuery** to connect different data sources into a single dashboard. -Supported SQream Driver Versions --------------------------------- - -SQream supports the following SQream driver versions: - -* The **PowerQuery Connector** is an additional layer on top of the ODBC. - - :: - -* SQream Driver Installation (ODBC v4.1.1) - Contact your administrator for the link to download ODBC v4.1.1. - -Related Information -------------------- -For more information, see the `Glossary <https://docs.sqream.com/en/v2022.1/glossary.html>`_. \ No newline at end of file From 5cf214940d7ab23c146474e036a65b3bb6e5e599 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 3 Aug 2023 08:09:38 +0300 Subject: [PATCH 0716/1892] Update glossary.rst --- glossary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glossary.rst b/glossary.rst index f4634d712..818cf3cf0 100644 --- a/glossary.rst +++ b/glossary.rst @@ -27,7 +27,7 @@ The following table shows the **Glossary** descriptions: +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Node | A machine used to run SQream workers. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -| Role | A group or a user. For more information see :ref:`SQream Studio <creating_assigning_and_managing_roles_and_permissions>`. | +| Role | A group or a user. For more information see :ref:`SQream Studio <creating_assigning_and_managing_roles_and_permissions>`. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Storage cluster | The directory where SQream stores data. | +-----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ From 313d1ce1b4d4fdda948967164e3811a445385a0e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:06:55 +0300 Subject: [PATCH 0717/1892] Create rename_schema.rst --- .../ddl_commands/rename_schema.rst | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 reference/sql/sql_statements/ddl_commands/rename_schema.rst diff --git a/reference/sql/sql_statements/ddl_commands/rename_schema.rst b/reference/sql/sql_statements/ddl_commands/rename_schema.rst new file mode 100644 index 000000000..6ddcf7979 --- /dev/null +++ b/reference/sql/sql_statements/ddl_commands/rename_schema.rst @@ -0,0 +1,55 @@ +.. _rename_schema: + +************* +RENAME SCHEMA +************* + +``RENAME SCHEMA`` can be used to rename a schema. + +.. warning:: Renaming a schema can void existing views that use this schema. See more about :ref:`recompiling views <recompile_view>`. + +Permissions +=========== + +The role must have the ``DDL`` permission at the database or table level. + +Syntax +====== + +.. code-block:: postgres + + alter_schema_rename_schema_statement ::= + ALTER SCHEMA [database_name.]current_name RENAME TO new_name + ; + + current_name ::= identifier + + database_name ::= identifier + + new_name ::= identifier + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The database name for the schema. Defaults to ``master`` if not specified. + * - ``current_name`` + - The schema name to apply the change to. + * - ``new_name`` + - The new schema name. + +Examples +======== + + +.. code-block:: postgres + + ALTER SCHEMA master.staging RENAME TO staging_new; + + From c1ec5c142a9b539ee21ba40cda9453c2a493d84a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:08:17 +0300 Subject: [PATCH 0718/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index f8c6c4332..47a26b0a9 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -64,6 +64,9 @@ The following table shows the Data Definition commands: - Rename a column * - :ref:`RENAME_TABLE<rename_table>` - Rename a table + * - :ref:`RENAME_SCHEMA<rename_schema>` + - Rename a schema + Data Manipulation Commands (DML) @@ -211,4 +214,4 @@ The following table shows the Access Control commands: * - :ref:`revoke` - Revoke permissions from a role * - :ref:`rename_role` - - Rename a role \ No newline at end of file + - Rename a role From fc0db1cfe0cad3d46fcd57104f32ed75c7a39253 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:13:57 +0300 Subject: [PATCH 0719/1892] Update create_schema.rst --- .../ddl_commands/create_schema.rst | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_schema.rst b/reference/sql/sql_statements/ddl_commands/create_schema.rst index aefa64b4f..cba68bc73 100644 --- a/reference/sql/sql_statements/ddl_commands/create_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/create_schema.rst @@ -1,8 +1,9 @@ .. _create_schema: -***************** +************* CREATE SCHEMA -***************** +************* + The **CREATE SCHEMA** page describes the following: @@ -11,7 +12,7 @@ The **CREATE SCHEMA** page describes the following: :depth: 2 Overview -============ +======== ``CREATE SCHEMA`` creates a new schema in an existing database. A schema is a virtual space for storing tables. @@ -25,15 +26,16 @@ The **CREATE SCHEMA** statement can be used to query tables from different schem select <schema_name>.table_name.column_name from <schema_name>.table_name -See also: :ref:`drop_schema`, :ref:`alter_default_schema`. +See also: :ref:`drop_schema`, :ref:`alter_default_schema`, :ref:`rename_schema`. Permissions -============= +=========== The role must have the ``CREATE`` permission at the database level. Syntax -========== +====== + The following example shows the correct syntax for creating a schema: .. code-block:: postgres @@ -46,7 +48,8 @@ The following example shows the correct syntax for creating a schema: Parameters -============ +========== + The following table shows the ``schema_name`` parameters: .. list-table:: @@ -59,7 +62,8 @@ The following table shows the ``schema_name`` parameters: - The name of the schema to create. Examples -=========== +======== + This section includes the following examples: .. contents:: @@ -68,7 +72,8 @@ This section includes the following examples: Creating a Schema --------------------- +----------------- + The following example shows an example of the syntax for creating a schema: .. code-block:: postgres @@ -80,7 +85,8 @@ The following example shows an example of the syntax for creating a schema: SELECT * FROM staging.users; Altering the Default Schema for a Role ------------------------------------------ +-------------------------------------- + The following example shows an example of the syntax for altering the default schema for a role: .. code-block:: postgres From b4b6b8be905a15572a2755296939ab996a610aa2 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 12:19:21 +0300 Subject: [PATCH 0720/1892] Update rename_schema.rst --- reference/sql/sql_statements/ddl_commands/rename_schema.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/rename_schema.rst b/reference/sql/sql_statements/ddl_commands/rename_schema.rst index 6ddcf7979..0024d59c3 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_schema.rst @@ -4,14 +4,14 @@ RENAME SCHEMA ************* -``RENAME SCHEMA`` can be used to rename a schema. +Renaming schemas is mainly used for improving the clarity and organization of a database by giving schemas more meaningful or concise names. .. warning:: Renaming a schema can void existing views that use this schema. See more about :ref:`recompiling views <recompile_view>`. Permissions =========== -The role must have the ``DDL`` permission at the database or table level. +The role must have the ``DDL`` permission at the database level. Syntax ====== @@ -47,7 +47,6 @@ Parameters Examples ======== - .. code-block:: postgres ALTER SCHEMA master.staging RENAME TO staging_new; From c096eb0bbccf9fd22c3b0bcdb09f8ba5697af8db Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:07:49 +0300 Subject: [PATCH 0721/1892] Update alter_default_schema.rst --- .../sql/sql_statements/ddl_commands/alter_default_schema.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst index bca483060..8c5722f48 100644 --- a/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/alter_default_schema.rst @@ -6,7 +6,7 @@ ALTER DEFAULT SCHEMA The ``ALTER DEFAULT SCHEMA`` command can be used to change a role's default schema. The default schema in SQream is ``public``. -For more information, see :ref:`create_schema` and :ref:`drop_schema`. +For more information, see :ref:`create_schema`, :ref:`drop_schema`, and :ref:`rename_schema`. From ad5ddbc2634d8617220454eb074c3fde6e41838b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:11:59 +0300 Subject: [PATCH 0722/1892] Update drop_schema.rst --- reference/sql/sql_statements/ddl_commands/drop_schema.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/drop_schema.rst b/reference/sql/sql_statements/ddl_commands/drop_schema.rst index 0f2dfd454..79597b49a 100644 --- a/reference/sql/sql_statements/ddl_commands/drop_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/drop_schema.rst @@ -10,7 +10,7 @@ The schema has to be empty before removal. SQream DB does not support dropping a schema with objects. -See also: :ref:`create_schema`, :ref:`alter_default_schema`. +See also: :ref:`create_schema`, :ref:`alter_default_schema`, and :ref:`rename_schema`. Permissions ============= @@ -74,4 +74,4 @@ To drop the schema, drop the schema's tables first, and then drop the schema: t=> DROP TABLE test.bar; executed t=> DROP SCHEMA test; - executed \ No newline at end of file + executed From 6cdb2f7f781c2104834abfd75f9eaa034ae266ab Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 6 Aug 2023 15:13:45 +0300 Subject: [PATCH 0723/1892] Update sql_feature_support.rst --- reference/sql_feature_support.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 0997b72bb..70c101dae 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -1,8 +1,8 @@ .. _sql_feature_support: -************************* +********************* SQL Feature Checklist -************************* +********************* To understand which ANSI SQL and other SQL features SQream DB supports, use the tables below. @@ -12,7 +12,7 @@ To understand which ANSI SQL and other SQL features SQream DB supports, use the Data Types and Values -========================= +===================== Read more about :ref:`Yes data types<data_types>`. @@ -65,7 +65,7 @@ Read more about :ref:`Yes data types<data_types>`. Constraints -=============== +=========== .. list-table:: Constraints :widths: auto @@ -86,15 +86,15 @@ Constraints Transactions -================ +============ SQream DB treats each statement as an auto-commit transaction. Each transaction is isolated from other transactions with serializable isolation. -If a statement fails, the entire transaction is cancelled and rolled back. The database is unchanged. +If a statement fails, the entire transaction is canceled and rolled back. The database is unchanged. Indexes -============ +======= SQream DB has a range-index collected on all columns as part of the metadata collection process. @@ -143,8 +143,8 @@ Schema Changes - No - * - Rename schema - - No - - + - Yes + - :ref:`rename_schema` * - Drop schema - Yes - :ref:`drop_schema` From c2b8c99e18c7b343bdf12f25a981a625049df1b8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 7 Aug 2023 09:27:54 +0300 Subject: [PATCH 0724/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 6b086c50c..a8c3d3cc9 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -148,7 +148,7 @@ Consider the following JSON file to be ingested into SQreamDB: .. code-block:: json - { "name":"Avery Bradley", "age":25, "position":"PG", {years_in_nba":[2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} + { "name":"Avery Bradley", "age":25, "position":"PG"}, {years_in_nba":[2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} { "name":"Jae Crowder", "age":25, "position":"PG" }, {years_in_nba":[2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} { "name":"John Holland", "age":27, "position":"SG" }, {years_in_nba":[2017, 2018]"} From b2f4562ac1955fe3e7d5bcc777c077364b51ac45 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 7 Aug 2023 11:08:35 +0300 Subject: [PATCH 0725/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index a8c3d3cc9..63194ef2b 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -148,9 +148,10 @@ Consider the following JSON file to be ingested into SQreamDB: .. code-block:: json - { "name":"Avery Bradley", "age":25, "position":"PG"}, {years_in_nba":[2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} - { "name":"Jae Crowder", "age":25, "position":"PG" }, {years_in_nba":[2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]"} - { "name":"John Holland", "age":27, "position":"SG" }, {years_in_nba":[2017, 2018]"} + {"name":"Avery Bradley","age":25,"position":"PG","years_in_nba":[2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021]} + {"name":"Jae Crowder","age":25,"position":"PG","years_in_nba":[2012,2013,2014,2015,2016,2017,2018,2019,2020,2021]} + {"name":"John Holland","age":27,"position":"SG","years_in_nba":[2017,2018]} + Execute the following statement: From 4f01f0ce2b06abd8f925099d17cef412384eb1ae Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 7 Aug 2023 16:53:06 +0300 Subject: [PATCH 0726/1892] ARRAY --- data_ingestion/json.rst | 2 +- data_type_guides/sql_data_type_array.rst | 16 +++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 1c47b892e..ba63fa30b 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON object array: .. code-block:: postgres { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: postgres [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON object array: .. code-block:: json { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 63194ef2b..b5e91d6ff 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -144,7 +144,7 @@ Updating table values: Ingesting Arrayed Data from External Files ------------------------------------------ -Consider the following JSON file to be ingested into SQreamDB: +Consider the following JSON file named ``t``, located under ``/tmp/``: .. code-block:: json @@ -158,15 +158,17 @@ Execute the following statement: .. code-block:: sql CREATE FOREIGN TABLE nba - (name text not null), - (age int not null), - (position text not null), - (years_in_nba int[] not null) - + ( + name text, + age int, + position text, + years_in_nba int[] + ) + WRAPPER json_fdw OPTIONS ( - location = 'nba.json' + location ='/tmp/t.json' ) ; From 3232b42146efe8a23a87362a5e773bcb08f692ab Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:02:57 +0300 Subject: [PATCH 0727/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index b5e91d6ff..0b8bc6067 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -148,10 +148,25 @@ Consider the following JSON file named ``t``, located under ``/tmp/``: .. code-block:: json - {"name":"Avery Bradley","age":25,"position":"PG","years_in_nba":[2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021]} - {"name":"Jae Crowder","age":25,"position":"PG","years_in_nba":[2012,2013,2014,2015,2016,2017,2018,2019,2020,2021]} - {"name":"John Holland","age":27,"position":"SG","years_in_nba":[2017,2018]} - + [{ + "name": "Avery Bradley", + "age": 25, + "position": "PG", + "years_in_nba": [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] + }, + { + "name": "Jae Crowder", + "age": 25, + "position": "PG", + "years_in_nba": [2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] + }, + { + "name": "John Holland", + "age": 27, + "position": "SG", + "years_in_nba": [2017, 2018] + } + ] Execute the following statement: From cbcd914f51ba6b86388da2b7a4cb6c1377bb96ba Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:06:14 +0300 Subject: [PATCH 0728/1892] Update json.rst --- data_ingestion/json.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index ba63fa30b..d68af75f2 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON object array: .. code-block:: json { "name":"Avery Bradley", "age":25, "position":"PG" } { "name":"Jae Crowder", "age":25, "position":"PG" } { "name":"John Holland", "age":27, "position":"SG" } JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file From 60c7d9ded9da0eac00b701d512848857d445841a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:49:44 +0300 Subject: [PATCH 0729/1892] CTEs --- .../sql_statements/dml_commands/select.rst | 112 +++++++------ .../sql_syntax/common_table_expressions.rst | 148 +++++++++++++----- 2 files changed, 161 insertions(+), 99 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index 03bd20d70..2f0e2de75 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -1,8 +1,8 @@ .. _select: -********************** +****** SELECT -********************** +****** ``SELECT`` is the main statement that allows reading and processing of data. It is used to retrieve rows and columns from one or more tables. @@ -14,12 +14,12 @@ When used alone, the statement is known as a "``SELECT`` statement" or "``SELECT :local: Permissions -============= +=========== The role must have the ``SELECT`` permission on every table or schema that is referenced by the ``SELECT`` query. Syntax -========== +====== .. code-block:: postgres @@ -87,7 +87,7 @@ Syntax Elements -============ +======== .. list-table:: :widths: auto @@ -113,10 +113,10 @@ Elements - Concatenates the results of two queries together. ``UNION ALL`` does not remove duplicates. Notes -=========== +===== -Query processing ------------------ +Query Processing +---------------- Queries are processed in a manner equivalent to the following order: @@ -136,8 +136,8 @@ Inside the ``FROM`` clause, the processing occurs in the usual way, from the out .. _select_lists: -Select lists ----------------- +Select Lists +------------ The ``select_list`` is a comma separated list of column names and value expressions. @@ -155,7 +155,7 @@ The ``select_list`` is a comma separated list of column names and value expressi SELECT a, SUM(b) FROM t GROUP BY 1 ORDER BY 2 DESC; Examples -=========== +======== Assume a table named ``nba``, with the following structure: @@ -183,8 +183,8 @@ Here's a peek at the table contents (:download:`Download nba.csv </_static/sampl :header-rows: 1 -Simple queries ------------------- +Simple Queries +-------------- This query will get the Name, Team name, and Age from the NBA table, but only show the first 10 results. @@ -202,8 +202,8 @@ This query will get the Name, Team name, and Age from the NBA table, but only sh Terry Rozier,Boston Celtics,22 Marcus Smart,Boston Celtics,22 -Show a count of the rows ---------------------------- +Show Row Count +-------------- Use ``COUNT(*)`` to retrieve the number of rows in a result. @@ -212,8 +212,8 @@ Use ``COUNT(*)`` to retrieve the number of rows in a result. nba=> SELECT COUNT(*) FROM nba; 457 -Get all columns ------------------ +Get All Columns +--------------- ``*`` is used as shorthand for "all columns". @@ -237,8 +237,8 @@ Get all columns .. _where: -Filter on conditions ------------------------ +Filter On Conditions +-------------------- Use the ``WHERE`` clause to filter results. @@ -259,8 +259,8 @@ Use the ``WHERE`` clause to filter results. Joel Embiid,22,4626960 Nerlens Noel,22,3457800 -Filter based on a list ------------------------- +Filter Based On a List +---------------------- ``WHERE column IN (value_expr in comma separated list)`` matches the column with any value in the list. @@ -277,8 +277,8 @@ Filter based on a list Jeff Withey,26,947276,Utah Jazz -Select only distinct rows ---------------------------- +Select Only Distinct Rows +------------------------- .. code-block:: psql @@ -314,16 +314,16 @@ Select only distinct rows Utah Jazz Washington Wizards -Count distinct values ------------------------ +Count Distinct Values +--------------------- .. code-block:: psql nba=> SELECT COUNT(DISTINCT "Team") FROM nba; 30 -Rename columns with aliases ------------------------------ +Rename Columns With Aliases +--------------------------- .. code-block:: psql @@ -341,8 +341,8 @@ Rename columns with aliases R.J. Hunter | Boston Celtics | 1148640 Jonas Jerebko | Boston Celtics | 5000000 -Searching with ``LIKE`` -------------------------- +Searching With ``LIKE`` +----------------------- :ref:`like` allows pattern matching text in the ``WHERE`` clause. @@ -359,8 +359,8 @@ Searching with ``LIKE`` Allen Crabbe,24,947276,Portland Trail Blazers Ed Davis,27,6980802,Portland Trail Blazers -Aggregate functions ----------------------- +Aggregate Functions +------------------- Aggregate functions compute a single result from a column. @@ -390,8 +390,8 @@ Aggregate functions are often combined with ``GROUP BY``. A query like ``SELECT "Team",max("Salary") FROM nba`` is not valid, and will result in an error. -Filtering on aggregates --------------------------- +Filtering on Aggregates +----------------------- Filtering on aggregates is done with the ``HAVING`` clause, rather than the ``WHERE`` clause. @@ -410,8 +410,8 @@ Filtering on aggregates is done with the ``HAVING`` clause, rather than the ``WH .. _order_by: -Sorting results -------------------- +Sorting Results +--------------- ``ORDER BY`` takes a comma separated list of ordering specifications - a column followed by ``ASC`` for ascending or ``DESC`` for descending. @@ -450,8 +450,8 @@ Sorting results Portland Trail Blazers | 3220121 Philadelphia 76ers | 2213778 -Sorting with multiple columns ------------------------------------ +Sorting With Multiple Columns +----------------------------- Order retrieved rows by multiple columns: @@ -471,8 +471,8 @@ Order retrieved rows by multiple columns: Aaron Brooks | PG | 161 | 2250000 -Combining two or more queries ---------------------------------- +Combining Two or More Queries +----------------------------- ``UNION ALL`` can be used to combine the results of two or more queries into one result set. @@ -488,17 +488,15 @@ Combining two or more queries PG PG -Common table expressions (CTE) --------------------------------- - -Common table expressions or CTEs allow a possibly complex subquery to be represented in a short way later on, for improved readability. +Common Table Expression +----------------------- -It does not affect query performance. +A Common Table Expression (CTE) is a temporary named result set that can be referenced within a ``SELECT``, ``INSERT``, ``UPDATE``, or ``DELETE`` statement, allowing for more readable and modular queries. CTEs do not affect query performance. .. code-block:: psql - nba=> WITH s AS (SELECT "Name" FROM nba WHERE "Salary" > 20000000) - . SELECT * FROM nba AS n, s WHERE n."Name" = s."Name"; + WITH s AS (SELECT Name FROM nba WHERE Salary > 20000000) + SELECT * FROM nba AS n, s WHERE n.Name = s.Name; Name | Team | Number | Position | Age | Height | Weight | College | Salary | name0 ----------------+-----------------------+--------+----------+-----+--------+--------+--------------+----------+---------------- Carmelo Anthony | New York Knicks | 7 | SF | 32 | 6-8 | 240 | Syracuse | 22875000 | Carmelo Anthony @@ -510,31 +508,31 @@ It does not affect query performance. Kobe Bryant | Los Angeles Lakers | 24 | SF | 37 | 6-6 | 212 | | 25000000 | Kobe Bryant LeBron James | Cleveland Cavaliers | 23 | SF | 31 | 6-8 | 250 | | 22970500 | LeBron James -In this example, the ``WITH`` clause defines the temporary name ``r`` for the subquery which finds salaries over $20 million. The result set becomes a valid table reference in any table expression of the subsequent SELECT clause. +In this example, the ``WITH`` clause defines the temporary name ``s`` for the subquery which finds salaries over $20 million. The result set becomes a valid table reference in any table expression of the subsequent ``SELECT`` clause. Nested CTEs -^^^^^^^^^^^^^^ +^^^^^^^^^^^ -SQream DB also supports any amount of nested CTEs, such as this: +SQreamDB also supports any amount of nested CTEs, such as this: .. code-block:: postgres WITH w AS (SELECT * FROM - (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY "Salary" DESC)) - SELECT * FROM w ORDER BY "Weight" DESC; + (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY Salary DESC)) + SELECT * FROM w ORDER BY Weight DESC; Reusing CTEs -^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ -SQream DB supports reusing CTEs several times in a query: +SQreamDB supports reusing CTEs several times in a query: .. code-block:: psql - nba=> WITH - . nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), - . nba_az AS (SELECT "Name", "Team" FROM nba WHERE "College"='Arizona') - . SELECT * FROM nba_az JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; + WITH + nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), + nba_az AS (SELECT "Name", "Team" FROM nba WHERE "College"='Arizona') + SELECT * FROM nba_az JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; Name | Team | name0 | team0 ----------------+-----------------+----------------+---------------- Stanley Johnson | Detroit Pistons | Andre Drummond | Detroit Pistons diff --git a/reference/sql/sql_syntax/common_table_expressions.rst b/reference/sql/sql_syntax/common_table_expressions.rst index 8ea74dba7..62506b865 100644 --- a/reference/sql/sql_syntax/common_table_expressions.rst +++ b/reference/sql/sql_syntax/common_table_expressions.rst @@ -1,15 +1,13 @@ .. _common_table_expressions: -********************************* -Common table expressions (CTEs) -********************************* +************************ +Common Table Expressions +************************ -Common table expressions or CTEs allow a complex subquery to be represented in a short way later on for improved readability, and reuse multiple times in a query. - -CTEs do not affect query performance. +A Common Table Expression (CTE) is a temporary named result set that can be referenced within a ``SELECT``, ``INSERT``, ``UPDATE``, or ``DELETE`` statement, allowing for more readable and modular queries. CTEs do not affect query performance. Syntax -========== +====== .. code-block:: postgres @@ -39,62 +37,103 @@ Syntax | ( VALUES ( value_expr [, ... ] ) [, ... ] ) Examples -========== +======== + +Create the following ``nba`` table: + +.. code-block:: psql + + CREATE OR REPLACE TABLE nba ( + Name TEXT, + Team TEXT, + Number INTEGER, + Position TEXT, + Age INTEGER, + Height TEXT, + Weight INTEGER, + College TEXT, + Salary INTEGER, + name0 TEXT + ); + + INSERT INTO nba (Name, Team, Number, Position, Age, Height, Weight, College, Salary, name0) + VALUES + ('Carmelo Anthony', 'New York Knicks', 7, 'SF', 32, '6-8', 240, 'Syracuse', 22875000, 'Carmelo Anthony'), + ('Chris Bosh', 'Miami Heat', 1, 'PF', 32, '6-11', 235, 'Georgia Tech', 22192730, 'Chris Bosh'), + ('Chris Paul', 'Los Angeles Clippers', 3, 'PG', 31, '6-0', 175, 'Wake Forest', 21468695, 'Chris Paul'), + ('Derrick Rose', 'Chicago Bulls', 1, 'PG', 27, '6-3', 190, 'Memphis', 20093064, 'Derrick Rose'), + ('Dwight Howard', 'Houston Rockets', 12, 'C', 30, '6-11', 265, NULL, 22359364, 'Dwight Howard'), + ('Kevin Durant', 'Oklahoma City Thunder', 35, 'SF', 27, '6-9', 240, 'Texas', 20158622, 'Kevin Durant'), + ('Kobe Bryant', 'Los Angeles Lakers', 24, 'SF', 37, '6-6', 212, NULL, 25000000, 'Kobe Bryant'), + ('LeBron James', 'Cleveland Cavaliers', 23, 'SF', 31, '6-8', 250, NULL, 22970500, 'LeBron James') + ('Stanley Johnson', 'Detroit Pistons', 3, 'SF', 26, '6-7', 245, 'Connecticut', 3120360, 'Stanley Johnson'), + ('Andre Drummond', 'Detroit Pistons', 0, 'C', 28, '6-10', 279, 'Connecticut', 27093019, 'Andre Drummond'), + ('Aaron Gordon', 'Orlando Magic', 0, 'PF', 26, '6-8', 235, 'Arizona', 18136364, 'Aaron Gordon'), + ('Shabazz Napier', 'Orlando Magic', 13, 'PG', 31, '6-1', 175, 'Connecticut', 1378242, 'Shabazz Napier'); Simple CTE --------------- +---------- .. code-block:: psql - nba=> WITH s AS (SELECT "Name" FROM nba WHERE "Salary" > 20000000) - . SELECT * FROM nba AS n, s WHERE n."Name" = s."Name"; - Name | Team | Number | Position | Age | Height | Weight | College | Salary | name0 - ----------------+-----------------------+--------+----------+-----+--------+--------+--------------+----------+---------------- - Carmelo Anthony | New York Knicks | 7 | SF | 32 | 6-8 | 240 | Syracuse | 22875000 | Carmelo Anthony - Chris Bosh | Miami Heat | 1 | PF | 32 | 6-11 | 235 | Georgia Tech | 22192730 | Chris Bosh - Chris Paul | Los Angeles Clippers | 3 | PG | 31 | 6-0 | 175 | Wake Forest | 21468695 | Chris Paul - Derrick Rose | Chicago Bulls | 1 | PG | 27 | 6-3 | 190 | Memphis | 20093064 | Derrick Rose - Dwight Howard | Houston Rockets | 12 | C | 30 | 6-11 | 265 | | 22359364 | Dwight Howard - Kevin Durant | Oklahoma City Thunder | 35 | SF | 27 | 6-9 | 240 | Texas | 20158622 | Kevin Durant - Kobe Bryant | Los Angeles Lakers | 24 | SF | 37 | 6-6 | 212 | | 25000000 | Kobe Bryant - LeBron James | Cleveland Cavaliers | 23 | SF | 31 | 6-8 | 250 | | 22970500 | LeBron James - -In this example, the ``WITH`` clause defines the temporary name ``r`` for the subquery which finds salaries over $20 million. The result set becomes a valid table reference in any table expression of the subsequent SELECT clause. + WITH s AS (SELECT Name FROM nba WHERE Salary > 20000000) + SELECT * FROM nba AS n, s WHERE n.Name = s.Name; + name |team |number|position|age|height|weight|college |salary |name0 |name1 | + ---------------+---------------------+------+--------+---+------+------+------------+--------+---------------+---------------+ + Kobe Bryant |Los Angeles Lakers | 24|SF | 37|6-6 | 212| |25000000|Kobe Bryant |Kobe Bryant | + LeBron James |Cleveland Cavaliers | 23|SF | 31|6-8 | 250| |22970500|LeBron James |LeBron James | + Dwight Howard |Houston Rockets | 12|C | 30|6-11 | 265| |22359364|Dwight Howard |Dwight Howard | + Carmelo Anthony|New York Knicks | 7|SF | 32|6-8 | 240|Syracuse |22875000|Carmelo Anthony|Carmelo Anthony| + Chris Bosh |Miami Heat | 1|PF | 32|6-11 | 235|Georgia Tech|22192730|Chris Bosh |Chris Bosh | + Chris Paul |Los Angeles Clippers | 3|PG | 31|6-0 | 175|Wake Forest |21468695|Chris Paul |Chris Paul | + Kevin Durant |Oklahoma City Thunder| 35|SF | 27|6-9 | 240|Texas |20158622|Kevin Durant |Kevin Durant | + Derrick Rose |Chicago Bulls | 1|PG | 27|6-3 | 190|Memphis |20093064|Derrick Rose |Derrick Rose | + +In this example, the ``WITH`` clause defines the temporary name ``s`` for the subquery which finds salaries over $20 million. The result set becomes a valid table reference in any table expression of the subsequent ``SELECT`` clause. Nested CTEs ---------------- +----------- -SQream DB also supports any amount of nested CTEs, such as this: +SQreamDB also supports any amount of nested CTEs, such as this: .. code-block:: postgres WITH w AS (SELECT * FROM - (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY "Salary" DESC)) - SELECT * FROM w ORDER BY "Weight" DESC; + (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY Salary DESC)) + SELECT * FROM w ORDER BY Weight DESC; + name |team |number|position|age|height|weight|college |salary |name0 | + ---------------+---------------------+------+--------+---+------+------+------------+--------+---------------+ + Dwight Howard |Houston Rockets | 12|C | 30|6-11 | 265| |22359364|Dwight Howard | + LeBron James |Cleveland Cavaliers | 23|SF | 31|6-8 | 250| |22970500|LeBron James | + Carmelo Anthony|New York Knicks | 7|SF | 32|6-8 | 240|Syracuse |22875000|Carmelo Anthony| + Kevin Durant |Oklahoma City Thunder| 35|SF | 27|6-9 | 240|Texas |20158622|Kevin Durant | + Chris Bosh |Miami Heat | 1|PF | 32|6-11 | 235|Georgia Tech|22192730|Chris Bosh | + Kobe Bryant |Los Angeles Lakers | 24|SF | 37|6-6 | 212| |25000000|Kobe Bryant | + Derrick Rose |Chicago Bulls | 1|PG | 27|6-3 | 190|Memphis |20093064|Derrick Rose | + Chris Paul |Los Angeles Clippers | 3|PG | 31|6-0 | 175|Wake Forest |21468695|Chris Paul | Reusing CTEs ----------------- +------------ -SQream DB supports reusing CTEs several times in a query. +SQreamDB supports reusing CTEs several times in a query. CTEs are separated with commas. .. code-block:: psql - nba=> WITH - . nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), - . nba_az AS (SELECT "Name", "Team" FROM nba WHERE "College"='Arizona') - . SELECT * FROM nba_az JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; - Name | Team | name0 | team0 - ----------------+-----------------+----------------+---------------- - Stanley Johnson | Detroit Pistons | Andre Drummond | Detroit Pistons - Aaron Gordon | Orlando Magic | Shabazz Napier | Orlando Magic + WITH + nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), + nba_az AS (SELECT "Name", "Team" FROM nba WHERE "College"='Arizona') + SELECT * FROM nba_az JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; + name |team |name0 |team0 | + ------------+-------------+--------------+-------------+ + Aaron Gordon|Orlando Magic|Shabazz Napier|Orlando Magic| -Using CTEs with :ref:`create_table_as` ----------------------------------------- +Using CTEs with ``CREATE TABLE AS`` +----------------------------------- When used with :ref:`create_table_as`, the ``CREATE TABLE`` statement should appear before ``WITH``. @@ -103,6 +142,31 @@ When used with :ref:`create_table_as`, the ``CREATE TABLE`` statement should app CREATE TABLE weights AS WITH w AS - (SELECT * FROM - (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY "Salary" DESC)) - SELECT * FROM w ORDER BY "Weight" DESC; + (SELECT * FROM + (WITH x AS (SELECT * FROM nba) SELECT * FROM x ORDER BY Salary DESC)) + SELECT * FROM w ORDER BY Weight DESC; + + SELECT * FROM weights; + + name |team |number|position|age|height|weight|college |salary |name0 | + ---------------+---------------------+------+--------+---+------+------+------------+--------+---------------+ + Andre Drummond |Detroit Pistons | 0|C | 28|6-10 | 279|Connecticut |27093019|Andre Drummond | + Dwight Howard |Houston Rockets | 12|C | 30|6-11 | 265| |22359364|Dwight Howard | + LeBron James |Cleveland Cavaliers | 23|SF | 31|6-8 | 250| |22970500|LeBron James | + Stanley Johnson|Detroit Pistons | 3|SF | 26|6-7 | 245|Connecticut | 3120360|Stanley Johnson| + Carmelo Anthony|New York Knicks | 7|SF | 32|6-8 | 240|Syracuse |22875000|Carmelo Anthony| + Kevin Durant |Oklahoma City Thunder| 35|SF | 27|6-9 | 240|Texas |20158622|Kevin Durant | + Chris Bosh |Miami Heat | 1|PF | 32|6-11 | 235|Georgia Tech|22192730|Chris Bosh | + Aaron Gordon |Orlando Magic | 0|PF | 26|6-8 | 235|Arizona |18136364|Aaron Gordon | + Kobe Bryant |Los Angeles Lakers | 24|SF | 37|6-6 | 212| |25000000|Kobe Bryant | + Derrick Rose |Chicago Bulls | 1|PG | 27|6-3 | 190|Memphis |20093064|Derrick Rose | + Chris Paul |Los Angeles Clippers | 3|PG | 31|6-0 | 175|Wake Forest |21468695|Chris Paul | + Shabazz Napier |Orlando Magic | 13|PG | 31|6-1 | 175|Connecticut | 1378242|Shabazz Napier | + +Using CTEs with ``INSERT`` +-------------------------- + +The :ref:`insert` statement should appear before ``WITH``. + +.. code-block:: postgres + From 509e959e011044fbe1306416e04fdbc78f33797e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 8 Aug 2023 11:50:45 +0300 Subject: [PATCH 0730/1892] CTEs --- reference/sql/sql_statements/dml_commands/select.rst | 2 +- reference/sql/sql_syntax/common_table_expressions.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index 2f0e2de75..bb1e44af4 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -491,7 +491,7 @@ Combining Two or More Queries Common Table Expression ----------------------- -A Common Table Expression (CTE) is a temporary named result set that can be referenced within a ``SELECT``, ``INSERT``, ``UPDATE``, or ``DELETE`` statement, allowing for more readable and modular queries. CTEs do not affect query performance. +A Common Table Expression (CTE) is a temporary named result set that can be referenced within a statement, allowing for more readable and modular queries. CTEs do not affect query performance. .. code-block:: psql diff --git a/reference/sql/sql_syntax/common_table_expressions.rst b/reference/sql/sql_syntax/common_table_expressions.rst index 62506b865..c905b641d 100644 --- a/reference/sql/sql_syntax/common_table_expressions.rst +++ b/reference/sql/sql_syntax/common_table_expressions.rst @@ -4,7 +4,7 @@ Common Table Expressions ************************ -A Common Table Expression (CTE) is a temporary named result set that can be referenced within a ``SELECT``, ``INSERT``, ``UPDATE``, or ``DELETE`` statement, allowing for more readable and modular queries. CTEs do not affect query performance. +A Common Table Expression (CTE) is a temporary named result set that can be referenced within a statement, allowing for more readable and modular queries. CTEs do not affect query performance. Syntax ====== From 04c2e24a7a51cd262ebe73a023c96850d2a7b84c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 8 Aug 2023 13:51:45 +0300 Subject: [PATCH 0731/1892] Update common_table_expressions.rst --- .../sql_syntax/common_table_expressions.rst | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/reference/sql/sql_syntax/common_table_expressions.rst b/reference/sql/sql_syntax/common_table_expressions.rst index c905b641d..a1958f02e 100644 --- a/reference/sql/sql_syntax/common_table_expressions.rst +++ b/reference/sql/sql_syntax/common_table_expressions.rst @@ -170,3 +170,27 @@ The :ref:`insert` statement should appear before ``WITH``. .. code-block:: postgres + CREATE OR REPLACE TABLE nba_archive ( + Name TEXT, + Team TEXT, + Number INTEGER, + Position TEXT, + Age INTEGER, + Height TEXT, + Weight INTEGER, + College TEXT, + Salary INTEGER, + name0 TEXT + ); + + INSERT INTO nba_archive + WITH nba_info AS( + SELECT * + FROM nba + ) + SELECT * + FROM nba_info; + + SELECT * FROM nba_archive ; + + \ No newline at end of file From 7a558310207d8264e77fe3d880512bdcb66e3816 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 9 Aug 2023 10:12:14 +0300 Subject: [PATCH 0732/1892] Update charindex.rst --- .../scalar_functions/string/charindex.rst | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index c8f2e4223..e519d31e7 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -1,10 +1,11 @@ .. _charindex: -************************** +********* CHARINDEX -************************** +********* + +``CHARINDEX`` is a 1-based indexing function that returns the starting position of a specified substring within a given string. -Returns the starting position of a string inside another string. See also :ref:`patindex`, :ref:`regexp_instr`. @@ -64,7 +65,7 @@ Using ``CHARINDEX`` .. code-block:: sql - SELECT CHARINDEX('john', username) FROM users; + SELECT CHARINDEX('doe', username) FROM users; Output: @@ -72,8 +73,8 @@ Output: charindex| ---------+ - 1 | - 0 | + 6 | + 6 | 0 | 0 | From cc87e8a9d197ad0e121678fffd971c7b192bf67f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:00:19 +0300 Subject: [PATCH 0733/1892] Update index.rst --- index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.rst b/index.rst index 6a174af67..64923ac0a 100644 --- a/index.rst +++ b/index.rst @@ -1,8 +1,8 @@ .. _index: -************************* -SQream DB Documentation -************************* +********************** +SQreamDB Documentation +********************** SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQream DB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. From 00219a57368b1e76946dff58a83a3c5f5c8b2252 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:31:30 +0300 Subject: [PATCH 0734/1892] Sizing --- architecture/internals_architecture.rst | 75 +++++++++++-------------- configuration_guides/spooling.rst | 16 +++--- 2 files changed, 42 insertions(+), 49 deletions(-) diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 571b5f9a0..9b5793d1a 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -1,31 +1,32 @@ .. _internals_architecture: -*************************** -Internals and architecture -*************************** +************************** +Internals and Architecture +************************** -SQream DB internals -============================== -Here is a high level architecture diagram of SQream DB's internals. +SQreamDB internals +================== + +Here is a high level architecture diagram of SQreamDB's internals. .. figure:: /_static/images/sqream_db_internals.png - :alt: SQream DB internals + :alt: SQreamDB internals -Statement compiler ------------------------- +Statement Compiler +------------------ -The statement compiler is written in Haskell. This takes SQL text and produces an optimised statement plan. +The statement compiler is written in Haskell. This takes SQL text and produces an optimized statement plan. -Concurrency and concurrency control ----------------------------------------- +Concurrency and Concurrency Control +----------------------------------- -The execution engine in SQream DB is built around thread workers with message passing. It uses threads to overlap different kinds of operations (including IO and GPU operations with CPU operations), and to accelerate CPU intensive operations. +The execution engine in SQreamDB is built around thread workers with message passing. It uses threads to overlap different kinds of operations (including IO and GPU operations with CPU operations), and to accelerate CPU intensive operations. Transactions --------------------- +------------ -SQream DB has serializable transactions, with these features: +SQreamDB has serializable transactions, with these features: * Serializable, with any kind of statement @@ -38,28 +39,28 @@ SQream DB has serializable transactions, with these features: * Other operations such as :ref:`delete`, :ref:`truncate`, and DDL use :ref:`coarse-grained exclusive locking<concurrency_and_locks>`. Storage ----------- +------- The storage is split into the :ref:`metadata layer<metadata_system>` and an append-only/ garbage collected bulk data layer. -Metadata layer -^^^^^^^^^^^^^^^^^^^^^^ +Metadata Layer +^^^^^^^^^^^^^^ The metadata layer uses RocksDB, and uses RocksDB's snapshot and write atomic features as part of the transaction system. The metadata layer, together with the append-only bulk data layer help ensure consistency. -Bulk data layer -^^^^^^^^^^^^^^^^^^^^^^^^ +Bulk Data Layer +^^^^^^^^^^^^^^^ -The bulk data layer is comprised of extents, which are optimised for IO performance as much as possible. Inside the extents, are chunks, which are optimised for processing in the CPU and GPU. Compression is used in the extents and chunks. +The bulk data layer is comprised of extents, which are optimized for IO performance as much as possible. Inside the extents, are chunks, which are optimized for processing in the CPU and GPU. Compression is used in the extents and chunks. -When you run small inserts, you will get less optimised chunks and extents, but the system is designed to both be able to still run efficiently on this, and to be able to reorganise them transactionally in the background, without blocking DML operations. By writing small chunks in small inserts, then reorganising later, it supports both fast medium sized insert transactions and fast querying. +When you run small inserts, you will get less optimized chunks and extents, but the system is designed to both be able to still run efficiently on this, and to be able to reorganize them transactionally in the background, without blocking DML operations. By writing small chunks in small inserts, then reorganizing later, it supports both fast medium sized insert transactions and fast querying. -Building blocks ----------------------- +Building Blocks +--------------- -The heavy lifting in SQream DB is done by single purpose C++/CUDA building blocks. +The heavy lifting in SQreamDB is done by single purpose C++/CUDA building blocks. These are purposely designed to not be smart - they have to be instructed exactly what to do. @@ -67,29 +68,19 @@ Most of the intelligence in piecing things together is in the statement compiler Columnar -============= +======== -Like many other analytical database management systems, SQream DB uses a column store for tables. +Like many other analytical database management systems, SQreamDB uses a column store for tables. Column stores offer better I/O and performance with analytic workloads. Columns also compress much better, and lend themselves well to bulk data. -GPU usage -============= - -SQream DB uses GPUs for accelerating database operations. This acceleration brings additional benefit to columnar data processing. - -SQream DB's GPU acceleration is integral to database operations. It is not an additional feature, but rather core to most data operations, e.g. ``GROUP BY``, scalar functions, ``JOIN``, ``ORDER BY``, and more. - -Using a GPU is an extended form of SIMD (Single-instruction, multiple data) intended for high throughput operations. When GPU acceleraiton is used, SQream DB uses special building blocks to take advantage of the high degree of parallelism of the GPU. This means that GPU operations use a single instruction that runs on multiple values. - - +GPU Usage +========= -.. describe the concepts behind the storage, transaction, statement -.. engine +SQreamDB uses GPUs for accelerating database operations. This acceleration brings additional benefit to columnar data processing. +SQreamDB's GPU acceleration is integral to database operations. It is not an additional feature, but rather core to most data operations, e.g. ``GROUP BY``, scalar functions, ``JOIN``, ``ORDER BY``, and more. -.. some of this might be better in another document, if you're reading to -.. understand how sqream performs, this is not the internal architecture -.. but something more directly important to a customer/user +Using a GPU is an extended form of SIMD (Single-instruction, multiple data) intended for high throughput operations. When GPU acceleraiton is used, SQreamDB uses special building blocks to take advantage of the high degree of parallelism of the GPU. This means that GPU operations use a single instruction that runs on multiple values. diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst index 0235b757a..b77c9a605 100644 --- a/configuration_guides/spooling.rst +++ b/configuration_guides/spooling.rst @@ -1,20 +1,21 @@ .. _spooling: -************************** +******************************** Configuring the Spooling Feature -************************** +******************************** -From the SQream Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQream recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. +From the SQreamDB Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. -In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. SQream recommends setting ``limitQueryMemoryGB`` to 5% less than the total host memory divided by the amount of ``sqreamd`` workers on host. +In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. Example Configurations ----------- +---------------------- Setting Spool Memory -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~ + The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: .. code-block:: console @@ -34,7 +35,8 @@ The following is an example of setting ``spoolMemoryGB`` value per-worker for 51 } Recommended Settings -~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~ + The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: .. code-block:: console From e5949fc9863d9f3c33dacc9f98cffede24dc0f15 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:32:49 +0300 Subject: [PATCH 0735/1892] Update spooling.rst --- configuration_guides/spooling.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst index b77c9a605..78df2e93f 100644 --- a/configuration_guides/spooling.rst +++ b/configuration_guides/spooling.rst @@ -1,8 +1,8 @@ .. _spooling: -******************************** -Configuring the Spooling Feature -******************************** +********************** +Spooling Configuration +********************** From the SQreamDB Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. From 56c0e49a54e55ceb540296d37aeb1e470cba33f5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:37:54 +0300 Subject: [PATCH 0736/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/feature_guides/concurrency_and_scaling_in_sqream.rst b/feature_guides/concurrency_and_scaling_in_sqream.rst index 0370913fa..db23aaed7 100644 --- a/feature_guides/concurrency_and_scaling_in_sqream.rst +++ b/feature_guides/concurrency_and_scaling_in_sqream.rst @@ -1,36 +1,34 @@ .. _concurrency_and_scaling_in_sqream: -*************************************** -Concurrency and Scaling in SQream DB -*************************************** +*********************************** +Concurrency and Scaling in SQreamDB +*********************************** -A SQream DB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. +A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. -SQream DB supports ``n`` concurrent statements by having ``n`` workers in a cluster. Each worker uses a fixed slice of a GPU's memory, with usual values are around 8-16GB of GPU memory per worker. This size is ideal for queries running on large data with potentially large row sizes. +SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a cluster. Each worker uses a fixed slice of a GPU's memory, with usual values are around 8-16GB of GPU memory per worker. This size is ideal for queries running on large data with potentially large row sizes. -Scaling when data sizes grow --------------------------------- +Scaling When Data Sizes Grow +---------------------------- -For many statements, SQream DB scales linearly when adding more storage and querying on large data sets. It uses very optimised 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. +For many statements, SQreamDB scales linearly when adding more storage and querying on large data sets. It uses very optimised 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. -Scaling when queries are queueing ---------------------------------------- +Scaling When Queries Are Queuing +-------------------------------- -SQream DB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. +SQreamDB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. -What to do when queries are slow ----------------------------------- +What To Do When Queries Are Slow +-------------------------------- Adding more workers or GPUs does not boost the performance of a single statement or query. To boost the performance of a single statement, start by examining the :ref:`best practices<sql_best_practices>` and ensure the guidelines are followed. -.. TODO: we have a lot of techniques to speed up statements which aren't ready for customers to use without support - add something here and in the best practices about this - Adding additional RAM to nodes, using more GPU memory, and faster CPUs or storage can also sometimes help. .. rubric:: Need help? -Analyzing complex workloads can be challenging. SQream's experienced customer support has the experience to advise on these matters to ensure the best experience. +Analyzing complex workloads can be challenging. SQreamDB's experienced customer support has the experience to advise on these matters to ensure the best experience. -Visit `SQream's support portal <https://support.sqream.com>`_ for additional support. +Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. From 684946670fb4616a554822f7dbd945f7d017b812 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 09:55:23 +0300 Subject: [PATCH 0737/1892] Sizing --- .../filesystem_and_filesystem_usage.rst | 34 +++++++++---------- architecture/index.rst | 10 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst index 634097e23..1bd670efb 100644 --- a/architecture/filesystem_and_filesystem_usage.rst +++ b/architecture/filesystem_and_filesystem_usage.rst @@ -1,29 +1,29 @@ .. _filesystem_and_filesystem_usage: -******************************* -Filesystem and usage -******************************* +******************** +Filesystem and Usage +******************** -SQream DB writes and reads data from disk. +SQreamDB writes and reads data from disk. -The SQream DB storage directory, sometimes refered to as a **storage cluster** is a collection of database objects, metadata database, and logs. +The SQreamDB storage directory, sometimes referred to as a **storage cluster** is a collection of database objects, metadata database, and logs. -Each SQream DB worker and the metadata server must have access to the storage cluster in order to function properly. +Each SQreamDB worker and the metadata server must have access to the storage cluster in order to function properly. .. _storage_cluster: Directory organization -============================ +====================== .. figure:: /_static/images/storage_organization.png -The **cluster root** is the directory in which all data for SQream DB is stored. +The **cluster root** is the directory in which all data for SQreamDB is stored. -.. contents:: SQream DB storage cluster directories +.. contents:: SQreamDB storage cluster directories :local: ``databases`` ----------------- +------------- The databases directory houses all of the actual data in tables and columns. @@ -64,26 +64,26 @@ Each column directory will contain extents, which are collections of chunks. .. figure:: /_static/images/chunks_and_extents.png ``metadata`` or ``rocksdb`` ----------------------------- +--------------------------- -SQream DB's metadata is an embedded key-value store, based on RocksDB. RocksDB helps SQream DB ensure efficient storage for keys, handle atomic writes, snapshots, durability, and automatic recovery. +SQreamDB's metadata is an embedded key-value store, based on RocksDB. RocksDB helps SQreamDB ensure efficient storage for keys, handle atomic writes, snapshots, durability, and automatic recovery. The metadata is where all database objects are stored, including roles, permissions, database and table structures, chunk mappings, and more. ``temp`` ----------------- +-------- -The ``temp`` directory is where SQream DB writes temporary data. +The ``temp`` directory is where SQreamDB writes temporary data. -The directory to which SQream DB writes temporary data can be changed to any other directory on the filesystem. SQream recommends remapping this directory to a fast local storage to get better performance when executing intensive larger-than-RAM operations like sorting. SQream recommends an SSD or NVMe drive, in mirrored RAID 1 configuration. +The directory to which SQreamDB writes temporary data can be changed to any other directory on the filesystem. SQreamDB recommends remapping this directory to a fast local storage to get better performance when executing intensive larger-than-RAM operations like sorting. SQreamDB recommends an SSD or NVMe drive, in mirrored RAID 1 configuration. If desired, the ``temp`` folder can be redirected to a local disk for improved performance, by setting the ``tempPath`` setting in the :ref:`configuration<configuration>` file. ``logs`` ----------------- +-------- -The logs directory contains logs produced by SQream DB. +The logs directory contains logs produced by SQreamDB. See more about the logs in the :ref:`logging` guide. diff --git a/architecture/index.rst b/architecture/index.rst index f4aa7072c..bf8faca62 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -4,11 +4,11 @@ System Architecture ******************* -This topic includes guides that walk an end-user, database administrator, or system architect through the main ideas behind SQream DB. +The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides serve as SQreamDB system walk-throughs for end-users, database administrators, and system architects. -While SQream DB has many similarities to other database management systems, it has some unique and additional capabilities. -Explore the guides below for information about SQream DB's architecture. + +While SQreamDB has many similarities to other database management systems, it has some unique and additional capabilities. .. toctree:: :maxdepth: 2 @@ -16,5 +16,5 @@ Explore the guides below for information about SQream DB's architecture. :glob: :titlesonly: - internals_architecture - filesystem_and_filesystem_usage + + From 5e4a47b4eef8c6834a0ccf438393bacfbb884be0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 10:06:13 +0300 Subject: [PATCH 0738/1892] Update index.rst --- architecture/index.rst | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/architecture/index.rst b/architecture/index.rst index bf8faca62..070b89a17 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -4,17 +4,11 @@ System Architecture ******************* -The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides serve as SQreamDB system walk-throughs for end-users, database administrators, and system architects. - - - -While SQreamDB has many similarities to other database management systems, it has some unique and additional capabilities. +The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. .. toctree:: - :maxdepth: 2 - :caption: In this section: - :glob: - :titlesonly: + :hidden: - + internals_architecture + filesystem_and_filesystem_usage From cdb1c690bcc74089c55ef8ef46618da760154754 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 12:03:06 +0300 Subject: [PATCH 0739/1892] Sizing --- .../concurrency_and_scaling_in_sqream.rst | 118 ++++++++++++++++++ architecture/internals_architecture.rst | 68 +++++----- .../concurrency_and_scaling_in_sqream.rst | 34 ----- feature_guides/index.rst | 8 +- reference/catalog_reference.rst | 5 +- reference/catalog_reference_examples.rst | 15 +-- .../catalog_reference_schema_information.rst | 11 +- 7 files changed, 177 insertions(+), 82 deletions(-) create mode 100644 architecture/concurrency_and_scaling_in_sqream.rst delete mode 100644 feature_guides/concurrency_and_scaling_in_sqream.rst diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst new file mode 100644 index 000000000..910e5fdc4 --- /dev/null +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -0,0 +1,118 @@ +.. _concurrency_and_scaling_in_sqream: + +****** +Sizing +****** + +Concurrency and Scaling in SQreamDB +=================================== + +A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. + +SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a cluster. + +.. list-table:: Minimum Resource Required Per Worker + :widths: auto + :header-rows: 1 + + * - Component + - CPU Cores + - RAM (GB) + - Local Storage (GB) + * - Worker + - 8 + - 128 + - 10 + * - Metadata Server + - 10 cores per 30 Workers + - 128 per 1T rows (accumulated for all tables) + - 10 + * - UI + - 16 + - 16 + - 50 + * - Picker + - 8 + - 8 + - + +.. list-table:: Maximum Workers Per GPU + :widths: auto + :header-rows: 1 + + * - T4 (16GB) + - V100 (32GB) + - A100 (40GB) + - A100 (80GB) + * - 1 + - 2 + - 3 + - 6 + + + +Scaling When Data Sizes Grow +---------------------------- + +For many statements, SQreamDB scales linearly when adding more storage and querying on large data sets. It uses optimized 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. + +Scaling When Queries Are Queuing +-------------------------------- + +SQreamDB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. + +What To Do When Queries Are Slow +-------------------------------- + +Adding more workers or GPUs does not boost the performance of a single statement or query. + +To boost the performance of a single statement, start by examining the :ref:`best practices<sql_best_practices>` and ensure the guidelines are followed. + +Adding additional RAM to nodes, using more GPU memory, and faster CPUs or storage can also sometimes help. + +Spooling Configuration +====================== + +From the SQreamDB Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. + +In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. + +Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. + +Example Configurations +---------------------- + +Setting Spool Memory +~~~~~~~~~~~~~~~~~~~~ + +The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: + +.. code-block:: console + + { + “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, + “gpu”: 0, + “licensePath”: “home/test_user/SQream/tests/license.enc”, + “machineIP”: “127.0.0.1”, + “metadataServerIp”: “127.0.0.1”, + “metadataServerPort”: “3105, + “port”: 5000, + “useConfigIP”” true, + “limitQueryMemoryGB" : 121, + “spoolMemoryGB" : 108 + “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + } + +Recommended Settings +~~~~~~~~~~~~~~~~~~~~ + +The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: + +.. code-block:: console + + limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 + spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 + +.. rubric:: Need help? + +Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 9b5793d1a..334e0ef8f 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -4,44 +4,33 @@ Internals and Architecture ************************** +Get to know the SQreamDB key functions and system architecture components and the best practices and customization possibilities. -SQreamDB internals -================== - -Here is a high level architecture diagram of SQreamDB's internals. +High-Level Architecture Diagram +=============================== .. figure:: /_static/images/sqream_db_internals.png :alt: SQreamDB internals +Key Functions and Components +============================ + Statement Compiler ------------------ -The statement compiler is written in Haskell. This takes SQL text and produces an optimized statement plan. +The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement plans. -Concurrency and Concurrency Control ------------------------------------ +Concurrency and Admission Control +--------------------------------- -The execution engine in SQreamDB is built around thread workers with message passing. It uses threads to overlap different kinds of operations (including IO and GPU operations with CPU operations), and to accelerate CPU intensive operations. +The SQreamDB execution engine employs thread workers and message passing for its foundation. This threading approach enables the concurrent execution of diverse operations, seamlessly integrating IO and GPU tasks with CPU operations while boosting the performance of CPU-intensive tasks. -Transactions ------------- +Learn more about :ref:`concurrency_and_scaling_in_sqream`. -SQreamDB has serializable transactions, with these features: +Storage Layer +------------- -* Serializable, with any kind of statement - -* Run multiple :ref:`SELECT queries<select>` concurrently with anything - -* Run multiple inserts to the same table at the same time - -* Cannot run multiple statements in a single transaction - -* Other operations such as :ref:`delete`, :ref:`truncate`, and DDL use :ref:`coarse-grained exclusive locking<concurrency_and_locks>`. - -Storage -------- - -The storage is split into the :ref:`metadata layer<metadata_system>` and an append-only/ garbage collected bulk data layer. +The storage is split into the metadata layer and an append-only / garbage collected bulk data layer. Metadata Layer ^^^^^^^^^^^^^^ @@ -57,6 +46,30 @@ The bulk data layer is comprised of extents, which are optimized for IO performa When you run small inserts, you will get less optimized chunks and extents, but the system is designed to both be able to still run efficiently on this, and to be able to reorganize them transactionally in the background, without blocking DML operations. By writing small chunks in small inserts, then reorganizing later, it supports both fast medium sized insert transactions and fast querying. +Columnar Storage +^^^^^^^^^^^^^^^^ + +Like many other analytical database management systems, SQreamDB uses a column store for tables. + +Column stores offer better I/O and performance with analytic workloads. Columns also compress much better, and lend themselves well to bulk data. + +Transactions +------------ + +SQreamDB has serializable transactions, with these features: + +* Serializable, with any kind of statement + +* Run multiple :ref:`SELECT queries<select>` concurrently with anything + +* Run multiple inserts to the same table at the same time + +* Cannot run multiple statements in a single transaction + +* Other operations such as :ref:`delete`, :ref:`truncate`, and DDL use :ref:`coarse-grained exclusive locking<concurrency_and_locks>`. + + + Building Blocks --------------- @@ -67,12 +80,7 @@ These are purposely designed to not be smart - they have to be instructed exactl Most of the intelligence in piecing things together is in the statement compiler. -Columnar -======== -Like many other analytical database management systems, SQreamDB uses a column store for tables. - -Column stores offer better I/O and performance with analytic workloads. Columns also compress much better, and lend themselves well to bulk data. GPU Usage ========= diff --git a/feature_guides/concurrency_and_scaling_in_sqream.rst b/feature_guides/concurrency_and_scaling_in_sqream.rst deleted file mode 100644 index db23aaed7..000000000 --- a/feature_guides/concurrency_and_scaling_in_sqream.rst +++ /dev/null @@ -1,34 +0,0 @@ -.. _concurrency_and_scaling_in_sqream: - -*********************************** -Concurrency and Scaling in SQreamDB -*********************************** - -A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. - -SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a cluster. Each worker uses a fixed slice of a GPU's memory, with usual values are around 8-16GB of GPU memory per worker. This size is ideal for queries running on large data with potentially large row sizes. - -Scaling When Data Sizes Grow ----------------------------- - -For many statements, SQreamDB scales linearly when adding more storage and querying on large data sets. It uses very optimised 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. - -Scaling When Queries Are Queuing --------------------------------- - -SQreamDB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. - -What To Do When Queries Are Slow --------------------------------- - -Adding more workers or GPUs does not boost the performance of a single statement or query. - -To boost the performance of a single statement, start by examining the :ref:`best practices<sql_best_practices>` and ensure the guidelines are followed. - -Adding additional RAM to nodes, using more GPU memory, and faster CPUs or storage can also sometimes help. - -.. rubric:: Need help? - -Analyzing complex workloads can be challenging. SQreamDB's experienced customer support has the experience to advise on these matters to ensure the best experience. - -Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 4fe0652ce..e1c1e5118 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -1,11 +1,10 @@ .. _feature_guides: -*********************** +************** Feature Guides -*********************** -The **Feature Guides** section describes background processes that SQream uses to manage several areas of operation, such as data ingestion, load balancing, and access control. +************** -This section describes the following features: +The **Feature Guides** section describes background processes that SQreamDB uses to manage several areas of operation, such as data ingestion, load balancing, and access control. .. toctree:: :maxdepth: 1 @@ -18,4 +17,3 @@ This section describes the following features: python_functions workload_manager concurrency_and_locks - concurrency_and_scaling_in_sqream \ No newline at end of file diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index 8fc0593b8..6035dd34b 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -1,8 +1,9 @@ .. _catalog_reference: -************************************* +*********************** Catalog Reference Guide -************************************* +*********************** + The **Catalog Reference Guide** describes the following: .. toctree:: diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst index 3e605ee05..612d4b76f 100644 --- a/reference/catalog_reference_examples.rst +++ b/reference/catalog_reference_examples.rst @@ -1,8 +1,9 @@ .. _catalog_reference_examples: -************************************* +******** Examples -************************************* +******** + The **Examples** page includes the following examples: .. contents:: @@ -10,7 +11,7 @@ The **Examples** page includes the following examples: :depth: 1 Listing All Tables in a Database ----------------------------------- +-------------------------------- .. code-block:: psql @@ -23,7 +24,7 @@ Listing All Tables in a Database master | 27 | public | jabberwocky | true | 8 | 0 Listing All Schemas in a Database ------------------------------------- +--------------------------------- .. code-block:: psql @@ -35,7 +36,7 @@ Listing All Schemas in a Database Listing Columns and Their Types for a Specific Table ---------------------------------------------------- +---------------------------------------------------- .. code-block:: postgres @@ -44,7 +45,7 @@ Listing Columns and Their Types for a Specific Table WHERE table_name='cool_animals'; Listing Delete Predicates ------------------------- +------------------------- .. code-block:: postgres @@ -55,7 +56,7 @@ Listing Delete Predicates Listing Saved Queries ------------------------------ +--------------------- .. code-block:: postgres diff --git a/reference/catalog_reference_schema_information.rst b/reference/catalog_reference_schema_information.rst index 6cd43ab6a..f91607dfa 100644 --- a/reference/catalog_reference_schema_information.rst +++ b/reference/catalog_reference_schema_information.rst @@ -1,8 +1,9 @@ .. _catalog_reference_schema_information: -************************************* +***************************************** What Information Does the Schema Contain? -************************************* +***************************************** + The schema includes tables designated and relevant for both external and internal use: .. contents:: @@ -10,7 +11,8 @@ The schema includes tables designated and relevant for both external and interna :depth: 1 External Tables ------------------ +--------------- + The following table shows the data objects contained in the ``sqream_catalog`` schema designated for external use: .. list-table:: Database Objects @@ -43,7 +45,8 @@ The following table shows the data objects contained in the ``sqream_catalog`` s - ``user_defined_functions`` Internal Tables ------------------ +--------------- + The following table shows the data objects contained in the ``sqream_catalog`` schema designated for internal use: .. list-table:: Storage Objects From 66c5313c8783c58055beab4458ffa8adca9d01d3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:10:36 +0300 Subject: [PATCH 0740/1892] architecture --- _static/images/sqream_db_table_crop.png | Bin 0 -> 92813 bytes architecture/index.rst | 5 +++++ architecture/internals_architecture.rst | 3 --- index.rst | 12 ++++++------ 4 files changed, 11 insertions(+), 9 deletions(-) create mode 100644 _static/images/sqream_db_table_crop.png diff --git a/_static/images/sqream_db_table_crop.png b/_static/images/sqream_db_table_crop.png new file mode 100644 index 0000000000000000000000000000000000000000..ed2ce13f217e33c739d94f5a96c4b07d8ba29a28 GIT binary patch literal 92813 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 OPe$^wMDD|9-v0-lq2Gi6 literal 0 HcmV?d00001 diff --git a/architecture/index.rst b/architecture/index.rst index 070b89a17..dd511a31e 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -6,6 +6,11 @@ System Architecture The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. +.. figure:: /_static/images/sqream_db_table_crop.png + :scale: 50 % + + + .. toctree:: :hidden: diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 334e0ef8f..9d50cccc5 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -6,9 +6,6 @@ Internals and Architecture Get to know the SQreamDB key functions and system architecture components and the best practices and customization possibilities. -High-Level Architecture Diagram -=============================== - .. figure:: /_static/images/sqream_db_internals.png :alt: SQreamDB internals diff --git a/index.rst b/index.rst index 64923ac0a..05aa05061 100644 --- a/index.rst +++ b/index.rst @@ -65,15 +65,15 @@ If you couldn't find what you're looking for, we're always happy to help. Visit getting_started/index installation_guides/index + architecture/index + configuration_guides/index + operational_guides/index + connecting_to_sqream/index + sqream_studio_5.4.7/index + feature_guides/index data_ingestion/index - connecting_to_sqream/index external_storage_platforms/index loading_and_unloading_data/index - feature_guides/index - operational_guides/index - sqream_studio_5.4.7/index - architecture/index - configuration_guides/index reference/index data_type_guides/index releases/index From 90e759a5b07ee3a4d4e4dd5fbaa062c53c879b24 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 14:11:03 +0300 Subject: [PATCH 0741/1892] Update index.rst --- architecture/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/index.rst b/architecture/index.rst index dd511a31e..de1e2e9e5 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -7,7 +7,7 @@ System Architecture The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. .. figure:: /_static/images/sqream_db_table_crop.png - :scale: 50 % + :scale: 40 % From 8aa9657e77701b653777d00fb92be8551b4c06b0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 10 Aug 2023 16:51:32 +0300 Subject: [PATCH 0742/1892] Sizing --- .../concurrency_and_scaling_in_sqream.rst | 29 +++-- .../optimization_best_practices.rst | 120 +++++++++--------- 2 files changed, 74 insertions(+), 75 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 910e5fdc4..712b6878c 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -4,14 +4,14 @@ Sizing ****** -Concurrency and Scaling in SQreamDB -=================================== +Concurrency +=========== -A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. +SQreamDB's concurrency is facilitated through a cluster of workers, allowing multiple statements to be executed simultaneously. The cluster can concurrently run one statement per worker process. Choosing the right number of workers for each SQreamDB cluster is crucial for finding the right balance between performance and concurrency. Assigning too many workers can cause resource issues, such as not having enough RAM, GRAM, CPU cores, or GPU cores. -SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a cluster. +The minimum resources required per Worker: -.. list-table:: Minimum Resource Required Per Worker +.. list-table:: :widths: auto :header-rows: 1 @@ -35,8 +35,10 @@ SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a clust - 8 - 8 - + +The maximum recommended Workers per GPU: -.. list-table:: Maximum Workers Per GPU +.. list-table:: :widths: auto :header-rows: 1 @@ -49,15 +51,16 @@ SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a clust - 3 - 6 +Scaling +======= - -Scaling When Data Sizes Grow ----------------------------- +When Data Sizes Grow +-------------------- For many statements, SQreamDB scales linearly when adding more storage and querying on large data sets. It uses optimized 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. -Scaling When Queries Are Queuing --------------------------------- +When Queries Are Queuing +------------------------ SQreamDB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. @@ -83,7 +86,7 @@ Example Configurations ---------------------- Setting Spool Memory -~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^ The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: @@ -104,7 +107,7 @@ The following is an example of setting ``spoolMemoryGB`` value per-worker for 51 } Recommended Settings -~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^ The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 2860b193b..2ed925d4b 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -1,68 +1,68 @@ .. _sql_best_practices: -********************************** +******************************* Optimization and Best Practices -********************************** +******************************* -This topic explains some best practices of working with SQream DB. +This topic explains some best practices of working with SQreamDB. See also our :ref:`monitoring_query_performance` guide for more information. -.. contents:: In this topic: :local: .. _table_design_best_practices: Table design -============== -This section describes best practices and guidelines for designing tables. +============ -Use date and datetime types for columns ------------------------------------------ -When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``TEXT`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQream DB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. +Using ``DATE`` and ``DATETIME`` Data Types +------------------------------------------ -Don't flatten or denormalize data ------------------------------------ +When creating tables with dates or timestamps, using the purpose-built ``DATE`` and ``DATETIME`` types over integer types or ``TEXT`` will bring performance and storage footprint improvements, and in many cases huge performance improvements (as well as data integrity benefits). SQreamDB stores dates and datetimes very efficiently and can strongly optimize queries using these specific types. + +Avoiding Data flattening and Denormalization +-------------------------------------------- -SQream DB executes JOIN operations very effectively. It is almost always better to JOIN tables at query-time rather than flatten/denormalize your tables. +SQreamDB executes ``JOIN`` operations very effectively. It is almost always better to ``JOIN`` tables at query-time rather than flatten/denormalize your tables. This will also reduce storage size and reduce row-lengths. -We highly suggest using ``INT`` or ``BIGINT`` as join keys, rather than a text/string type. +We highly suggest using ``INT`` or ``BIGINT`` as join keys, rather than a ``TEXT`` or ``STRING`` type. -Convert foreign tables to native tables -------------------------------------------- +Converting Foreign Tables to Native Tables +------------------------------------------ -SQream DB's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. +SQreamDB's native storage is heavily optimized for analytic workloads. It is always faster for querying than other formats, even columnar ones such as Parquet. It also enables the use of additional metadata to help speed up queries, in some cases by many orders of magnitude. -You can improve the performance of all operations by converting :ref:`foreign tables<external_tables>` into native tables by using the :ref:`create_table_as` syntax. +You can improve the performance of all operations by converting :ref:`foreign_tables` into native tables by using the :ref:`create_table_as` syntax. For example, .. code-block:: postgres - CREATE TABLE native_table AS SELECT * FROM external_table + CREATE TABLE native_table AS SELECT * FROM foreign_table; The one situation when this wouldn't be as useful is when data will be only queried once. -Use information about the column data to your advantage -------------------------------------------------------------- +Leveraging Column Data Information +---------------------------------- + Knowing the data types and their ranges can help design a better table. -Set ``NULL`` or ``NOT NULL`` when relevant -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Appropriately Using ``NULL`` and ``NOT NULL`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, if a value can't be missing (or ``NULL``), specify a ``NOT NULL`` constraint on the columns. +For example, if a value cannot be missing (or ``NULL``), specify a ``NOT NULL`` constraint on the columns. Not only does specifying ``NOT NULL`` save on data storage, it lets the query compiler know that a column cannot have a ``NULL`` value, which can improve query performance. Sorting -============== +======= Data sorting is an important factor in minimizing storage size and improving query performance. -* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQream DB reads during query execution. +* Minimizing storage saves on physical resources and increases performance by reducing overall disk I/O. Prioritize the sorting of low-cardinality columns. This reduces the number of chunks and extents that SQreamDB reads during query execution. * Where possible, sort columns with the lowest cardinality first. Avoid sorting ``TEXT`` columns with lengths exceeding 50 characters. @@ -70,17 +70,17 @@ Data sorting is an important factor in minimizing storage size and improving que .. _query_best_practices: -Query best practices -===================== +Query Best Practices +==================== This section describes best practices for writing SQL queries. -Reduce data sets before joining tables ------------------------------------------ +Reducing Datasets Before Joining Tables +--------------------------------------- Reducing the input to a ``JOIN`` clause can increase performance. -Some queries benefit from retreiving a reduced dataset as a subquery prior to a join. +Some queries benefit from retrieving a reduced dataset as a subquery prior to a join. For example, @@ -103,11 +103,11 @@ Can be rewritten as group by 2) AS fact ON dim.store_id=fact.store_id; -Prefer the ANSI JOIN ----------------------------- +Using ANSI ``JOIN`` +------------------- -SQream DB prefers the ANSI JOIN syntax. -In some cases, the ANSI JOIN performs better than the non-ANSI variety. +SQreamDB prefers the ANSI ``JOIN`` syntax. +In some cases, the ANSI ``JOIN`` performs better than the non-ANSI variety. For example, this ANSI JOIN example will perform better: @@ -121,7 +121,7 @@ For example, this ANSI JOIN example will perform better: JOIN "Customers" as c ON s.c_id = c.id AND c.id = 20301125; -This non-ANSI JOIN is supported, but not recommended: +This non-ANSI ``JOIN`` is supported, but not recommended: .. code-block:: postgres :caption: Non-ANSI JOIN may not perform well @@ -136,14 +136,14 @@ This non-ANSI JOIN is supported, but not recommended: .. _high_selectivity: -Use the high selectivity hint --------------------------------- +Using High-Selectivity hint +--------------------------- Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` -SQream DB has a hint function called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. +SQreamDB has a hint function called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. -The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk +The hint signals to SQreamDB that the result of the condition will be very sparse, and that it should attempt to rechunk the results into fewer, fuller chunks. Use the high selectivity hint when you expect a predicate to filter out most values. For example, when the data is dispersed over lots of chunks (meaning that the data is :ref:`not well-clustered<data_clustering>`). @@ -162,8 +162,8 @@ This hint tells the query compiler that the ``WHERE`` condition is expected to f Read more about identifying the scenarios for the high selectivity hint in our :ref:`Monitoring query performance guide<high_selectivity_data_opt>`. -Cast smaller types to avoid overflow in aggregates ------------------------------------------------------- +Avoiding Aggregation Overflow +----------------------------- When using an ``INT`` or smaller type, the ``SUM`` and ``COUNT`` operations return a value of the same type. To avoid overflow on large results, cast the column up to a larger type. @@ -176,33 +176,32 @@ For example GROUP BY 1; -Prefer ``COUNT(*)`` and ``COUNT`` on non-nullable columns ------------------------------------------------------------- +Prefer ``COUNT(*)`` and ``COUNT`` to Non-nullable Columns +--------------------------------------------------------- -SQream DB optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column will operate quickly, but much slower than the previous variations. +SQreamDB optimizes ``COUNT(*)`` queries very strongly. This also applies to ``COUNT(column_name)`` on non-nullable columns. Using ``COUNT(column_name)`` on a nullable column will operate quickly, but much slower than the previous variations. -Return only required columns +Returning Only Required Columns ------------------------------- Returning only the columns you need to client programs can improve overall query performance. This also reduces the overall result set, which can improve performance in third-party tools. -SQream is able to optimize out unneeded columns very strongly due to its columnar storage. +SQreamDB is able to optimize out unneeded columns very strongly due to its columnar storage. -Use saved queries to reduce recurring compilation time -------------------------------------------------------- +Reducing Recurring Compilation Time +----------------------------------- -:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQream DB's metadata for later re-use. +:ref:`saved_queries` are compiled when they are created. The query plan is saved in SQreamDB's metadata for later re-use. Saved query plans enable reduced compilation overhead, especially with very complex queries, such as queries with lots of values in an :ref:`IN` predicate. When executed, the saved query plan is recalled and executed on the up-to-date data stored on disk. -See how to use saved queries in the :ref:`saved queries guide<saved_queries>`. -Pre-filter to reduce :ref:`JOIN<joins>` complexity --------------------------------------------------------- +Reducing :ref:`JOIN<joins>` Complexity +-------------------------------------- Filter and reduce table sizes prior to joining on them @@ -231,23 +230,20 @@ Can be rewritten as: .. _data_loading_considerations: -Data loading considerations -================================= +Data Loading Considerations +=========================== -Allow and use natural sorting on data ----------------------------------------- +Using Natural Data Sorting +-------------------------- Very often, tabular data is already naturally ordered along a dimension such as a timestamp or area. -This natural order is a major factor for query performance later on, as data that is naturally sorted can be more easily compressed and analyzed with SQream DB's metadata collection. +This natural order is a major factor for query performance later on, as data that is naturally sorted can be more easily compressed and analyzed with SQreamDB's metadata collection. For example, when data is sorted by timestamp, filtering on this timestamp is more effective than filtering on an unordered column. Natural ordering can also be used for effective :ref:`delete` operations. -Further reading and monitoring query performance -======================================================= - -Read our :ref:`monitoring_query_performance` guide to learn how to use the built in monitoring utilities. -The guide also gives concerete examples for improving query performance. +Use the :ref:`monitoring_query_performance` guide to learn about built-in monitoring utilities. +The guide also gives concrete examples for improving query performance. From 733b64a6407b18b9aa8167382f5160798e24efbf Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 10:01:16 +0300 Subject: [PATCH 0743/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 910e5fdc4..02d23c59f 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -9,8 +9,6 @@ Concurrency and Scaling in SQreamDB A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. -SQreamDB supports ``n`` concurrent statements by having ``n`` workers in a cluster. - .. list-table:: Minimum Resource Required Per Worker :widths: auto :header-rows: 1 From 901a3c9fc112be2f6a81b4a26f9a00fc827407f2 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 11:28:01 +0300 Subject: [PATCH 0744/1892] Update index.rst --- architecture/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/architecture/index.rst b/architecture/index.rst index de1e2e9e5..5f298bfa0 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -16,4 +16,5 @@ The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` gui internals_architecture filesystem_and_filesystem_usage + concurrency_and_scaling_in_sqream From 6bdd34e4b412985171c64046a3e22ed9cc9adfff Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 11:52:08 +0300 Subject: [PATCH 0745/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 02d23c59f..24f8bb6e6 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -7,7 +7,7 @@ Sizing Concurrency and Scaling in SQreamDB =================================== -A SQreamDB cluster can concurrently run one regular statement per worker process. A number of small statements will execute alongside these statements without waiting or blocking anything. +A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. A number of small statements will execute alongside these statements without waiting or blocking anything. .. list-table:: Minimum Resource Required Per Worker :widths: auto @@ -25,11 +25,11 @@ A SQreamDB cluster can concurrently run one regular statement per worker process - 10 cores per 30 Workers - 128 per 1T rows (accumulated for all tables) - 10 - * - UI + * - SqreamDB Acceleration Studio - 16 - 16 - 50 - * - Picker + * - Server Picker - 8 - 8 - @@ -38,16 +38,19 @@ A SQreamDB cluster can concurrently run one regular statement per worker process :widths: auto :header-rows: 1 - * - T4 (16GB) - - V100 (32GB) - - A100 (40GB) - - A100 (80GB) + * - NVIDIA Tesla T4 (16GB) + - NVIDIA Tesla V100 (32GB) + - NVIDIA Tesla A100 (40GB) + - NVIDIA Tesla A100 (80GB) * - 1 - 2 - 3 - 6 +.. rubric:: The GPU you are using is not on the list? + +Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. Scaling When Data Sizes Grow ---------------------------- From ae86bd20c263af5045077a7ab383b7b34c3b4fd4 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 12:18:32 +0300 Subject: [PATCH 0746/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 24f8bb6e6..45f6a724f 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -9,6 +9,8 @@ Concurrency and Scaling in SQreamDB A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. A number of small statements will execute alongside these statements without waiting or blocking anything. +Utility functions that require little resources such as :ref:`show_server_status`, will be executed regardless of load. + .. list-table:: Minimum Resource Required Per Worker :widths: auto :header-rows: 1 From 895e0186d78de534f57c39ea548fc7c77112a437 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 12:19:40 +0300 Subject: [PATCH 0747/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 45f6a724f..54b7139ef 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -7,9 +7,7 @@ Sizing Concurrency and Scaling in SQreamDB =================================== -A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. A number of small statements will execute alongside these statements without waiting or blocking anything. - -Utility functions that require little resources such as :ref:`show_server_status`, will be executed regardless of load. +A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions that require little resources such as :ref:`show_server_status`, will be executed regardless of load. .. list-table:: Minimum Resource Required Per Worker :widths: auto From 8d900944a26ae61d260a949286207db87be9a851 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 12:22:07 +0300 Subject: [PATCH 0748/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 54b7139ef..8255b75b1 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -7,7 +7,7 @@ Sizing Concurrency and Scaling in SQreamDB =================================== -A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions that require little resources such as :ref:`show_server_status`, will be executed regardless of load. +A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions with minimal resource requirements, such as :ref:`show_server_status`, will be executed regardless of the workload. .. list-table:: Minimum Resource Required Per Worker :widths: auto From 1b7315b25749946fc5fa888644e4c9b903c21226 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 13 Aug 2023 12:31:13 +0300 Subject: [PATCH 0749/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 8255b75b1..ec2cabce0 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -48,7 +48,7 @@ A SQreamDB cluster can execute one statement per worker process while also suppo - 6 -.. rubric:: The GPU you are using is not on the list? +.. tip:: The GPU you're using is not on the list? Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. From cced9e53b04678e60a554eb351fee958f145044a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 14 Aug 2023 08:33:51 +0300 Subject: [PATCH 0750/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 712b6878c..e33b97379 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -4,14 +4,12 @@ Sizing ****** -Concurrency -=========== +Concurrency and Scaling in SQreamDB +=================================== -SQreamDB's concurrency is facilitated through a cluster of workers, allowing multiple statements to be executed simultaneously. The cluster can concurrently run one statement per worker process. Choosing the right number of workers for each SQreamDB cluster is crucial for finding the right balance between performance and concurrency. Assigning too many workers can cause resource issues, such as not having enough RAM, GRAM, CPU cores, or GPU cores. +A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions with minimal resource requirements, such as :ref:`show_server_status`, will be executed regardless of the workload. -The minimum resources required per Worker: - -.. list-table:: +.. list-table:: Minimum Resource Required Per Worker :widths: auto :header-rows: 1 @@ -26,41 +24,41 @@ The minimum resources required per Worker: * - Metadata Server - 10 cores per 30 Workers - 128 per 1T rows (accumulated for all tables) - - 10 - * - UI + - 10 + * - SqreamDB Acceleration Studio - 16 - 16 - 50 - * - Picker + * - Server Picker - 8 - 8 - - -The maximum recommended Workers per GPU: -.. list-table:: +.. list-table:: Maximum Workers Per GPU :widths: auto :header-rows: 1 - * - T4 (16GB) - - V100 (32GB) - - A100 (40GB) - - A100 (80GB) + * - NVIDIA Tesla T4 (16GB) + - NVIDIA Tesla V100 (32GB) + - NVIDIA Tesla A100 (40GB) + - NVIDIA Tesla A100 (80GB) * - 1 - 2 - 3 - 6 -Scaling -======= -When Data Sizes Grow --------------------- +.. tip:: The GPU you're using is not on the list? + +Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. + +Scaling When Data Sizes Grow +---------------------------- For many statements, SQreamDB scales linearly when adding more storage and querying on large data sets. It uses optimized 'brute force' algorithms and implementations, which don't suffer from sudden performance cliffs at larger data sizes. -When Queries Are Queuing ------------------------- +Scaling When Queries Are Queuing +-------------------------------- SQreamDB scales well by adding more workers, GPUs, and nodes to support more concurrent statements. @@ -86,7 +84,7 @@ Example Configurations ---------------------- Setting Spool Memory -^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~ The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: @@ -107,7 +105,7 @@ The following is an example of setting ``spoolMemoryGB`` value per-worker for 51 } Recommended Settings -^^^^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~~~~ The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: From 38099569605486a0b45287e691e12b5a447077b5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 14 Aug 2023 08:50:40 +0300 Subject: [PATCH 0751/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index e33b97379..e3edd447a 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -9,7 +9,9 @@ Concurrency and Scaling in SQreamDB A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions with minimal resource requirements, such as :ref:`show_server_status`, will be executed regardless of the workload. -.. list-table:: Minimum Resource Required Per Worker +Minimum Resource Required Per Worker: + +.. list-table:: :widths: auto :header-rows: 1 @@ -33,24 +35,27 @@ A SQreamDB cluster can execute one statement per worker process while also suppo - 8 - 8 - + +Maximum Workers Per GPU: -.. list-table:: Maximum Workers Per GPU +.. list-table:: :widths: auto :header-rows: 1 - * - NVIDIA Tesla T4 (16GB) - - NVIDIA Tesla V100 (32GB) - - NVIDIA Tesla A100 (40GB) - - NVIDIA Tesla A100 (80GB) - * - 1 + * - GPU + - Workers + * - NVIDIA Tesla T4 (16GB) + - 1 + * - NVIDIA Tesla V100 (32GB) - 2 - - 3 + * - NVIDIA Tesla A100 (40GB) + - 3 + * - NVIDIA Tesla A100 (80GB) - 6 -.. tip:: The GPU you're using is not on the list? -Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. +.. tip:: Your GPU is not on the list? Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. Scaling When Data Sizes Grow ---------------------------- From 500218f27cdef7a903024e3b1de4d6b896cdffdc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:19:38 +0300 Subject: [PATCH 0752/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index e3edd447a..6fa22c987 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -25,7 +25,7 @@ Minimum Resource Required Per Worker: - 10 * - Metadata Server - 10 cores per 30 Workers - - 128 per 1T rows (accumulated for all tables) + - 128 per 1T rows (1M chunks) - 10 * - SqreamDB Acceleration Studio - 16 @@ -35,6 +35,11 @@ Minimum Resource Required Per Worker: - 8 - 8 - + * - Operational statements such as :ref:`copy_to` and :ref:`Clean-Up<delete_guide>` + - + - 64 + - + Maximum Workers Per GPU: @@ -52,11 +57,12 @@ Maximum Workers Per GPU: - 3 * - NVIDIA Tesla A100 (80GB) - 6 + * - NVIDIA Tesla H100 (80GB) + - 6 - - .. tip:: Your GPU is not on the list? Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. + Scaling When Data Sizes Grow ---------------------------- From 36271444e9e6478aba671b427a49d7f5d2692a03 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 16 Aug 2023 08:49:53 +0300 Subject: [PATCH 0753/1892] Update executing_statements_and_running_queries_from_the_editor.rst --- ...executing_statements_and_running_queries_from_the_editor.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst index 22666c2bd..76baf51c2 100644 --- a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst @@ -200,8 +200,6 @@ The database object functions are used to perform the following: - Generates an `RENAME TABLE AS <https://docs.sqream.com/en/latest/reference/sql/sql_statements/ddl_commands/rename_table.html#rename-table>`_ statement for renaming the selected table in the editing area. * - Adding column statement - Generates an `ADD COLUMN <https://docs.sqream.com/en/latest/reference/sql/sql_statements/ddl_commands/add_column.html#add-column>`_ statement for adding columns to the selected table in the editing area. - * - Truncate table statement - - Generates a `TRUNCATE_IF_EXISTS <https://docs.sqream.com/en/latest/reference/sql/sql_statements/dml_commands/truncate_if_exists.html#truncate>`_ statement for the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL From f5c999d4e7118da5e0e56b8db77bd12e4f343f2f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 16 Aug 2023 08:54:37 +0300 Subject: [PATCH 0754/1892] Update executing_statements_and_running_queries_from_the_editor.rst --- .../executing_statements_and_running_queries_from_the_editor.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst index 76baf51c2..2a2a9475e 100644 --- a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst @@ -278,7 +278,6 @@ You can add and name new tabs for each statement that you need to execute, and S You can also rename the default tab name by double-clicking it and typing a new name and write multiple statements in tandem in the same tab by separating them with semicolons (``;``).If too many tabs to fit into the Statement Pane are open at the same time, the tab arrows are displayed. You can scroll through the tabs by clicking |icon-left| or |icon-right|, and close tabs by clicking |icon-close|. You can also close all tabs at once by clicking **Close all** located to the right of the tabs. -.. tip:: If this is your first time using SQreamDB, see :ref:`Getting Started <getting_started>`. .. Keyboard shortcuts From 146412bcf232ea8b88555772cc0b81b2ea17f723 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:33:15 +0300 Subject: [PATCH 0755/1892] Update charindex.rst --- .../scalar_functions/string/charindex.rst | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index e519d31e7..f4e859fce 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -4,7 +4,7 @@ CHARINDEX ********* -``CHARINDEX`` is a 1-based indexing function that returns the starting position of a specified substring within a given string. +``CHARINDEX`` is a 1-based indexing function (both input and output) that returns the starting position of a specified substring within a given string. See also :ref:`patindex`, :ref:`regexp_instr`. @@ -39,25 +39,24 @@ Integer start position of a match, or 0 if no match was found. If one of the parameters is NULL, then the return value is NULL. +Empty string search returns 0. + Examples ======== -For these examples, consider the following table and contents: +For these examples, consider the following table: -.. code-block:: sql +.. code-block:: none - CREATE TABLE users ( - id INT, - username TEXT, - email TEXT, - password TEXT - ); - - INSERT INTO users (id, username, email, password) - VALUES (1, 'john_doe', 'john.doe@example.com', 'password1'), - (2, 'jane_doe', 'jane.doe@example.com', 'password2'), - (3, 'bob_smith', 'bob.smith@example.com', 'password3'), - (4, 'susan_jones', 'susan.jones@example.com', 'password4'); + id | username | email | password + ----+-------------+-------------------------+----------- + 1 | john_doe | john.doe@example.com | password1 + ----+-------------+-------------------------+----------- + 2 | jane_doe | jane.doe@example.com | password2 + ----+-------------+-------------------------+----------- + 3 | bob_smith | bob.smith@example.com | password3 + ----+-------------+-------------------------+----------- + 4 | susan_jones | susan.jones@example.com | password4 Using ``CHARINDEX`` From c4dbfb000357e37cb4bc404476ce634ce947ee9d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 16 Aug 2023 13:56:18 +0300 Subject: [PATCH 0756/1892] Update charindex.rst --- .../scalar_functions/string/charindex.rst | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/charindex.rst b/reference/sql/sql_functions/scalar_functions/string/charindex.rst index f4e859fce..893332d7d 100644 --- a/reference/sql/sql_functions/scalar_functions/string/charindex.rst +++ b/reference/sql/sql_functions/scalar_functions/string/charindex.rst @@ -59,9 +59,6 @@ For these examples, consider the following table: 4 | susan_jones | susan.jones@example.com | password4 -Using ``CHARINDEX`` -------------------- - .. code-block:: sql SELECT CHARINDEX('doe', username) FROM users; @@ -76,5 +73,31 @@ Output: 6 | 0 | 0 | + +.. code-block:: sql + + SELECT CHARINDEX('doe', username, 10) FROM users; + +Output: + +.. code-block:: none + + charindex| + ---------+ + 0 | + 0 | + 0 | + 0 | +.. code-block:: sql + SELECT CHARINDEX('jane_doe', username, -10) FROM users; + +.. code-block:: none + + charindex| + ---------+ + 0 | + 1 | + 0 | + 0 | \ No newline at end of file From 53094a2f20a55c9821c7bddf6f024c3ed6bd80db Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 16 Aug 2023 14:17:00 +0300 Subject: [PATCH 0757/1892] Update sign.rst --- .../sql_functions/scalar_functions/numeric/sign.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst index db2ff7547..b86f9c573 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst @@ -1,15 +1,15 @@ .. _sign: -************************** +**** SIGN -************************** +**** The ``SIGN`` function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL, and returns an ``INT`` value of -1, 0, or 1, depending on the sign of the input argument. Syntax -========== +====== .. code-block:: postgres @@ -29,7 +29,8 @@ Arguments Return ====== -Returns an output of the same data type as the input data type. + +Returns an ``INT`` value. Depending on the sign of the input argument, the return is: @@ -50,7 +51,7 @@ Example Output: -.. code-block:: postgres +.. code-block:: none sign | sign0 | sign1 -----+------+------- From 90de44c3f38ad88ce0fab08fb9c5f07c048e6b3e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 17 Aug 2023 08:41:48 +0300 Subject: [PATCH 0758/1892] Update crc64.rst --- .../sql_functions/scalar_functions/numeric/crc64.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst index 4fb4dfdc0..de3693aa2 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/crc64.rst @@ -30,15 +30,15 @@ Returns Returns a CRC-64 hash of the text input, of type ``BIGINT``. -.. note:: If the input value is NULL, the result is NULL. +If the input value is ``NULL``, the result is ``NULL``. Examples ======== -Calculate a CRC-64 hash of a string ------------------------------------ - -.. code-block:: psql +.. code-block:: sql SELECT CRC64(x) FROM (VALUES ('This is a relatively long text string, that can be converted to a shorter hash' :: text)) as t(x); - -8397827068206190216 \ No newline at end of file + +.. code-block:: none + + -8397827068206190216 \ No newline at end of file From 32255273ec4ff90c3a308216808738a2c10450c1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 17 Aug 2023 09:54:30 +0300 Subject: [PATCH 0759/1892] Create whats_new.rst --- releases/whats_new.rst | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 releases/whats_new.rst diff --git a/releases/whats_new.rst b/releases/whats_new.rst new file mode 100644 index 000000000..1727451a6 --- /dev/null +++ b/releases/whats_new.rst @@ -0,0 +1,8 @@ +.. _whats_new: + +********** +What's New +********** + + + From 7a2fcfb253dd9d805fedfd549cd7cb5912076986 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 17 Aug 2023 10:55:39 +0300 Subject: [PATCH 0760/1892] Release highlights --- releases/4.3.rst | 2 -- releases/index.rst | 1 + releases/whats_new.rst | 29 ++++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 35e00d73b..eb0ecebfe 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -34,8 +34,6 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► A new :re:`SQLoader <ingesting_from_databases>` will enable you to load data into SQreamDB from other databases. - ► Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: * VIEWS diff --git a/releases/index.rst b/releases/index.rst index 25b834bc6..29458712d 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -31,6 +31,7 @@ Release Notes :glob: :hidden: + whats_new 4.0_index 2022.1_index 2021.2_index diff --git a/releases/whats_new.rst b/releases/whats_new.rst index 1727451a6..3b2ac0863 100644 --- a/releases/whats_new.rst +++ b/releases/whats_new.rst @@ -1,8 +1,31 @@ .. _whats_new: -********** -What's New -********** +****************** +Release Highlights +****************** + +:ref:`Version 4.3<4.3>` + +* `Access Control Permissions Expansion <https://docs.sqream.com/en/latest/releases/4.3.html#new-features-and-enhancements>`_ +* `New AWS S3 Access Configurations <https://docs.sqream.com/en/latest/releases/4.3.html#configuration-adjustments>`_ + +:ref:`Version 4.2<4.2>` + +* `New Apache Spark Connector <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ +* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ + +:ref:`Version 4.1<4.1>` + +* `LDAP Management Enhancements <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ +* `New Trino Connector <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ +* `Brute-Force Attack Protection <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ + +:ref:`Version 4.0<4.0>` + +* `SQreamDB License Storage Capacity <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ +* `LDAP Authentication <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ +* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ + From 49ab66d300243355f9274757ba781e8427c4c97f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 17 Aug 2023 15:07:36 +0300 Subject: [PATCH 0761/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 6fa22c987..d1d5c780a 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -25,7 +25,7 @@ Minimum Resource Required Per Worker: - 10 * - Metadata Server - 10 cores per 30 Workers - - 128 per 1T rows (1M chunks) + - 128 per 1T rows (optimally 1M chunks) - 10 * - SqreamDB Acceleration Studio - 16 @@ -35,11 +35,9 @@ Minimum Resource Required Per Worker: - 8 - 8 - - * - Operational statements such as :ref:`copy_to` and :ref:`Clean-Up<delete_guide>` - - - - 64 - - - + + +Lightweight queries, such as :ref:`copy_to` and :ref:`Clean-Up<delete_guide>` require 64 RAM (GB). Maximum Workers Per GPU: @@ -60,6 +58,8 @@ Maximum Workers Per GPU: * - NVIDIA Tesla H100 (80GB) - 6 + + .. tip:: Your GPU is not on the list? Visit `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional information. From ed893ceeb6cad9490f371802705b4bb8b123be14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 17 Aug 2023 16:29:37 +0300 Subject: [PATCH 0762/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 42 ++++++++++++------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index d1d5c780a..9c960010f 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -85,19 +85,21 @@ Adding additional RAM to nodes, using more GPU memory, and faster CPUs or storag Spooling Configuration ====================== -From the SQreamDB Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. +:math:`limitQueryMemoryGB=\frac{\text{Total RAM - Internal Operation - metadata Server - Server picker}}{\text{Number of Workers}}` -In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. +:math:`spoolMemoryGB=limitQueryMemoryGB - 50GB` -Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. +SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. -Example Configurations ----------------------- +Example +------- Setting Spool Memory ~~~~~~~~~~~~~~~~~~~~ -The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: +The following examples are for 2T of RAM and 9 workers running on 3 A100(40) GPUs: + +Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: .. code-block:: console @@ -110,20 +112,28 @@ The following is an example of setting ``spoolMemoryGB`` value per-worker for 51 “metadataServerPort”: “3105, “port”: 5000, “useConfigIP”” true, - “limitQueryMemoryGB" : 121, - “spoolMemoryGB" : 108 - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + “limitQueryMemoryGB" : 201, } -Recommended Settings -~~~~~~~~~~~~~~~~~~~~ - -The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: +Configuring the ``spoolMemoryGB`` using the legacy configuration file: .. code-block:: console - - limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 - spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 + + { + "diskSpaceMinFreePercent": 10, + "enableLogDebug": false, + "insertCompressors": 8, + "insertParsers": 8, + "isUnavailableNode": false, + "logBlackList": "webui", + "logDebugLevel": 6, + "nodeInfoLoggingSec": 60, + "useClientLog": true, + "useMetadataServer": true, + "spoolMemoryGB": 151, + "waitForClientSeconds": 18000, + "enablePythonUdfs": true + } .. rubric:: Need help? From 6ad2585adf27118d3ea01c6702f6823cac82fecf Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 20 Aug 2023 11:59:53 +0300 Subject: [PATCH 0763/1892] Update index.rst --- releases/index.rst | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 29458712d..2e13d5e85 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,26 +4,27 @@ Release Notes ************* - -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Version - - Release Date - * - :ref:`4.4` - - xxxxxxx xx, xxxx - * - :ref:`4.3` - - June 11, 2023 - * - :ref:`4.2` - - April 23, 2023 - * - :ref:`4.1` - - March 01, 2023 - * - :ref:`4.0` - - January 25, 2023 +:ref:`Version 4.3 - June 11, 2023<4.3>` +* `Access Control Permissions Expansion <https://docs.sqream.com/en/latest/releases/4.3.html#new-features-and-enhancements>`_ +* `New AWS S3 Access Configurations <https://docs.sqream.com/en/latest/releases/4.3.html#configuration-adjustments>`_ +:ref:`Version 4.2 - April 23, 2023<4.2>` + +* `New Apache Spark Connector <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ +* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ + +:ref:`Version 4.1 - March 01, 2032<4.1>` + +* `LDAP Management Enhancements <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ +* `New Trino Connector <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ +* `Brute-Force Attack Protection <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ + +:ref:`Version 4.0 - January 25, 2023<4.0>` + +* `SQreamDB License Storage Capacity <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ +* `LDAP Authentication <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ +* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ .. toctree:: @@ -35,7 +36,4 @@ Release Notes 4.0_index 2022.1_index 2021.2_index - 2021.1_index - 2020.3_index - 2020.2 - 2020.1 \ No newline at end of file + From 3eb596ec4e28caab58f65f52920b80ed259bfe0b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 20 Aug 2023 12:00:51 +0300 Subject: [PATCH 0764/1892] Delete whats_new.rst --- releases/whats_new.rst | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 releases/whats_new.rst diff --git a/releases/whats_new.rst b/releases/whats_new.rst deleted file mode 100644 index 3b2ac0863..000000000 --- a/releases/whats_new.rst +++ /dev/null @@ -1,31 +0,0 @@ -.. _whats_new: - -****************** -Release Highlights -****************** - -:ref:`Version 4.3<4.3>` - -* `Access Control Permissions Expansion <https://docs.sqream.com/en/latest/releases/4.3.html#new-features-and-enhancements>`_ -* `New AWS S3 Access Configurations <https://docs.sqream.com/en/latest/releases/4.3.html#configuration-adjustments>`_ - -:ref:`Version 4.2<4.2>` - -* `New Apache Spark Connector <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ -* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ - -:ref:`Version 4.1<4.1>` - -* `LDAP Management Enhancements <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ -* `New Trino Connector <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ -* `Brute-Force Attack Protection <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ - -:ref:`Version 4.0<4.0>` - -* `SQreamDB License Storage Capacity <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ -* `LDAP Authentication <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ -* `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.0.html#new-features>`_ - - - - From bdb90e5bb1b818a55a5fbdbc1365e077a50cc581 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 20 Aug 2023 17:03:38 +0300 Subject: [PATCH 0765/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index abb5d59af..6dc8a2b03 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -58,7 +58,7 @@ The following table shows the supported data types. * - ``NUMERIC`` - 38 digits - 16 bytes - - ``0.123245678901234567890123456789012345678`` + - ``0.12324567890123456789012345678901234567`` - ``DECIMAL`` * - ``DATE`` - Date @@ -76,4 +76,4 @@ The following table shows the supported data types. - ``[1,2,3]`` - NA -.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. \ No newline at end of file +.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. From 8abd05e41bada8cb8b6cb2a46162f03ceb339841 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 20 Aug 2023 17:15:34 +0300 Subject: [PATCH 0766/1892] Update sql_data_types_numeric.rst --- data_type_guides/sql_data_types_numeric.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/data_type_guides/sql_data_types_numeric.rst b/data_type_guides/sql_data_types_numeric.rst index 8d63a82f5..cb1b7a810 100644 --- a/data_type_guides/sql_data_types_numeric.rst +++ b/data_type_guides/sql_data_types_numeric.rst @@ -1,8 +1,9 @@ .. _sql_data_types_numeric: -************************* +******* Numeric -************************* +******* + The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point <floating_point>` is recommended. The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. If no parameters are specified, Numeric defaults to ``numeric(38, 0)``. @@ -15,7 +16,7 @@ The following is an example of the Numeric syntax: .. code-block:: postgres CREATE OR REPLACE table t(x numeric(20, 10), y numeric(38, 38)); - INSERT INTO t VALUES(1234567890.1234567890, 0.123245678901234567890123456789012345678); + INSERT INTO t VALUES(1234567890.1234567890, 0.12324567890123456789012345678901234567); SELECT x + y FROM t; The following table shows information relevant to the Numeric data type: @@ -29,10 +30,10 @@ The following table shows information relevant to the Numeric data type: - Example * - 38 digits - 16 bytes - - ``0.123245678901234567890123456789012345678`` + - ``0.12324567890123456789012345678901234567`` Numeric supports the following operations: * All join types. * All aggregation types (not including Window functions). - * Scalar functions (not including some trigonometric and logarithmic functions). \ No newline at end of file + * Scalar functions (not including some trigonometric and logarithmic functions). From b5f9bababcd267ac41c0d51b9b026ef9a624577b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 08:30:11 +0300 Subject: [PATCH 0767/1892] Update drop_saved_query.rst --- .../sql/sql_statements/utility_commands/drop_saved_query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst index 9e7d8d725..f8174edd2 100644 --- a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst @@ -8,7 +8,7 @@ DROP_SAVED_QUERY Read more in the :ref:`saved_queries<saved_queries>` guide. -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`show_saved_query`, ref:`list_saved_queries`. +See also: :ref:`save_query`, :ref:`execute_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. Permissions ============= From cef41c6aad11df0e55c6d8b5c030cf93cd715d45 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 08:34:45 +0300 Subject: [PATCH 0768/1892] Update execute_saved_query.rst --- .../sql/sql_statements/utility_commands/execute_saved_query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index 39675d47f..fdc626577 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -109,7 +109,7 @@ Use parameters to replace them later at execution time. .. tip:: Use dollar quoting (`$$`) to avoid escaping strings. - .. code-block:: psql +.. code-block:: psql t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); executed From ee899ef03c694821d9323e42bf19fa4697c28c0d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 08:38:47 +0300 Subject: [PATCH 0769/1892] Update list_saved_queries.rst --- .../sql/sql_statements/utility_commands/list_saved_queries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst index bb1781840..a50bbc43f 100644 --- a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst +++ b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst @@ -10,7 +10,7 @@ This is an alternative way to using the ``savedqueries`` catalog view. Read more in the :ref:`saved_queries` guide. -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`show_saved_query`. +See also: :ref:`save_query`, :ref:`execute_saved_query`, :ref:`drop_saved_query`, :ref:`show_saved_query` Permissions ============= From f1b721085daabbcd15ae131a095b5b2422276965 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 09:09:31 +0300 Subject: [PATCH 0770/1892] Update is_ascii.rst --- .../scalar_functions/conditionals/is_ascii.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst index 495e46e76..3f2b5fb86 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_ascii.rst @@ -55,9 +55,9 @@ IS NULL .. code-block:: psql id | text | is_ascii - ---+----------+----------+--------- - 1 | 行こう | false - 2 | 乾杯 | false - 3 | L'chaim | true + ---+----------+---------- + 1 | 行こう | false + 2 | 乾杯 | false + 3 | L'chaim | true From 25ed8a615d1e38bde269cf6342fc9c1eee63d56e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:11:29 +0300 Subject: [PATCH 0771/1892] Update power_bi.rst --- connecting_to_sqream/client_platforms/power_bi.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index ec95ab7f3..2c19567d3 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -4,9 +4,6 @@ BI Desktop ********** -Overview -======== - **Power BI Desktop** lets you connect to SQream and use underlying data as with other data sources in Power BI Desktop. SQream integrates with Power BI Desktop to do the following: @@ -57,11 +54,11 @@ Installing Power BI Desktop For information about downloading and configuring your ODBC driver, see :ref:`ODBC <odbc>` or contact `SQream Support <https://sqream.atlassian.net/servicedesk/>`_. -#. Navigate to **Windows** > **Documents** and create a folder called **Power BI Desktop Custom Connectors**. +#. Navigate to **Windows** > **Documents** and create a folder named **Power BI Desktop** with a subfolder named **Custom Connectors**. :: -#. From the Client Drivers page, download the **PowerQuery.mez** file. +#. From the Client Drivers page, :ref:`download<client_drivers>` the **PowerQuery.mez** file. :: From 2125c682a5b21d3c122bce825e32486eee6b3839 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:32:06 +0300 Subject: [PATCH 0772/1892] Update logging.rst --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 90499e971..28ffca44b 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -374,7 +374,7 @@ Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a databas OPTIONS ( LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', - DELIMITER = '|' + DELIMITER = '|', CONTINUE_ON_ERROR = true ) ; From f8d6c888e1f3278c73fac397a0436a19ffc5ed7e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 08:55:57 +0300 Subject: [PATCH 0773/1892] Update trunc.rst --- .../sql/sql_functions/scalar_functions/date_and_time/trunc.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index e3511281f..442fc7e4b 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -8,7 +8,8 @@ Truncates a ``DATE`` or ``DATETIME`` value to a specified resolution. For example, truncating a ``DATE`` down to the nearest month returns the date of the first day of the month. -.. note:: This function is overloaded. The function :ref:`TRUNC<trunc>` can also round numbers towards zero. +.. note:: * This function is overloaded. The function :ref:`TRUNC<trunc>` can also round numbers towards zero. + * Specifying the ``MILLISECOND`` interval with the ``TRUNC`` function is redundant, as there is nothing smaller than milliseconds. Syntax ========== From 1b584e9e94beea8696db2ee55a404dd28b8d412c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:10:18 +0300 Subject: [PATCH 0774/1892] Update 4.4.rst --- releases/4.4.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index b12c2cdc8..6f81fc55a 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -104,11 +104,7 @@ The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_ ► ``VARCHAR`` -The ``VARCHAR`` data type is deprecated to improve the core functionalities of the platform and to align with the constantly evolving ecosystem requirements. - -* Support in the ``VARCHAR`` data type ends at September 30th, 2023. -* ``VARCHAR`` is no longer supported for new customers, effective from version 2022.1.3. -* The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. +With the improvement of the core functionalities of the platform and to align with the constantly evolving ecosystem requirements, the ``VARCHAR`` data type is deprecated and may not be used. The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. Upgrading to v4.4 ----------------- From a57064c8b44408fe31f9d9f0aae6a62289bb8a68 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:17:58 +0300 Subject: [PATCH 0775/1892] Update index.rst --- connecting_to_sqream/client_drivers/trino/index.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index 700e15801..c8c67a068 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -5,7 +5,7 @@ Trino ***** -If you are using Trino for distributed SQL query processing and wish to use it to connect to a SQream, follow these instructions. +If you are using Trino for distributed SQL query processing and wish to use it to connect to BLUE, follow these instructions. .. contents:: @@ -15,7 +15,7 @@ If you are using Trino for distributed SQL query processing and wish to use it t Prerequisites ------------- -To use Trino with SQream, you must have the following installed: +To use Trino with BLUE, you must have the following installed: * SQream version 4.1 or later * Trino version 403 or later @@ -34,7 +34,7 @@ Installation JDBC ~~~~ -In case JDBC is not yet configured, follow the `JDBC Client Drivers page <https://docs.sqream.com/en/v2021.1/third_party_tools/client_drivers/jdbc/index.html>`_ for registration and configuration guidance. +In case JDBC is not yet configured, follow the :ref:`JDBC Client Drivers page<java_jdbc>` for registration and configuration guidance. Trino Connector @@ -126,15 +126,11 @@ Use the appropriate Trino data type for executing queries. Upon execution, incom - ``DATE`` * - ``TIMESTAMP`` - ``DATETIME`` - * - ``VARCHAR(N)`` - - ``VARCHAR(N)``. * - ``VARCHAR`` - ``TEXT`` * - ``DECIMAL(P,S)`` - ``NUMERIC(P,S)`` -.. note:: ``VARCHAR`` is soon to be deprecated and may not be used in SQream DB. - Limitations ----------- @@ -143,4 +139,4 @@ The Trino Connector does not support the following SQL statements: * ``GRANT`` * ``REVOKE`` * ``SHOW GRANTSHOW ROLES`` -* ``SHOW ROLE GRANTS`` \ No newline at end of file +* ``SHOW ROLE GRANTS`` From 8410e777bc4859e876d408eac9d7e044fe120ae2 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:26:31 +0300 Subject: [PATCH 0776/1892] Update ingesting_data.rst --- data_ingestion/ingesting_data.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index db157f6b4..0fedaec14 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -291,7 +291,7 @@ The following list shows the best practices when ingesting data from ORC files: Type Support and Behavior Notes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -You must load ORC files through foreign table. Note that the destination table structure must be identical to the number of columns between the source files. +You must load ORC files through a foreign table. Note that the destination table structure must be identical to the number of columns between the source files. For more information, see :ref:`foreign_tables`. @@ -312,7 +312,7 @@ The types should match to some extent within the same "class", as shown in the f - ``BIGINT`` - ``REAL`` - ``DOUBLE`` - - Text [#f0]_ + - ``TEXT`` - ``DATE`` - ``DATETIME`` * - ``boolean`` @@ -426,7 +426,7 @@ The types should match to some extent within the same "class", as shown in the f - - Supported -* If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be ommited. +* If an ORC file has an unsupported type like ``binary``, ``list``, ``map``, and ``union``, but the data is not referenced in the table (it does not appear in the :ref:`SELECT` query), the statement will succeed. If the column is referenced, an error will be thrown to the user, explaining that the type is not supported, but the column may be omitted. @@ -480,8 +480,6 @@ For more information, see the following: .. rubric:: Footnotes -.. [#f0] Text values include ``TEXT``, ``VARCHAR``, and ``NVARCHAR`` - .. [#f2] With UTF8 annotation .. [#f3] With ``TIMESTAMP_NANOS`` or ``TIMESTAMP_MILLIS`` annotation @@ -492,4 +490,4 @@ For more information, see the following: .. [#f6] Will succeed if all values are 0, 1 -.. [#f7] Will succeed if all values fit the destination type \ No newline at end of file +.. [#f7] Will succeed if all values fit the destination type From 69a37023ed745756a74bb25a221db0b7bd0f7a2c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:28:57 +0300 Subject: [PATCH 0777/1892] Update current_method_showing_all_flags_in_the_catalog_table.rst --- ...urrent_method_showing_all_flags_in_the_catalog_table.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst index bdcbb39ff..7400684f7 100644 --- a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -16,7 +16,7 @@ The following is an example of a catalog table query: .. code-block:: console - externalTableBlobEstimate, 100, 100, default, - varcharEncoding, ascii, ascii, default, Changes the expected encoding for Varchar columns + externalTableBlobEstimate, 100, 100, default, + ascii, ascii, default, Changes the expected encoding for Varchar columns useCrcForTextJoinKeys, true, true, default, - hiveStyleImplicitStringCasts, false, false, default, \ No newline at end of file + hiveStyleImplicitStringCasts, false, false, default, From 5e65f52a9f0c7c5145b1addfce45c89df8b43326 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:31:53 +0300 Subject: [PATCH 0778/1892] Update literals.rst --- reference/sql/sql_syntax/literals.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 906684590..4fc741ca4 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -86,7 +86,7 @@ Examples '1997-01-01' -- This is a string -The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``VARCHAR``. +The actual data type of the value changes based on context, the format used, and the value itself. In the example below, the first value is interpreted as a ``DATE``, while the second is interpreted as a ``TEXT``. .. code-block:: postgres @@ -103,6 +103,7 @@ This section describes the following types of literals: Regular String Literals ----------------------- + In SQL, a **regular string literal** is a sequence of zero or more characters bound by single quotes (``'``): .. code-block:: postgres @@ -135,7 +136,8 @@ The following are some examples of regular string literals: .. _dollar_quoted_string_literals: Dollar-Quoted String Literals ------------------------ +----------------------------- + **Dollar-quoted string literals** consist of a dollar sign (``$``), an optional "tag" of zero or more characters, another dollar sign, an arbitrary sequence of characters that make up the string content, a dollar sign, the same tag at the beginning of the dollar quote, and another dollar sign. @@ -239,7 +241,6 @@ The following is a syntax reference for typed literals: | REAL | DATE | DATETIME - | VARCHAR ( digits ) | TEXT ( digits ) Examples From 55f9069d844aa3fd48b72e82533a5daab37fe836 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:34:31 +0300 Subject: [PATCH 0779/1892] Update trunc.rst --- .../sql/sql_functions/scalar_functions/date_and_time/trunc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index 442fc7e4b..c367a05b8 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -105,7 +105,7 @@ For these examples, consider the following table and contents: .. code-block:: postgres - CREATE TABLE cool_dates(name VARCHAR(40), d DATE, dt DATETIME); + CREATE TABLE cool_dates(name TEXT(40), d DATE, dt DATETIME); INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') From 4defe2cbf501bd0330cadffa967385653199e023 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:36:16 +0300 Subject: [PATCH 0780/1892] Update current_method_configuration_levels.rst --- .../current_method_configuration_levels.rst | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 68661fd55..a3f0df6f1 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -380,21 +380,6 @@ Flag List - boolean - ``FALSE`` - * - ``useLegacyStringLiterals`` - - SUPERUSER - - Session - - Interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. Used to preserve legacy behavior in existing customers. - - boolean - - ``FALSE`` - - - - - - - - - * - ``blockNewVarcharObjects`` - SUPERUSER - Session @@ -412,4 +397,4 @@ Flag List - Cluster - Prevents a query from processing more memory than the defined value. - uint - - ``100000`` \ No newline at end of file + - ``100000`` From 3499eb2791a3d36c662f1a9ffa07e01647a686ef Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:38:16 +0300 Subject: [PATCH 0781/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 938a8847d..9ff4b7920 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -325,7 +325,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea .. code-block:: python - create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s varchar(12), ss text, dt date, dtt datetime)' + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text(12), ss text, dt date, dtt datetime)' cur.execute(create) 3. Load your data into table using the ``INSERT`` command. @@ -411,8 +411,8 @@ This section shows how to use the ORM to create and populate tables from Python 'employees' , metadata , sa.Column('id', sa.Integer) - , sa.Column('name', sa.VARCHAR(32)) - , sa.Column('lastname', sa.VARCHAR(32)) + , sa.Column('name', sa.TEXT(32)) + , sa.Column('lastname', sa.TEXT(32)) , sa.Column('salary', sa.Float) ) @@ -449,4 +449,4 @@ This section shows how to use the ORM to create and populate tables from Python result = engine.execute(ins) -For more information, see the :ref:`python_api_reference_guide`. \ No newline at end of file +For more information, see the :ref:`python_api_reference_guide`. From d038d4daef624fba2ec17b922e4ebfa86b95f6c0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:39:40 +0300 Subject: [PATCH 0782/1892] Update tibco_spotfire.rst --- connecting_to_sqream/client_platforms/tibco_spotfire.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst index b3ce5a95b..2420da40a 100644 --- a/connecting_to_sqream/client_platforms/tibco_spotfire.rst +++ b/connecting_to_sqream/client_platforms/tibco_spotfire.rst @@ -147,7 +147,7 @@ After creating a connection, you can create your SQream data source template. <to>Integer</to> </type-mapping> <type-mapping> - <from>VARCHAR(2048)</from> + <from>TEXT(2048)</from> <to>String</to> </type-mapping> <type-mapping> @@ -395,4 +395,4 @@ Information Services do not Support Live Queries TIBCO Spotfire data connectors support live queries, but no APIs currently exist for creating custom data connectors. This is resolved by creating a customized SQream adapter using TIBCO's **Data Virtualization (TDV)** or the **Spotfire Advanced Services (ADS)**. These can be used from the built-in TDV connector to enable live queries. -This resolution applies to JDBC and ODBC drivers. \ No newline at end of file +This resolution applies to JDBC and ODBC drivers. From 0eb78a04bfc859dd6779854fb79053fe8e1399f0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:51:09 +0300 Subject: [PATCH 0783/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index e241f0b66..acd0b757f 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -27,7 +27,6 @@ If you are looking for a tool that is not listed, SQream and our partners can he informatica microstrategy pentaho - php power_bi r sap_businessobjects From e6e682a8d595215c144709ecd697eb05c16c3075 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:51:51 +0300 Subject: [PATCH 0784/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 41577d0b6..b6a7538c1 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -91,9 +91,10 @@ The following are applicable to Windows: odbc/index dotnet/index spark/index + php/index .. rubric:: Need help? -If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ From f4e377ebfef668811e46ffa0d2967ba4858ae17b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:58:15 +0300 Subject: [PATCH 0785/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index b6a7538c1..db18f330d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -91,7 +91,7 @@ The following are applicable to Windows: odbc/index dotnet/index spark/index - php/index + php From 1eaae1eb33ba5e38643929117c6560bb05a44b99 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 10:18:09 +0300 Subject: [PATCH 0786/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index db18f330d..053aa39dd 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -90,8 +90,9 @@ The following are applicable to Windows: nodejs/index odbc/index dotnet/index - spark/index php + spark/index + From 0722f64f6cc3f768308f0b6b519a4c0b39343b48 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 22 Aug 2023 10:23:16 +0300 Subject: [PATCH 0787/1892] php relocation --- connecting_to_sqream/{client_platforms => client_drivers}/php.rst | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename connecting_to_sqream/{client_platforms => client_drivers}/php.rst (100%) diff --git a/connecting_to_sqream/client_platforms/php.rst b/connecting_to_sqream/client_drivers/php.rst similarity index 100% rename from connecting_to_sqream/client_platforms/php.rst rename to connecting_to_sqream/client_drivers/php.rst From d3cad2cc3d7cb394f0b58473cf86faf26c71b36b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 13:29:06 +0300 Subject: [PATCH 0788/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index ea6f3606a..4d808e5cf 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -57,11 +57,11 @@ An average single-node cluster can be a rackmount server or workstation, contain * - GPU - NVIDIA 2x A100 or H100 * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. -In this system configuration, SQream can store about 100TB of raw data (assuming average compression ratio and ~30TB of usable raw storage). +In this system configuration, SQream can store about 100TB of raw data (assuming an average compression ratio and ~30TB of usable raw storage). If a NAS is used, the 10x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. @@ -99,12 +99,12 @@ The following table shows SQream's recommended hardware specifications: * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 * - External Storage - - * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high speed network card minimum 40G compatible to customer’s infrastructure + * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high-speed network card minimum 40G compatible with customer’s infrastructure * 50 TB (NAS connected over GPFS, Lustre, Weka, or VAST) GPFS recommended * - GPU - NVIDIA 2x A100 or H100 * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux Metadata Specifications ~~~~~~~~~~~~~~~~~~~~~~~ @@ -130,7 +130,7 @@ The following table shows SQream's recommended metadata server specifications: * - Power sources - Two Power Supplies - 800W AC 50/60Hz 100~240Vac/9.2-4.7A, 3139 BTU/hr * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at up to 5GB/s. @@ -152,16 +152,16 @@ The following table shows SQream's recommended Studio server specifications: * - RAM - 16 GB * - Onboard storage - - 50 GB SSD 2.5in Hot plug for OS, RAID1 + - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v7.x or CentOS v7.x + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 Cluster Design Considerations ============================= This section describes the following cluster design considerations: -* In a SQream installation, the storage and compute are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. +* In a SQream installation, the storage and computing are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. :: @@ -206,12 +206,12 @@ The **Balancing Cost and Performance** section provides a breakdown of deploymen CPU Compute ----------- -SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors, and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. +SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. GPU Compute and RAM ------------------- -The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla A100 40GB or H100 GPU for best performance and highest concurrent user support. +The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla A100 80GB GPU for the best performance and highest concurrent user support. GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. @@ -227,10 +227,10 @@ Operating System SQream can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v7 - * CentOS v7 + * Red Hat Enterprise Linux (RHEL) v7.9 + * CentOS v7.9 * Amazon Linux 2018.03 - * Other Linux distributions may be supported via nvidia-docker + * Other Linux distributions may be supported via Nvidia-docker Storage ------- @@ -240,4 +240,4 @@ For clustered scale-out installations, SQream relies on NAS storage. For stand-a SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. -.. note:: Non production HW requirements may be found at `Non Production HW Requirements <non_production_hardware_guide.html>`_ \ No newline at end of file +.. note:: Non production HW requirements may be found at `Non Production HW Requirements <non_production_hardware_guide.html>`_ From f46bc49cc25358e67621ad25b7121e121cf610bc Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:17:16 +0300 Subject: [PATCH 0789/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 4d808e5cf..63493add0 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -51,7 +51,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Onboard storage - * 2x 960GB SSD 2.5in hot plug for OS, RAID1 - * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 + * 2x 2TB SSD or NVMe, for temporary spooling, RAID0 * 10x 3.84TB SSD 2.5in Hot plug for storage, RAID6 * - GPU @@ -96,7 +96,7 @@ The following table shows SQream's recommended hardware specifications: * - Onboard storage - * 2x 960GB SSD 2.5in hot plug for OS, RAID1 - * 2x 2TB SSD or NVMe, for temporary spooling, RAID1 + * 2x 2TB SSD or NVMe, for temporary spooling, RAID0 * - External Storage - * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high-speed network card minimum 40G compatible with customer’s infrastructure @@ -132,7 +132,7 @@ The following table shows SQream's recommended metadata server specifications: * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux -.. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at up to 5GB/s. +.. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at 5GB/s or more. SQream Studio Server Example ---------------------------- @@ -169,7 +169,7 @@ This section describes the following cluster design considerations: :: -* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQream recommends an SSD or NVMe drive in RAID 1 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. +* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQream recommends an SSD or NVMe drive in RAID0 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. :: From a41dac193b3cfc88ce206f12d7b631ed6d0f458e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:37:53 +0300 Subject: [PATCH 0790/1892] Update index.rst --- getting_started/index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/getting_started/index.rst b/getting_started/index.rst index 36f2c3296..5f37bfc41 100644 --- a/getting_started/index.rst +++ b/getting_started/index.rst @@ -14,4 +14,5 @@ The **Getting Started** page describes the following things you need to start us installing_sqream executing_statements_in_sqream performing_basic_sqream_operations - hardware_guide \ No newline at end of file + hardware_guide + non_production_hardware_guide From acc72a9be38ce0155d298aad63d9d981d1669ae0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:38:58 +0300 Subject: [PATCH 0791/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 63493add0..99e9457d5 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -240,4 +240,4 @@ For clustered scale-out installations, SQream relies on NAS storage. For stand-a SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. -.. note:: Non production HW requirements may be found at `Non Production HW Requirements <non_production_hardware_guide.html>`_ +.. note:: Non production HW requirements may be found at :ref:`Non-Production Hardware Requirements<non_production_hardware_guide>` From 5a3db555da5a589b1fd197afd9286cf18a3e3ab0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:43:52 +0300 Subject: [PATCH 0792/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 99e9457d5..bd7a79d9f 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -240,4 +240,4 @@ For clustered scale-out installations, SQream relies on NAS storage. For stand-a SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. -.. note:: Non production HW requirements may be found at :ref:`Non-Production Hardware Requirements<non_production_hardware_guide>` +.. note:: Non production HW requirements may be found at :ref:`non_production_hardware_guide` From a62c36183ea503c797227477ddb19895c020dfe0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:50:10 +0300 Subject: [PATCH 0793/1892] Update index.rst --- .../client_drivers/jdbc/index.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index db7b1602c..f86aaea7f 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -81,7 +81,7 @@ The following is the syntax for SQream: .. code-block:: text - jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>sqream;[<optional parameters>; ...] + jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>;[<optional parameters>; ...] Connection Parameters ^^^^^^^^^^^^^^^^^^^^^ @@ -105,13 +105,13 @@ The following table shows the connection string parameters: - None - Database name to connect to. For example, ``master`` * - ``username=<username>`` - - Mandatory + - Optional - None - - Username of a role to use for connection. For example, ``username=rhendricks`` + - Username of a role to use for connection. For example, ``username=SqreamRole`` SqreamRolePassword2023 * - ``password=<password>`` - - Mandatory + - Optional - None - - Specifies the password of the selected role. For example, ``password=Tr0ub4dor&3`` + - Specifies the password of the selected role. For example, ``password=SqreamRolePassword2023`` * - ``service=<service>`` - Optional - ``sqream`` @@ -127,7 +127,7 @@ The following table shows the connection string parameters: * - ``<fetchSize>`` - Optional - ``true`` - - Enables on-demand loading, and defines double buffer size for result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the fetchSize is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. + - Enables on-demand loading, and defines double buffer size for the result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the ``fetchSize`` is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. * - ``<insertBuffer>`` - Optional - ``true`` @@ -143,24 +143,24 @@ The following table shows the connection string parameters: * - ``<idleconnectiontimeout>`` - Optional - 0 - - Sets the duration, in seconds, for which a database connection can remain idle before it is terminated. If the parameter is set to its default value, idle connections will not be terminated. The idle connection timer begins counting after the completion of a query execution. + - Sets the duration, in seconds, for which a database connection can remain idle before it is terminated. If the parameter is set to its default value, idle connections will not be terminated. The idle connection timer begins counting after the completion of query execution. Connection String Examples ^^^^^^^^^^^^^^^^^^^^^^^^^^ -The following is an example of a SQream cluster with load balancer and no service queues (with SSL): +The following is an example of a SQream cluster with a load balancer and no service queues (with SSL): .. code-block:: text jdbc:Sqream://sqream.mynetwork.co:3108/master;user=rhendricks;password=Tr0ub4dor&3;ssl=true;cluster=true -The following is a minimal example for a local standalone SQream database: +The following is a minimal example of a local standalone SQream database: .. code-block:: text jdbc:Sqream://127.0.0.1:5000/master;user=rhendricks;password=Tr0ub4dor&3 -The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` +The following is an example of a SQream cluster with a load balancer and a specific service queue named ``etl``, to the database named ``raviga`` .. code-block:: text From 3a176fc37c893b9296d636f602dfcef997adc930 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 14:50:53 +0300 Subject: [PATCH 0794/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index f86aaea7f..a2d7272f6 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -107,7 +107,7 @@ The following table shows the connection string parameters: * - ``username=<username>`` - Optional - None - - Username of a role to use for connection. For example, ``username=SqreamRole`` SqreamRolePassword2023 + - Username of a role to use for connection. For example, ``username=SqreamRole`` * - ``password=<password>`` - Optional - None From 4b2ff93f873e0e2dc10c9eb180530d8149b6cf2f Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 15:00:38 +0300 Subject: [PATCH 0795/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index bd7a79d9f..ff611cecd 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -239,5 +239,3 @@ For clustered scale-out installations, SQream relies on NAS storage. For stand-a SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. - -.. note:: Non production HW requirements may be found at :ref:`non_production_hardware_guide` From f3fd795e4439e53e0e545655804c3e0b45bf89f3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 22 Aug 2023 15:06:14 +0300 Subject: [PATCH 0796/1892] Update denodo.rst --- connecting_to_sqream/client_platforms/denodo.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst index 30f33e204..c5b3a8d0e 100644 --- a/connecting_to_sqream/client_platforms/denodo.rst +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -52,7 +52,7 @@ Setting Up a Connection to SQreamDB - * - Database URI - The URI that specifies the location and details of the database or data source to be connected - - ``jdbc:Sream://192.168.4.93:3108/master;cluster=true`` + - ``jdbc:Sqream://<host_and_port>/<database_name>;[<optional_parameters>; ...]`` - * - Transaction isolation - The level of isolation used to manage concurrent transactions in the database connection, ensuring data consistency and integrity From 2ec4bc18d53e93ed49f192561a8334bfc9618168 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:29:03 +0300 Subject: [PATCH 0797/1892] Update decode.rst --- .../scalar_functions/string/decode.rst | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst index f2048e2b4..5329c49c8 100644 --- a/reference/sql/sql_functions/scalar_functions/string/decode.rst +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -1,21 +1,20 @@ .. _decode: -******************** +****** DECODE -******************** +****** + The ``DECODE`` function takes an expression or column and compares it to a series of search values. It returns a result value that corresponds to the first matching search value, or the default value ``NULL`` if no matches are found. Syntax -========== -The following shows the correct syntax for the DECODE function: +====== .. code-block:: postgres DECODE( <expr> , <search1> , <result1> [ , <search2> , <result2> ... ] [ , <default> ] ) Parameters -============ -The following table shows the DECODE parameters: +========== .. list-table:: :widths: auto @@ -24,11 +23,11 @@ The following table shows the DECODE parameters: * - Parameter - Description * - ``expr`` - - The expression to be evaluated. + - The expression to be evaluated * - ``search`` - - A value that ``expr`` is compared against. + - A value that ``expr`` is compared against * - ``result1`` - - A value that is returnd if ``expr`` matches ``search``. + - A value that is returned if ``expr`` matches ``search`` Return ====== @@ -45,18 +44,18 @@ Example SELECT european_size,DECODE(european_size,8,40,9,41,10,42,99) from test1; - Output: - +---------------+---------+ - |european_size |decode | - +-------------------------+ - |8 |40 | - +---------------+---------+ - |9 |41 | - +-------------------------+ - |10 |42 | - +-------------------------+ - |11 |99 | - +-------------------------+ + + +---------------+---------+ + |european_size |decode | + +---------------+---------+ + |8 |40 | + +---------------+---------+ + |9 |41 | + +---------------+---------+ + |10 |42 | + +---------------+---------+ + |11 |99 | + +---------------+---------+ From 7f40dc5ed280664a5ca3bb951129f3ea3833e4b7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:31:27 +0300 Subject: [PATCH 0798/1892] Update keywords_and_identifiers.rst --- .../sql_syntax/keywords_and_identifiers.rst | 154 ++++++------------ 1 file changed, 46 insertions(+), 108 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 75687998c..646b12e20 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -1,8 +1,11 @@ .. _keywords_and_identifiers: -*********** +************************ +Identifiers and Keywords +************************ + Identifiers -*********** +=========== **Identifiers** are names given to SQL entities, such as tables, columns, databases, and variables. Identifiers must be unique so that entities can be correctly identified during the execution of a program. Identifiers can also be used to change a column name in the result (column alias) in a ``SELECT`` statement. Identifiers can be either quoted or unquoted and a maximum 128 characters long. @@ -22,117 +25,52 @@ Quoted identifiers must follow these rules: * May contain any ASCII character except ``@``, ``$`` or ``"``. * Must be case-sensitive and referenced with double quotes (``"``) +Examples +-------- + +Creating quoted and unquoted identifiers: + +.. code-block:: sql + + CREATE ROLE "developer"; --quoted identifiers preserves case - will create "developer" + CREATE ROLE "Developer"; --quoted identifiers preserves case - will create "Developer" + CREATE ROLE Developer; --unquoted identifiers ignores case - will create "developer" + +Valid and invalid use of identifiers: + +.. code-block:: sql + + -- these are all valid examples when quoted: + + CREATE SCHEMA "my schema"; + CREATE SCHEMA "123schema"; + + -- but are invalid when unquoted: + + CREATE SCHEMA my schema; --invalid + CREATE SCHEMA 123schema; --invalid + + -- Use of invalid characters: + + CREATE SCHEMA "my schema@master"; + + Status: Ended with errorError preparing statement: Unsupported character '@' in identifier: "my schema@master" + Quoted identifiers cannot contain the character '@'. + Quoted identifiers may contain any ASCII character with code between 32 and 126 except for: + - @ + - $ + - " + + +Keywords +======== + Identifiers are different than **keywords**, which are predefined words reserved with specific meanings in a statement. Some examples of keywords are ``SELECT``, ``CREATE``, and ``WHERE``. Note that keywords **cannot** be used as identifiers. SQreamDB reserved keywords: - - ``ALL`` - - ``ANALYSE`` - - ``ANALYZE`` - - ``AND`` - - ``ANY`` - - ``ARRAY`` - - ``AS`` - - ``ASC`` - - ``AUTHORIZATION`` - - ``BINARY`` - - ``BIGINT`` - - ``BOTH`` - - ``CASE`` - - ``CAST`` - - ``CHECK`` - - ``COLLATE`` - - ``COLUMN`` - - ``CONCURRENTLY`` - - ``CONSTRAINT`` - - ``CREATE`` - - ``CROSS`` - - ``CURRENT_CATALOG`` - - ``CURRENT_ROLE`` - - ``CURRENT_TIME`` - - ``CURRENT_USER`` - - ``DEFAULT`` - - ``DEFERRABLE`` - - ``DESC`` - - ``DISTINCT`` - - ``DO`` - - ``ELSE`` - - ``END`` - - ``EXCEPT`` - - ``FALSE`` - - ``FETCH`` - - ``FOR`` - - ``FREEZE`` - - ``FROM`` - - ``FULL`` - - ``FUNCTION`` - - ``GRANT`` - - ``GROUP`` - - ``HASH`` - - ``HAVING`` - - ``ILIKE`` - - ``IN`` - - ``INITIALLY`` - - ``INNER`` - - ``INTERSECT`` - - ``INTO`` - - ``IS`` - - ``ISNULL`` - - ``JOIN`` - - ``KEY`` - - ``LEADING`` - - ``LEFT`` - - ``LIKE`` - - ``LIMIT`` - - ``LOCALTIME`` - - ``LOCALTIMESTAMP`` - - ``LOOP`` - - ``MERGE`` - - ``NATURAL`` - - ``NOT`` - - ``NOTNULL`` - - ``NULL`` - - ``OFFSET`` - - ``ON`` - - ``ONLY`` - - ``OPTION`` - - ``OR`` - - ``ORDER`` - - ``OUTER`` - - ``OVER`` - - ``OVERLAPS`` - - ``PERCENT`` - - ``PLACING`` - - ``PRIMARY`` - - ``PRECISION`` - - ``PROC`` - - ``REFERENCES`` - - ``RETURNING`` - - ``RIGHT`` - - ``RLIKE`` - - ``SELECT`` - - ``SESSION_USER`` - - ``SET`` - - ``SIMILAR`` - - ``SOME`` - - ``SYMMETRIC`` - - ``TABLE`` - - ``THEN`` - - ``TO`` - - ``TRAILING`` - - ``TRAN`` - - ``TRUE`` - - ``UNION`` - - ``UNIQUE`` - - ``USER`` - - ``USING`` - - ``VARIADIC`` - - ``VERBOSE`` - - ``WHEN`` - - ``WHERE`` - - ``WINDOW`` - - ``WITH`` +``ALL`` | ``ANALYSE`` | ``ANALYZE`` | ``AND`` | ``ANY`` | ``ARRAY`` | ``AS`` | ``ASC`` | ``AUTHORIZATION`` | ``BINARY`` | ``BIGINT`` | ``BOTH`` | ``CASE`` | ``CAST`` | ``CHECK`` | ``COLLATE`` | ``COLUMN`` | ``CONCURRENTLY`` | ``CONSTRAINT`` | ``CREATE`` | ``CROSS`` | ``CURRENT_CATALOG`` | ``CURRENT_ROLE`` | ``CURRENT_TIME`` | ``CURRENT_USER`` | ``DEFAULT`` | ``DEFERRABLE`` | ``DESC`` | ``DISTINCT`` | ``DO`` | ``ELSE`` | ``END`` | ``EXCEPT`` | ``FALSE`` | ``FETCH`` | ``FOR`` | ``FREEZE`` | ``FROM`` | ``FULL`` | ``FUNCTION`` | ``GRANT`` | ``GROUP`` | ``HASH`` | ``HAVING`` | ``ILIKE`` | ``IN`` | ``INITIALLY`` | ``INNER`` | ``INTERSECT`` | ``INTO`` | ``IS`` | ``ISNULL`` | ``JOIN`` | ``KEY`` | ``LEADING`` | ``LEFT`` | ``LIKE`` | ``LIMIT`` | ``LOCALTIME`` | ``LOCALTIMESTAMP`` | ``LOOP`` | ``MERGE`` | ``NATURAL`` | ``NOT`` | ``NOTNULL`` | - ``NULL`` | ``OFFSET`` | ``ON`` | ``ONLY`` | ``OPTION`` | ``OR`` | ``ORDER`` | ``OUTER`` | ``OVER`` | ``OVERLAPS`` | ``PERCENT`` | ``PLACING`` | ``PRIMARY`` | ``PRECISION`` | ``PROC`` | ``REFERENCES`` | ``RETURNING`` | ``RIGHT`` | ``RLIKE`` | ``SELECT`` | ``SESSION_USER`` | ``SET`` | ``SIMILAR`` | ``SOME`` | ``SYMMETRIC`` | ``TABLE`` | ``THEN`` | ``TO`` | ``TRAILING`` | ``TRAN`` | ``TRUE`` | ``UNION`` | ``UNIQUE`` | ``USER`` | ``USING`` | ``VARIADIC`` | ``VERBOSE`` | ``WHEN`` | ``WHERE`` | ``WINDOW`` | ``WITH`` From e8568458e2165909d81db07795a16a8f4a5033c2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 10:07:30 +0300 Subject: [PATCH 0799/1892] Remove Trino --- connecting_to_sqream/client_drivers/index.rst | 8 -------- releases/4.1.rst | 4 ---- 2 files changed, 12 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 053aa39dd..d5b5d2e06 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -25,13 +25,6 @@ The following are applicable to all operating systems: * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ * :ref:`net` - - -**Trino**: - - * Trino Connector - * :ref:`trino` - **Spark**: @@ -84,7 +77,6 @@ The following are applicable to Windows: :caption: Client Driver Documentation: :titlesonly: - trino/index jdbc/index python/index nodejs/index diff --git a/releases/4.1.rst b/releases/4.1.rst index a9203569b..2e4dd0ae4 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -17,10 +17,6 @@ New Features * :ref:`Lightweight Directory Access Protocol (LDAP)<ldap>` management enhancement - :: - - * The :ref:`Trino<trino>` ETL tool may now be used for distributed SQL query processing - :: * A new brute-force attack protection mechanism locks out user accounts for 15 minutes following 5 consecutive failed login attempts From 3cd35282946c73fafa463764635601351a2588c6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:14:30 +0300 Subject: [PATCH 0800/1892] Update denodo.rst --- connecting_to_sqream/client_platforms/denodo.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst index c5b3a8d0e..701ab3d3d 100644 --- a/connecting_to_sqream/client_platforms/denodo.rst +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -6,12 +6,13 @@ Denodo Platform Denodo Platform is a data virtualization solution that enables integration, access, and real-time data delivery from disparate on-premises and cloud-based sources. -Prerequisites -============= +Before You Begin +================ It is essential that you have the following installed: * Denodo 8.0 +* Java 1.8 Setting Up a Connection to SQreamDB =================================== @@ -73,3 +74,7 @@ Setting Up a Connection to SQreamDB 5. To verify your newly created connection, select the **Test connection** button. +Limitation +========== + +When working with table joins involving columns with identical names and exporting a view as a REST service, the query transformation process can introduce ambiguity due to the indistinguishable column identifiers. This ambiguity may result in unresolved column references during query execution, necessitating thoughtful aliasing or disambiguation strategies to ensure accurate results. From 86ebae50a5f5b26b4b7cd036551203e79aaf3598 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:34:08 +0300 Subject: [PATCH 0801/1892] Update copy_to.rst --- .../sql_statements/dml_commands/copy_to.rst | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 32e462f5d..f15b7e36f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -19,6 +19,7 @@ In general, ``COPY`` moves data between filesystem files and SQream DB tables. I Syntax ========== + The following is the correct syntax for using the **COPY TO** statement: .. code-block:: postgres @@ -70,6 +71,7 @@ The following is the correct syntax for using the **COPY TO** statement: Elements ============ + The following table shows the ``COPY_TO`` elements: .. list-table:: @@ -114,7 +116,8 @@ Supported Field Delimiters :depth: 1 Printable ASCII Characters -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ + Any printable ASCII character can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). The following table shows the supported printable ASCII characters: @@ -180,7 +183,8 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ Non-Printable ASCII Characters -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following table shows the supported non-printable ASCII characters: +---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ @@ -256,7 +260,8 @@ For example, ASCII character ``15``, known as "shift in", can be specified using .. note:: Delimiters are only applicable to the CSV file format. Unsupported ASCII Field Delimiters ------------------------------- +----------------------------------- + The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ @@ -403,6 +408,7 @@ The following table shows the unsupported ASCII field delimiters: Date Format --------------- + The date format in the output CSV is formatted as ISO 8601 (``2019-12-31 20:30:55.123``), regardless of how it was parsed initially with :ref:`COPY FROM date parsers<copy_date_parsers>`. For more information on the ``datetime`` format, see :ref:`sql_data_types_date`. @@ -419,6 +425,7 @@ Exporting Data From SQream to External File Tables Parquet ^^^^^^^ + The compression algorithm used for exporting data from SQream to Parquet files is Snappy. Exporting tables to Parquet files: @@ -551,6 +558,7 @@ The following is an example of saving files to an HDFS path: Using Non-Printable ASCII Characters as Delimiters -------------------------------------------------- + The following is an example of using non-printable ASCII characters as delimiters: Non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. @@ -565,6 +573,19 @@ For example, ASCII character ``15``, known as "shift in", can be specified using COPY nba TO WRAPPER csv_fdw OPTIONS (LOCATION = '/tmp/nba_export.csv', DELIMITER = E'\011'); -- 011 is a tab character +Using the ``MAX_FILE_SIZE`` and ``ENFORCE_SINGLE_FILE`` parameters: +------------------------------------------------------------------- + +.. code-block:: psql + + COPY nba TO WRAPPER csv_fdw OPTIONS( + max_file_size = '250000000', + enforce_single_file = 'true', + location = '/tmp/nba_export.parquet' + ); + + Permissions ============= + The role must have the ``SELECT`` permission on every table or schema that is referenced by the statement. \ No newline at end of file From 55f6efccbb9ed1654ad16592aea478a25a70dd67 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:21:49 +0300 Subject: [PATCH 0802/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 9c960010f..3671474b2 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -24,16 +24,16 @@ Minimum Resource Required Per Worker: - 128 - 10 * - Metadata Server - - 10 cores per 30 Workers - - 128 per 1T rows (optimally 1M chunks) + - 16 cores per 100 Workers + - 20 GB RAM for every 1 trillion rows - 10 * - SqreamDB Acceleration Studio - 16 - 16 - 50 * - Server Picker - - 8 - - 8 + - 1 + - 2 - From 8261dfb0de4c4ae6a0c912df581d20ec0002d947 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 14:33:45 +0300 Subject: [PATCH 0803/1892] Update sample.java --- connecting_to_sqream/client_drivers/jdbc/sample.java | 1 + 1 file changed, 1 insertion(+) diff --git a/connecting_to_sqream/client_drivers/jdbc/sample.java b/connecting_to_sqream/client_drivers/jdbc/sample.java index 3ff670747..ca591aa26 100644 --- a/connecting_to_sqream/client_drivers/jdbc/sample.java +++ b/connecting_to_sqream/client_drivers/jdbc/sample.java @@ -52,6 +52,7 @@ public void testJDBC() throws SQLException, IOException { } rs.close(); // Close the result set stmt.close(); // Close the statement handle + conn.close() } From d2bfac4b7c968783b8b1bcb462437913eca46b70 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:42:39 +0300 Subject: [PATCH 0804/1892] Update 4.3.rst --- releases/4.3.rst | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index eb0ecebfe..f87235fb8 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -62,31 +62,47 @@ Version 4.3 resolved Issues +====================+================================================================================================+ | SQ-11108 | Slow ``COPY FROM`` statements using ORC files | +--------------------+------------------------------------------------------------------------------------------------+ +| SQ-11804 | Slow metadata optimization | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12799 | Catalog queries may not be terminated | ++--------------------+------------------------------------------------------------------------------------------------+ | SQ-13112 | ``GRANT`` query queue issue | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13210, SQ-13426 | Slow query execution time | +--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | ++--------------------+------------------------------------------------------------------------------------------------+ | SQ-13322 | Cleanup operation case-sensitivity issue | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13453 | Metadata performance issue | +--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13460 | ``GRANT ALL ON ALL TABLES`` statement slow compilation time | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13461 | ``WHERE`` clause filter issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13529 | Pysqream concurrency issue | ++--------------------+------------------------------------------------------------------------------------------------+ | SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13587 | Large number of worker connections failure | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13467 | Snapshot issue causes metadata failure | +| SQ-13947 | Unicode character issue when using Tableau | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-11804 | Slow metadata optimization | +| SQ-14094 | Metadata server error stops workers and query queue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | +| SQ-14268 | Internal runtime memory issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12799 | Catalog queries may not be terminated | +| SQ-14724 | Alias issue when executing ``DELETE`` statement | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | +| SQ-13387 | Simple query slow compilation time due to metadata size | +--------------------+------------------------------------------------------------------------------------------------+ Configuration Adjustments @@ -122,6 +138,7 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t Upgrading to v4.3 ----------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -156,3 +173,8 @@ There are two methods of granting back access to services: .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +Version 4.3.1 Rollback To Version 4.0.1 +--------------------------------------- + + + From 1c8ef1764a37a235e53d294e25258eb92eb73624 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 09:37:53 +0300 Subject: [PATCH 0805/1892] Update sas_viya.rst --- .../client_platforms/sas_viya.rst | 80 +++++++------------ 1 file changed, 31 insertions(+), 49 deletions(-) diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index d84e9a038..310aa9a3c 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -4,50 +4,43 @@ SAS Viya ******** -Overview -======== - -SAS Viya is a cloud-enabled analytics engine used for producing useful insights. The **Connect to SQream Using SAS Viya** page describes how to connect to SAS Viya, and describes the following: +SAS Viya is a cloud-enabled analytics engine used for producing useful insights. .. contents:: :local: :depth: 1 Installing SAS Viya -------------------- +=================== The **Installing SAS Viya** section describes the following: -.. contents:: - :local: - :depth: 1 - Downloading SAS Viya -~~~~~~~~~~~~~~~~~~~~ +-------------------- -Integrating with SQream has been tested with SAS Viya v.03.05 and newer. +Integrating with SQreamDB has been tested with SAS Viya v.03.05 and newer. To download SAS Viya, see `SAS Viya <https://www.sas.com/en_us/software/viya.html>`_. Installing the JDBC Driver -~~~~~~~~~~~~~~~~~~~~~~~~~~ +---------------------------- -The SQream JDBC driver is required for establishing a connection between SAS Viya and SQream. +The SQreamDB JDBC driver is required for establishing a connection between SAS Viya and SQreamDB. **To install the JDBC driver:** -#. Download the `JDBC driver <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/jdbc/index.html>`_. +#. Download the :ref:`JDBC driver<java_jdbc>`. :: #. Unzip the JDBC driver into a location on the SAS Viya server. - SQream recommends creating the directory ``/opt/sqream`` on the SAS Viya server. + SQreamDB recommends creating the directory ``/opt/sqream`` on the SAS Viya server. Configuring SAS Viya --------------------- +====================== -After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQream Studio. +After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQreamDB BStudio. **To configure the JDBC driver from the SAS Studio:** @@ -59,24 +52,18 @@ After installing the JDBC driver, you must configure the JDBC driver from the SA :: -#. Configure the SQream JDBC connector by adding the following rows: +#. Configure the SQreamDB JDBC connector by adding the following rows: .. literalinclude:: connect3.sas :language: php -For more information about writing a connection string, see **Connect to SQream DB with a JDBC Application** and navigate to `Connection String <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/jdbc/index.html#connection-string-examples>`_. - Operating SAS Viya ------------------- +=================== The **Operating SAS Viya** section describes the following: - -.. contents:: - :local: - :depth: 1 Using SAS Viya Visual Analytics -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +----------------------------------- This section describes how to use SAS Viya Visual Analytics. @@ -123,15 +110,15 @@ This section describes how to use SAS Viya Visual Analytics. * - Name - Value * - class - - com.sqream.jdbc.SQDriver + - ``com.sqream.jdbc.SQDriver`` * - classPath - - *<path_to_jar_file>* + - ``<path_to_jar_file>`` * - url - - \jdbc:Sqream://*<IP>*:*<port>*/*<database>*;cluster=true + - ``\jdbc:Sqream://*<IP>*:*<port>*/*<database>*;cluster=true`` * - username - - <username> + - ``<username>`` * - password - - <password> + - ``<password>`` 10. Click **Test Connection**. @@ -139,45 +126,40 @@ This section describes how to use SAS Viya Visual Analytics. 11. If the connection is successful, click **Save**. -If your connection is not successful, see :ref:`troubleshooting_sas_viya` below. .. _troubleshooting_sas_viya: Troubleshooting SAS Viya ------------------------- - -The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQream using SAS Viya: +========================== -.. contents:: - :local: - :depth: 1 +The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQreamDB using SAS Viya: Inserting Only Required Data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------- -When using SAS Viya, SQream recommends using only data that you need, as described below: +When using SAS Viya, SQreamDB recommends using only data that you need, as described below: * Insert only the data sources you need into SAS Viya, excluding tables that don’t require analysis. :: -* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQream database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. +* To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQreamDB database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. Creating a Separate Service for SAS Viya -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------------------------------ -SQream recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. +SQreamDB recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. -Locating the SQream JDBC Driver -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Locating the SQreamDB JDBC Driver +---------------------------------- -In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the following error message: +In some cases, SAS Viya cannot locate the SQreamDB JDBC driver, generating the following error message: .. code-block:: text java.lang.ClassNotFoundException: com.sqream.jdbc.SQDriver -**To locate the SQream JDBC driver:** +**To locate the SQreamDB JDBC driver:** 1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. @@ -189,9 +171,9 @@ In some cases, SAS Viya cannot locate the SQream JDBC driver, generating the fol 3. Restart SAS Viya. -For more troubleshooting assistance, see the `SQream Support Portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. +For more troubleshooting assistance, see the `SQreamDB Support Portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Supporting TEXT -~~~~~~~~~~~~~~~ +----------------- In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. \ No newline at end of file From 174a973e9e220e70c17d3ccfd5b22223ba7f9439 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 11:24:47 +0300 Subject: [PATCH 0806/1892] Update sqream_db_internals.png --- _static/images/sqream_db_internals.png | Bin 132774 -> 92586 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/_static/images/sqream_db_internals.png b/_static/images/sqream_db_internals.png index 6b7b2b36bd17d88bf37f9176c00b6e9dc73d01bc..6c823a517dbceb3da5ea9f338dd922ad65c41b7c 100644 GIT binary patch literal 92586 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 literal 132774 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 From 9cdbfe859bd68338b3bc08d616d78fbd5b2db3f7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:29:07 +0300 Subject: [PATCH 0807/1892] Images --- _static/images/sqream_db_internals.png | Bin 92586 -> 327579 bytes _static/images/sqream_db_table_crop.png | Bin 92813 -> 139122 bytes architecture/index.rst | 2 +- architecture/internals_architecture.rst | 2 ++ 4 files changed, 3 insertions(+), 1 deletion(-) diff --git a/_static/images/sqream_db_internals.png b/_static/images/sqream_db_internals.png index 6c823a517dbceb3da5ea9f338dd922ad65c41b7c..646b96e4c1b5db4d7a37df8fdfe5097ff47738d9 100644 GIT binary patch literal 327579 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%0AG}rs;1K1 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%0DA~ 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%0D8m6}5{%?= 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 F{|D>(B?bTh literal 92586 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 diff --git a/_static/images/sqream_db_table_crop.png b/_static/images/sqream_db_table_crop.png index ed2ce13f217e33c739d94f5a96c4b07d8ba29a28..dcfe3bf466cef7035e58054a4244b038736c5c48 100644 GIT binary patch literal 139122 zcmc$F<zJLt*EWcNNTYNq2&k0Q(8EPYNH<ChFw#Re3?<Sf(m4XsIph#S!$@~`cXtfD zUe9yi&%f|~IDh-M&kyIhW9{Qud#z)Isj0{jKBsw(fq_A&ATOhVf$`K10|PVV8P4A~ z)28l_zYV6dhMW{e*&yA{-_BDDNo7e440sIwy$SZ;KAwa8XJ-ryqK<zbOq6}WR}75D zTm>0PEf1r8G;YNkxzuDlFLT-6B-JVJTx>P$QX0!&wA-?RU)+ZXLg)rIe$Y9Yd-Sn* zu4h*0i<;DWn|sSvRq=@)j&3HdJJ}|6teiiKrYNoXhC@RWG<s{5@nzw$F?>mUp7~6h zT*m!QcZ2${g=pwc|1-aLdap>HJ$(}J&;N(!J~TE~KTQchseOy3)Blx^gYP&6``@7) z12DNIW}X>Ecp+6<rjE>bQ=qJAoE1u}dp;M>|2tS;{_QH?7M^X_NnEtAes8*vs*iJh zfy;8|!sD+O+7b;l$PPU~N2Lbkztd}-Q*MzkR_98qM_-Sux|J@@%}*EAS*PXeN6mKG z<&S-v%7q4-9Sd-9to+~i*Z+KVHbc<6?9mRn@9A^<TfX8~NM~zOZ&pJ-cEBE{7Eb4v zkS+(|A6B<e|FeEg1FecWe!~_CPGRVyhsz<eArKNE<a2524fb3~IG6~sw=Lli(_fk~ zBI#b~diS4oKhBW@fRcwc6+`Y0x^FHwPeE-84xl13AytpFpw(+>M)dq6fAaLzl}d&v zvFx?`fP)>~zf-D%N&2;dGKl(*Odd~LZrJt<DM4oTnf0xJNkN_6v|<SZq}xiGqAr(j zT}{=EPVr|D1HnDF(|>om)jJlF<?`meYBOU);N|8h=r`y5`ugOnq=@h{xtPb7eKFz{ zweTKY_x4KVe{EwC?-mV=$fgr@Tz}=g8c1BZ1rqPEzQAFB8IjO?Jzly|I1};-yoRcp zfsF6DrXABvF%aA?RQSL6k9A$EzmDruwZPBqh$Qqv>YzDE4i0lPuA|d%fwwbDy;@ff zvpZ*$UG2&qsQ>*RrpN*pEql@oioxdxdY1d1|87Czk#}x-*8JM+rk>*g`MOU8$?$g{ zAyYc#zOEamDMRI)MxI4uC7fG0XojXuOr}YPk}1HFVn#Tw*S>kl^{wcAA)VQLGK6Kg zizLvO(Wu}q(9W;(Bini3M&<Q|L~QtLZHaF`@L~%xB$ex?j?PyezTY`*1KZy{PtW^W zSq}m9n)B8(9(bPkvza19dSX&WDBnApE+_Y_;oNQJU|G<F>^A=zOKkF6j9Z>-U!iJy zL>slth1AEUx)^gE>-B6pk-80d)~hVO&@_M9c4RDM>4i43Kku>?)5|XKKl{dPIVCPA z2rRV6ssLZ>k;SliaJ0?KD~l{A^{kF50Zbh_z)h&OCkGw8rIzy_r%T%~7!(PJXwsPq zKjB)ihMyu5elkjGFtna}$~IfOpYX5<?EC@a_+5mUnb>{kj(KNlv<&CpUHdjfz`%E` zcME??se0^*6HT2=xx^F486Wd8p-1jG=EuRnM$1#iBk-W-_u!zkf03a{f4P02fBflP z&=9bVq3Mq3k_~i2VdLIFFqoK&-85{rB7ip-Fq>iIXJOG;TjOv-n_H^5l(Ji5z(Mo{ z>BgP5LwNHA-I>xgoFpt}e-<}>gSA?3z^D?HRF^izRXQ;U8J}a<Nci-+HzDSby2aKv z8~W_dW8<~<Q`L-2C)2s#lBt6sDf+i<-6ipzIffXj&J9T4z24sLouHZn=V4WJ0`^l% z*1V#G8!YFzI%Ta--upox5@<Aq_n7z1VFP;4`jJzdoVt;U!CQXUjNH_KI_oKlq^Y6( z@m=W{>hz(v;h%7?h8Dzm)Wv^9RAS5jqk)Ja*93fJ_~)R?{V*cxQt<4JkB@6B50;#6 z{z73X7bk2{&rpJxa!s1Ms8YS`1CM~GvAOS|Orb$$x1u%(`Bryk><X{s`~e|<DE&o6 zkV)2Bc{iP&QS}4mTyb$yZIbSwfK81+)-e{>j6s&#jPv>*pWKrZPlMn7*N5ypNYNg2 z_Vr~KTZ|*h_3ksu>5D=|-1X$3N)EiH3gM7f+XOYT*63Mxy6K(2AK6_**2(6cJ~fI} zNN77oOZ7jIJ0soi*7@Q4sD>jX=zzJXXC$_yXCO9ZJ6`v@mza)EJ(pKq9D06u-?=Vk z5YiD*Ui?WtWOUi`>W<0b*3iB}{m<7E`1sKwq+EcaEYqsI)F3fct5RL-?cjmv^Mgc4 zy;uNlrWT8X#2;B>UEfnZsxFI8gu|7^?SfGw++{<_dt>&-w^2Lky#(T`CPNy>k%XIt zFVt)4k6*CUOr&1^lzTkZNyF*tS^ux8!cuO5sj|$2{gR#|bACL0!G96zIyQIi0M3ki zRq1!F=!XS5n|6nJhFvThgmBHjx_8B+G1{)9iTaX<9771S%y>ew0f@%gUYS6EjeBKD zAE>3%hRQFa>my^-S`DGh?!~mPA;Vj5yBBxix}SL_f%h>sJaFXnYOgYKp%kWHnsGnb z6V!6Q+Lr`e+IF!)NX+}I^>6iFF=nENha{kV5@K-oQ=hdBOS09t7*P}@XEoPr=Cec( zPD<Z)A{Ut`$L$#`&QDkMNS_l`=T0BHK)>Ic%rZB4w2QhY%cjm%BeNbWrNy9|-7|YM zN>Opoep%E(&Boc%_qL39!M$(E>v}LpqQ>3p-V%`1Q%vW`^^-D&dgdVRmPEk)1VEn^ z117L!@aI}>CGD?sQv%jTlhbHoF;!6Wf618LC{`?QI_~X}xLYaCf2bU>wEcu1=u|J{ zId{U$=y@+qjP8CwI=hoc1id$i-wBi)&pYkBk)e0$cb*jqaD>Re=%D=7ti=_2m2z9y zJbEH#V76l>WGm<&F>o+Dt6$!7k-!MNnD;Z#|029_;HIx(TX8k~aChW+-3Ds9C=&$= z^YHly_3@JS;(EDNhJhKcur<3q&E%L-G935c<u8O^kvPF&?~{fDHFmL23_6Fm+J9$G zP7V>_WXLu)JFT=w<iorlVz`^{dy{6Pg3nBw_>C5vmj^{*h_f&@Ut8<PhsGSKECN+c z#}CnTWQF3CE_73@)`zsd&tI>D>usbgy2<4~GZBSl)#A}&4!Y;TsLyYab~a!itCfVL z7OzWM(Bsub%|u_b`;roU<3^h_<HMiw{w3!jR5%|W?scP`i`JBne`tonZa+F3l}g`t zNsfpPds(vO1LIB#d^aw*JwaPDz{dvreEs15;BYXJ)G}iOa7V;`G_m$t>PHeop-U*> zO))rxXdxr&^rHvf8eW{I41L-CVQPN^($b>NhsjOKSmKeD^y;%8#unSb<mu{0R8l5- zbyTqVzQwH$pqqa5+y6!UZfTvk*dtu^5xHx71*A|`KIn4)p55!a!1E&rv4<(49}55w za}38e87KXTCGl{WxmZrN8n1O%LEbMU<hML{i&_}@6)jl_{GR;vLEPQrbdeZpKGXrb z?pj^!a5r}nz7KptH?Fg+z8ePnF;LnLbrQHpv|TllL=G8kTy%wSe)%U5oVNfeHxh1q znA8O6`JP0yEZ9y0j6tr|6%PMH<ctc(H3V}9bqpqt=SS!#-fQQcm$y64B}*ZSrl>}% zwJFvIT&={tnrTRF+u{3(Y23Wseaoz#(?Ev3cEzv6kWO}%>tD14<9OA+*a;`sR1N2; z*k+bPECq_`1Q9%bT_3^YIrP!OZ(3enu3$IJnbj!L*3><m-<<g!hYV$+VW}BL8C;86 ziZ?yDF^8V_jDD+wkC%xzg=@J`e!Q$4nFA_V1fA1-D`ENP0^#>Krstlzkss-_8^1+s z8+BGIcE*H!v6#hhGV=Z)aA9u0<6WNlxJn80Mf-_+TJ2atQFywah=x=bZUlkQBMG1V zO#O%M^Ui6Y5cc~vlb`DKS_jVsC_MY;<qck#9#WcKD{ea)->vzXr41`YCL1WNff<9O znC{SSb&akYySv3pKAX7`_m@|o`?~uzhIJW-5{=CIy=Z;l%^1w{zD3x<_^?)qRW}Gl z?E9UdRiB!2skq(j5<5>@+Mw(>?isChMCT>E)G8;MTbk82A^Pg3R8jVJ_#-G8%L75w zaG>M8GhqRGXdhd;U2H+R?er3xe2I)(zCqs|-W+cMPyB$6M~1Khonr5m2X^yH;d^iH z80*e0ctZL({#E@URy%7Vo&+gYm~F^F;PD8U40RmGTO?=T`IQrGlwVcvveHhxbbaaW z`?!A9{K)9#fcaioXrreGDYtah468rlgFRS`g%D@@cjP|5i_i5WO(j-{y!jw3(cP?& zG#$MCre{kRJIuDzvGa%i6uRr+M3RrnMP%T1wcg(EZb-#%C!(bWiEs!v(pm`-W+h^1 zxGMu)Z#>@3i(mP^l@JEP%x0MSRz;C7bEe)nOyoFR8y8lxA9s;Y*XGP%Hn=rgE-_Z? z@1@yiKo3u+nok=eB(4V;TO$%2`(Ij^6Yu++ceFSh^TE(jr&-KwP8_=QtxfVZ0e`UH zXD};hm>=Z#DP*tBkubJ+@1txrPFqU|mdy%gW)_>8?howmHxjt-cOHk0^y{CXB7HM^ zHt}<NSHM>c4|6S-OUm=USJESTuEguDF|pJyek2AnSv&31N(EluK4V1Hzj&K6rpg4S zVhv_6s!l7NIEdqh+V9Nyq33AJ#V&#*%PsEPazBXsc?{*iZW^5#Z~MzBHi?#g_I>T{ zY$72O=8TUV3_HlNU8h){tWDp}@G0+4Rji!wtp0n<w&rBLZBF)kBS7dX8&&j{--PYq zc30X0$Gk^Ny2sMU3yF+(T5H^FZW2UT{}L&}YPnAj2(zeT0JbtTKXP4;(&m588Cfm= zZdERAkkIBnB?BpjS>PXtHBSGjI`Hj0?lXR04`g5F#p^`r%FM5_=UG2-l*;b@LPS3j zbJ3(wZ<(hu-ztm$@j#<rl73$^k7OhKMZ$f5rnTb|t*)RS!pOed<qpfY66-EOSWI91 zq>oYPK^2DBYqdD7pQkD_p>|xSSh;av2VnHz3tF>(P;J!$O?NtHR68C;Fdd4lt`Qz} zia6uLvjXwWXCSPiI`5;0loE;e$LIE@bn1pCQ*F_QWW!sT9?P{YXK-BmyN!;svARHe zqx)Rl?!*9XsEpy)hKob5oggcz7@$l+gI5GS(4jLCVJ)Sl3+dsMFh9)=v-VWY)yQme z*qK$F6Fn&}4iND^ZoT(m^xV%{YC1a9mx%4#>|Orr;mdHmRf~MO2qgOL?^VE1^YN$i z&rCLDRGm!n@ERci`oXNSUL#kGheyEG*ao~e+r2v*q*GNBWnM6_;dB!Myx+E8y!vzJ z=ji2jNu}iTwE6zYd?dSUSratk`Tnx38!2+bsqhDFIL+C$(<{I^g+EbU?2oeTHNshA zQ1<N?9D1ml%nh`j*C-<*JZQAHtFL@gQ1D{z($UfM=wvNs5#9Ns#rOJ9lrbbkhnj2+ zMIlf|_hhfRD*yuYD~*#X8uQ_AeSG^vsx<D}>9vdefvLkQqHrlQNF~3xcSWto0mR4k z!l|4^Vi$9_K#NB7VQ1(e?k__g4{7J+5x4UshTQ2${EGVFul^#b)8L9qw37NxipK8k z$@B!@h|~U`V3bmsUeP*R{+6Sm`_}5s)LdGc;yjVRXGGo+@^S4>;&P`&&}VCbvEMw0 z7e*PzPMH)-SLAuslc*p+^?llU=_TUJ%n0l21uBDq{>`(I=}s*Z-=o;gjR-c!6&$Ym zu13Ybx2qV{!<ok&7@Dn$@nL$2BU1aSRa5DA3^hA$7m22R_OPL1*<CH2<IKAPwB0?4 zehhKGsb|Rt;VSoGE5S5;%B9^yNa=Gdj7$sGBhU3JZ{T@7sFa~`4?Sa$C&Q>nCmK`g zJk!f5am|r3#-LCoJ$jxPS+e{*B^MRevw0c>^@KJE)n6I=ob=mV!wV(LJ1C|2>hHAx zAdzQ8(k<yiH(P!G6FpgE@j^4OCq0MQxuwE9O6_es*s0Pl32xQ`5c0cK&x|Hc)jM}* zc)fGPdzzaC`kE0u9htKX7P=xIgO|Jmb*-uBK-2>`kKaG>BM3J2v*kQM&ua+hLrWp! z!Gel0gyTNjE?z!~eP0#p4$=?@Z8=qpT$I^7YL3tA4NjKNr#WBwG2vT?8&-T|v=E!P z?v1B;AxcoNF|A?Rs;rThIy|D+#J%-xQ)PNPF_QcI{iT0PU(v!rWqsIgvnbJ!M75v! zs*t4+;+HljdH$hD!;y4V+(e)d+qI*}xxne}ot!|i+mb<SuwX5Rod>vYHJKk!(?L6t zFW^WEX1F0_#HT(tF*;uRUjMd;ZoYBrat%c!PO+jtz@i?{ewdL~f6!SPB0)g8EL`1H z&kyeMG3enp8>gThEZ&z+*JHRU>|c1LDn%iPP&jD(>IM@O!f7ZaN=r?d^*f%94Pmv& zBR*3g{TjY8x(=U<_Nx}bq|`K?3qi$&2XaOSNxO5w$-M+9c%Aob@)(NROVf45Yttsd z&eK%4Upwwfabt1~vh*^54%g8);5soSnAVEkdlg0@hpEgQxqmVTR^~7!e4^lgZ){J5 zHYy1V2PV%Zm==ROU29D0f9;^#fwe|47qhkixcyPqjOZb>L`>YrU-h{^{+F(kuzKXx z{M9=I25j?a=ZW{mW2UvBEkmw&=bpO=2k5=B5}k<GRA(t0!)6>)&*oX~Nlu-Znz-9O z=KXscG4r4B#WmaSYb+zJ7XGljJvV3Y9T9ydV(k!hIuZ6+nDgHI$MZ2hT-GD+ZN3{* zD}qdmW6{8QxSfvX-O4N@XW(j+Nb%7`EESh{GmiT#N0Cy0B)zz!-_3IA)rmrE>zS(A zePSa}Z_#_5%j2?#@HiQMHkw!z=#Q6Db5TP((&rrP!BOW11N?~Cih^W`d9P2ekKh7- zvPUZ~r|&2J$LYHw5J&uYpY#dh>y}!x^7I!r+jwID$hfuGny0tYy08_Xmm;nSGX?3v zOh9wVrsaa&)3T~fU}{Q-pD;*WH&gnxVl=TWGt^dJoWhz-&z(Z$hG;-5hSF&!`(>2| zP&b91{UELM<)&i*s)U7e*;1hK!>+Qzip=btQw%R9O+{Pd3kfDc0i8uYVVzlKf%Kh| z-sYK}(=2E__1+3zT#QM*omR}RC{*-O)#wXR0m{L8Cb!>Uf0R=E5cy@l3Vlb6qyi5+ z#dC1niwShx#Ho=%^~j%ON1(ewmY}O_lwIArZvk}PNXUxzzN0BJ=PO*r&Q`6AM)FRP z-jBm<`9uN;h`<++!oO8w)i2Y^>zn9R3O2)Et(Us>Hf6d!5b6xx6;5Pmi&1%JNx)n? z?<5~71O2|8;c-z(Ru;0=tziPOK3bep``rrq@jg0AIjLxZ+85K#q(6W;#2)6t2>pN) z!_2d<Wst2q%~O!UomA`EdJs=|3CBPC8L*YIJAbck@GI67dKebIHZjxQxlY#^m_$Iz zul^!n^7rXBv~t8Tbuow(_Rkf&-76L_{Zc#aiz~`6wHhf!{YNd@;llOMtaw;*GJE`c zzWXNzo4@KI8aAr`FiNt9d9DsrcgMa~m}aL1QN#uU4%t>v1Y$!kw=Nm`5_+}Yna{ih zg?8s}9yj_ee-lShJ`Wf-;H_mR4w;W>V4$M$DSqdTB~t4e&o4@szblEsNka?c9PDR| z)lezZE2PNVB-&U`HgV{ussS%C6a)GB*pianw2q{9qJ*6Gm{*ujHL5!)6?;$M-?u{R zA@Q6lhb`FAaX*LmqyKApFTopRX_<5uX>+0_5q`M{qT}Dsm)@yG^Ok75uV4WTHp2xv zeC@3geSDl#4R>_((l(ZZUUIE02MOFbK~}ug^GIkxVplyuUS<~8-UIi2_~i8lID=2B zScD`aThuV?iZB;v6T~YTy*Rvo+PsNJe_*tIK^xxGN!pOzjcMSH0+mF(JXNRu@=g>( z_<@{2J_A3JMONW!@7`t7@4b^wWu`U4pgGU%Y@$nA6&ymW^d!^QAnc$_?vB<3-HDvk z@3$tPs2d;C8Ky7XX~A>tQPopk)Pc7rrSY28#CDt+-@2b}C;fP~%!4yThz7PW2}tT& zmpiFLkY#dqu69;(U^QA@bQsl783N%LEtM5Gp*UXff)Xo;hJCLK54$-+*-h9DO2?kk zYr;?LMh7dc#X^cp@Z;31)tYuXZdO7_XrvGDjf^dF3gTlyuZl4-i!OkQkxif2(neP% z2cw3Ef)N)^5pa0}(dH;l6x{lyg_3?=K!ozEH12JQx37*%utJmog3A&o$^8L{UH1)H zkBl!k%rov?Y7UGu1fivus*)R*8|u^b$A;b<z2w)Q;7_(#dN-66|LNB9j5MGSA)eBA zd`Tn`9-c)zEqXU8Byjj6{Yy;5%MW-d=@)vvtGMaT*WH$nw^-d3XRXtpi}81DP$yaY z4vKgGn3ie9IYpmJ7PRc6+#HO;kD3EM|M+RR21EQW+e$jXS;C#}^IO?asOgEWgzJyT zB5ldnmkZXfQAG*7`aLRe2@uTe@phEqa-fvDc82>nM)!ofVVU8U1<*q{ZYoP2peDO< z%>{;jPLhr$X;nntRxQ}ox7|p~M3MXn6);^^?<Zr+yQFGkw{7B6z7-eq`5CGAGbz?O zL7%a)$V6++MfCnWc)z<fAxqP4CDkh0@h|N^ZJf0T+Heu)3BLZi9KhVjbB|~8tW)Zs z9-bHAHSr8yx=*agGV!Jov*n8Jb+!12DA<3{=c#|q2?uikZnEuBF(KTw!KlBFg(pmC zuz^FqNlUg`p;+O{gy?7DH4EM9jUb#6s3q<s+He07X%eVy3Teb_)~lU23qjQ<jv-cS z6wH78dWDZ7@Fmjx)_jOy#iLEYb-0Q7#=}UI?%4Ar_Q^q$fV_SNzCT(OIM#~q7JPw- zM^#?@%<?pr)_>0*k};Iu(JWBwJZiptoJ-*4&@|15HPqrE)sgd#(2f&?RaA8l97X== zFnnV;_pl1d;>$(GL-HWz?DPFUv0}DXn<A-~@WK;EfDTvH#ei*M-$HuQJF&WU77{4# z;JRLlt(@k5jIQ}~OT7rH87|xd!1<`t%cJ98j2zcBRTBn<lIJwh<qWvCK=54%b?Al^ zq(mw+$I(B(h?$VHl{)p?V*~xXek!V8LiZ+KScE7)F_m5`1`_6*wf^yvnT^cWb&^(9 za|Z9Kza4(Cl!o|R(wG*1c<AN6crMC%WJ7BzuXY*C$xnmA9y)0MS&T4Uic@zr^0(GJ z%RxpK-paSbb~$O8f!j@Yfxow-#K@RypMd|Ay<*s*q6ilEETM72&v_|8MK%|mj~ZVJ zm$vQnVZRL(bPK0%M`_rjhQaLJb|ZH0arnKKSgkcgtc&%#Y4F7pto**gCH%z!Q2K%B z!uu#HfAPy~Bd*fTQ$Y#|%!Dc1v^OR;>n~}{z|-$4xQcVzF5JdKk&c_M9gr&)m?Ak0 z6Z~%i`?>{n5Z%vb<qUiiBais(v_S$Qi9Ry60>Aib0k!GT2hB8Nz@Xh7iU8kiyV0M` zue8f0YoovM&bV+eay^nh``_TIhpIp5gZ_K+nQM=rmerFW+I!orYf*mtC#%lgL2vuQ zH=Z|&B%Aux0Q-FJcKPqRZ=cT5#On#8^x}8ej9d)0lX-<TxEGB==~3jKLbLd)WMVf3 z18N*;S=w1XpXR@}RJ%{~+GcoBV{c^Vx52GL7kh;O!3%`j0@0}iTJ$1`w#wa9inBA6 zLU=A>AH&7N_NvE3M#4B(V_bJ`;%lXgoM*#1PtLoZ)O$X@_-c?u?8oOn9upp&b1&9B zZ>I+-6trPx&IdA#ffHx9fw!N;O;IC%PZqQ-de`8n7V`tEy)k(FA0Ml@>6!v~c>eOz z$t$!Hqi1Iy!s@Q@VDyKh>Hb@cy4VP|4h-5`$5|QW`)rlVF4;ivd)hoX0&k=Ig`Yzt zmsE~DBui+kz7dcBqX+5ExajJ;l-EheVp>GXGq>x7B%%jL{~W<8vk29^>~dn6O$7<) zL%Q9stwn)P=xX^XYIK#sow$Vbv?9jI(S0RU;rt-n29*kd%eKQl9^BjKu=zt;o{7YB zLJp9#Vo4#rRJSbAOErDnlD#(^^Z%wGm&Gxg+0Cu9d(Bx<pQ~ofMK5q3O=r`HjQ(k5 zf9K095f`DyEZD8$nm?T+m^Z`7ty-1u&Z-wk{uxt4?$}yssj#)}HR(u_>6+P$lQVB8 z&e{rIn>;~8keB6UVaHp6IUo+N9ZgvJsL`J;|JmU$AzWWE!mhVD(8xb@Mq*yftRw98 zd~DN&<=T?sH42@~l!#D?%>9@rG3*V`$#n;6O5IIocB!0fj5}TCBff00UB2%Atq9(I zc;-ls=XV|?yYYl{T#O6s0@@|D&bixWzxd|y>s+Q&okz%ko4^thbQl<RM8&(B`w#4D zn2j`WifPsol^yvDdi^Tex-$s?HzZ)pF#urqCX`l^a-vUuJE^BVJ<nkAr<Q)6Yt)q! z)vIwPZwYNQiYC{L(q7}m@G*QCO!j}R>saAQarbg6BV-f9?M2AkHyC`V=rh&BEYa`E zA+V$(b1WNSZoa<fNSPDMX(6KW1Uf9RUqBf2M=L{wn0`*=-PkaYS7~c(u9oP7poKhL zj#1f*%rC(Mm2IWLcS34TMXJ*@v8KQ22YM7D3hOeHnaL>Z{wHIdiQ%XIyk!YTA33rv z;R$tKvIS$ZoeO((4Q&0TVe*;x#g&w_ar=F=eEW(var-r1K@+#6eP(>~(e1^&AN^6? zm5TeZ)d~xm?7>N-2f>>f16UVRXmuMc4`-6BsqSv@I%#q0&7?`(us*;GMp|z4%%?UC zThf2_O9&k*G)M@d^gW;mMLvdcJ}$eVxc+f?&?Lebbmt_B2zcaYIEthCgnI3SJrR*y z$qm4XK4Q2u?M%>*v>i-H__*nQb6Prn7rN)ptvHI#d8Uuh_9~BRr9_2wOqLCVa@Nso z5G!wW0U>X_ln%&9xXrc#HnZVmo?%hLUEQ^%_+JDE0^d0Ga0d16r#hxj6Hj2AUv#<j z2)_wt2MpmE((3kSd9F{^FgEsd!~*$)Rar^Y(@#Q6iw06O+rjdpyM1Xg8zYXPDw58} zdcjYB@I)B^3o`KE*V$g{ZMyCJjyxhhztOpff_r50o>y!b6F{ENUS&ZbbJapnjw;io zN#;+0@WtR>4)FyG5pFusMD}P~XRQB{(O$t3K}Jft@x-Sf+X-v?qwFY|uU%bf1nlHY zlM$cxq4~Yd^}++q2tZfnd{HHSDVYt?JigE_wx?xoPLo57Dc=*pT#7C(o67vH+lnh= zd9~6!w>RA+?sh4rIn17r(F=zB*8*0umCm#?RRs<Ua(HvE0m0(%i;b85S=?pujl0Ji zxxV4wTcY^oMOC8cq8lRVGKFSYS%@w4(0G1BQZe&+JmG{x`LoX$#@lTO;rFq}^ij}` zu!G;}OtvI`V#6%^bdyc2A<*yciEsD8f1)=-?UqMrPd41f(Rl<Br7LF+FQ|Aatvm^C ze)!Pm>ezxOWKO!Ne=gy~VBS+@5R-R=Zd5SlGQ2U7yKplAUdp)5ej0UoM$MKfH!+<U z^W;L|tYtBs3;lum{Dy!i;y~&KvATd^vcmeWI^jqJ;h@PuF@3)N^igUx;bOr3>xyi^ z4SZvTqvT8E^e;7&@*36|Q0c%ic6ySvcI_-@1w#|Wd<B9H61xy(m4&Kb9YpPAP^t{~ z^CAzazX^rKakWz0cb>i!J1l^Q@S2{QnCE<_=Fxs1M&(joO8o(%`EyClFlVr#V=#7# z_8{0=sav3%WX`q3T8+Cgv`#i?Z53LeO0zioovFsHbF}!2i*oQH|0Y0#zZbY~Ey2UZ ze|M5j(NWC&U{oUZEDCj(DHPU}>9qzt*Ko=;>0A?_RoA2z2$7mQ6U*KUhtqzRB67U& zQ96BFjbzak0zWAeYc^*9ms#>OL+NPjpUDz1`zi4f#}f3JbX7CT0eaA%%;gZ{(Pk*+ zp15P$2@1FmrgmL%6y4mEoI}ai+QE-sINm6;)@A$FSMOEILF$Ky<ogxE4?eWF|F5RO z)e8-zWn`~PDRiVFoW9+p=vz%1Zt7U3^*e5KJMIh1M}?Q@mQ-5o#qD1u<;}oKm8!-L z@FvY-uYKttyX47DBx6NU;=_RG7FKpyPsyw4?c@So!sAV;b<vFP%Df+<tY8FVh(S7O zD8D6hS~(FV9{a(ONqj{IBzW7?w|Zruj1_J8lq(*2^jpH!Z|uj3sUIIA(fgFC0Z>oh zMR8)JMg7p2Ud*3?Thbv|jx*Y=D_A~8iYfqgkua;6s&M$p%vg&5)tCh2?UQ-_P8TG$ zl%r)KWoC(HA`QIm78%K@Z6B;9Ic^RQnB)IVZ;$tVI9)gX_dgJ*fC=B_7>y0`sgD&0 zT?$xH6|6V#Lt$U<dD8q~T!GKC=436qn0HnWKza!kF#!>uLQZ~U%)8FB<v+Q#T-8zM zSY#J(wUjI!fm-t8dI0heLE*_?QQxi|3I>A?6lY4yQ4D?v%?YKwx;wo6Db3W5MJBDy zin02A&fOCVTll-}WIK8%X4aNRvqrrCLx$z6IVGK9h;>u%6dBC`MPGB^5yEj~@8X*B zrD{S%iEcq<{$HeCGRib>spIb}b7ALz4OB2S@mfq2*UV2-dGmx1yfvm%<p|6I@Si=? zE@+ZoWxbp+DTk2N{v<6@$aWScd*Z>gq3-B0sDAzqfHOK+$NfHYZ>!9<x^$N~5EaFJ zS{QQ}hpqtA_*&-AlAO~?J8#Npm^%6~>L`WB3UUVHZ{*z9s~Mk%Eoz5Ezg7p#>g?o3 zk<!}#j-G^t1_+%$Cr1h5)*^{548nS|PPftBz}+{CREfl^5#_cl!5O0~6et7hOZA;H zVr&-<uJG;T?2Txl+M!{1WES{@Q;!-v<3GJL5g|#P<P6%Lfy*o2Mto$}&#Y#i<|&0I zb_8diTGm&_Mcrx`O5xBl69vuoP=LLTsm7xLcmrl$M`S4-f7bjb*ZM7PP8)ugZlkU& zG}uxDXx1i&190i*yhL<-5-h3Q=)M)HPetfYtS5tS)D3_|j_J+6YBpR-Zk-gtr{+8M zfd50AYo6R2@v#!MKUD(<^plX9rA$!#EXyjhmJfv)U&)vEA9U!zLzDS`?+rp-4`-t< zMW+fYl(<mgpHEH-V~t8C@EUMHhjOTj%XLjQQaaPM{_kFW!L!0XBz^X8dwr9K?AEO1 zb5DPhJ5CaxT;NgssG!cn4c>kI%ukMDHr8X%YglInF94=~@N#rf_NKTgr+fVJY55X~ z=n>r~;RF*{jO13DqW8WODpu%@H^c@ctZ`T@y;E3TnI&8R43Lg#-u-hqDXRtuyQN$H zRv(SJJ57EwEaavn-VJ?EacRQr!j#O11HWLhZF(yXCq3Eb#PCv-^4g(t6QPuM?Wej! z@+lz0(6OIOlRU43gqFytA^Sq1?7Hnb-PtED2KqRNQ-u7wqydlFn!rE0ue{y|)1z3{ z3WRuB?TL<oq>mWZHZyEzt$!*7_by)@5P-h*f;(5-dj8B0z6i<rs#Sh#9r>d<yzug) zy`f0<RI48NYG*oVv=Op1eHaHX2IQ!iDMBNG-@u$$+;btbV?cjT{={hTo^~VVf8p!J z{sLde>5bUjY+;q}BMxZ6j(3-dPJ)Si10TYkYAi9GV(Nzw>S}Hh8RV+&;|ReQN&z+{ zOCRLKw?r6@v%P_S4R8$Z<W>3bOtwjV^-t-ym|R#Dz&Jj&FzS%F@S_Qe670Y#td_S= z;4Mc8MB-01(L4ZtGkk1kfLI#Xi<zwzn&=s@{Y5-Ao^%1dlLEqlAzMqV??y!HI6S8$ z-fSB7*O3^HydyI6)iUPMGQeUY{qifAaVN8v1w-UPXn+H4$YPn~TqMS<@LpV0H~fss z*NOHn;Hw@%Zb#`4OG~lc7&ZOHB%UANiDDyOjT5Q2+}aw?sJU>}3z+uuB;@X5POTD_ zf=G`-EZye6M=nQL^bw|z2l9Sl;Ndm>LRBw+c0}v(mRfQ{Eh=YUUU7Q*7oin%j_ul? zK`~3Y)WIMT?2$8^H>RW+i?<aQF6nvF<5acPI*TR1S%a%5Shws@pRdUo$d6DTA}#wq z<C3cgz`Lop65hqHz~_yzT}l55in)_Rbrk_gX5Qv`*AcUqDrmzS-!%2sA|{WG$n4OX z9Nxz1G~=bYOjAFkNKbPkPd7!w$A`moF{;0_BPH`r;P<?v`q_v0p)%e5<Vc+FO>_G( z8&Iq4cK7KB_H02M)&3l%c&dr(frkBf%rA!2^1-LQMv+a3)f*?`z+1v%&ADijB<cO& zgE;&{@P<@Mc!Jxb^FOfuw0H+g4(2kHQGl?Rt7WK>OqHoA!A#AH(|H|)>{1L@L1vhT zBhrI61ixBw{VbMj%gbRi=(={EDn=u)lG+@1dESFN{Ga?yt{T?XdhVy?MqNqzIZ^)X zT)l|-aKUrEMHZ2|3|up!rb~qDk4WYvfw=A;$uBL$DF&g<)9-jHGED^DiE_X1{vm`@ zdm!KJR6Yiw7daI8MhwHB@7;_H;=QAnA0M2mQy6<Kqq_IW7)5PTV!CrTUOR*RUjTZ4 zeV7V&N>NtU`kX&!HYX~O=uHe&>c!>aUtyAb*IQ`-90Kr>UwYYm^Ko_#_wlq%M<NW( z_mE<G=AWOIkN03>^SEWcL^w44xr2su&v)Sk0(&s*e(SuM@QY6!_01FP0&Uem;-P|G z3%Hg`L8|tD=v~?FH7*a#c_Drz)^XcMd4uYgbKe*uRLa~l-9ASYb%;{F$>baSAig?7 zX&ZAy5o`En<m%ccc!&P?#O?%UVMDw~HH^8LMw2#eyvZqoisx&YdbEIOvo{?s%>V-_ z^1H8|GTEH!%FiWBCEEN9aM{b|`<zYbrdsAhTC@0@X=PhF(M@^RuFt_6eCJm6!5gl( zz1vpJDlIF<>z&O3<wyx@NM8tVKkLUMaUwU`xR@U2iw}>a|50gq=<Zy4L59xXfSTI4 zS;_=xj>3-WsByT2RvN7xFxfzFD|6eZ?j9!J-1XI1U1mh_xaEB|6}861wR^$#9wVtI zMkmUPsZ>6FJaX55dL$r6O3V3$=2k^y>}yTiH?jxAvL}w&doP97NW{C!+RVR-XG215 zcY(sIEL2_HK^t2|alPrTpG3)RwwvWe)3Q8&y!0Cky&b2)vqagBu(7x?Emnv{>y0OF zo^~BeP|6dR8<}no1Z9p}=&V{ynePYAJGIIk#qGW@)i>w_@Z2Lh1DNxk_#j}_S#JE9 zm5v+P=-9uK4`*W(a)oCAcVLp;jajubKB|`_zZ}wwGs63P`vngiQ^ng@i+Z&<h3WJU zD!{gw=G8tOiD*L1mXh>t)a<h`vGM5X-Bdb}?|YJY`!cqspcf*RvIMhoqb{Mgif~lN zaVObD-xoX=5PumJ7xl;9RgYuUfutd$p29^oTn`Qiu!Z*3e<A{gSWC#!9haHKzZ|K> zQK8e=G5g^`{aXu`#b3=aG*P>l+|Bhv+k>^)H}uZw8*g)qbWYcZ5`6BuYv#|_cpspW zON7+^?#I|mXW8Z8FJ8J_T#8{EGBYu|e4Ue`xD1R}J>dwF-*5vqBRq6PL%J7JJiaZL zC^O}v5V-3t?G_&MuhpFfPW|z*bQ-I*am+6&rmsa{^Gv~|33J$`38vGc=iymbq$9#M z%MT85WXxd(TFcG9b1}WNBg%<DrLtTKOu^%6JgWhjY}s;J>3ZA*{rB(kA7@p&U%j~u zFy5Ar6pF4mzO@o1=B2Q=A`#7Dt>5?+-6@%2m_%52(iMNAHFl!_o2Bx4ve+_sO=c9h zO><(YL{FI(L{H3P`Y93~z80FlglDxQJCL*Nq+JDRMr(jZOE$>JC1OKnrJQHghGhXO zYc=BlE_^O&B=LEUaya2I2ry0ykg<>|fzXHLIC-JmG~o`#x6efY=i58~>=5evUy=e7 zc|v1S`3Oheoj=IyFQ7PS9Q3zOIDgeXyVTZ1oMS{4-b$goAE>4j^bmM|V>hjh&$*!c zu(=KihM*%v8w^L+hFs$P@}48(C3yI#D$F!dSvj)m42gG%>WkYyi_qM!&v2aVS^tb_ zG;?Ao(tHFCK&l)fnvO>ayieqi)=z2luG&}=(<lkeF-EuGYjD1@Z*#qX_oG08GSd&O z&Ma~2_qkD&F^klw5BwPj@z9?iMgF0+O>+5g8B(y4_4926*Ck=!z(ut}6RN;0N!H8G z6O+|(pj0=;sZi5teiXQnCuv*2XwOT$uqC5p#w<IlD{KkkQTpcsZr}8=|GpB-Qa^VJ zu&J{XPY<#3AbN%%urC-5<%E7@tO)E}`}zc(d+;8oErHmq=(Q|pcH84^{BZMN5a9<G ze^Oiwq-{I4!CPAr>v#tYx7>VzKeA>`_B<S{-@qV9J{{oYA$NlZ+_D(V`}yH37<IlG z%lUfi@#nC}Tf7u{)mr}a8WJsKk)#d^znIqZs`oe<z2J4HUuQRvfAYWzvE7$hJ~C0Z zqMesH5!#(b8v-;5!spD)&X(g;b=9gLoQg^zbk?x#z=WSS`!9)*u_3GB3X=7zf=~Vr z@`IqAmqSC9vc+AsZq~=CZdm2kN4(ckgMOqo!xn2@bnHo8lvIx+r*H0H+$t3o?nNcA z0X{W2U8WTY?`PlVkrr*;HyB2NTmNu{JlWY5adgO3vfQu7wjl}AfT(^6)qWX$phjlz zTkU?0H~>qR4IK-zQ#<?beMJ)N<!>qm+<Jl|+kc4BSZ(#?u0xGHUl3W<5b_2p0n&nU z-sLSFxqBmxa9KIrw0ZD)5WFz6E$n@l0jIt1ozAmXK9FP@`<KT&fv~za?5&7o?AA5* zxPc4PdSgA=dXiXxAfBO@QvPIkY=tB;AICOLhk2OsyfMSvS)WMYK7~!Oe0p?GwYclR zrYCs3aE;b2Gqvd`oT`%eDHL(;jXpHSP+ffP+5goL)Bq@XFnm?islW8VlGZm$-u8kA zue;i*U~+4yc2ZURG$jCx1JGFgx_<vt%e$DXdP2Z^8IVm2z9A?jb@p^>tx{;uP$g`# zZrpX6%z5Q1Y{P&}CLOn_=;|ghKzwq$TDImG>yeotHT+Fnch>Wd$F|ML2XxdgQ+?qI zbEKx$RuM~95_j)$>uYtlkN-VlIL&i;dK?uu;(R3whsRyCVjDM(7*~W#hMJ+v4Gn50 zTi$W|#FT6^M+O<j67z+XtbJ8a_N|E^$4^<(dM>A|2fFO+hhtys<t!AJ?(<W+&7u#| z9a)H$!~X6~z|Ub6DOo;YPG?mtuvwGj{gh9>YI^dl3F8zu&4F9#%;Dj)AY*Vo9ARiv z=F)(sFp>}o>u69IISVa7iO{+6Gfyefs<Oz6h4&ft(Rq@es*e^=(AqeZSoN6~Bdd^_ zAiKIofxD@h;LK<29vLSmn?<o52Qrkl2A56c`xQ#p+>jvV3ATF&c2}(-)q8l(I)Y`{ zrCNW$t8UEd6KOMZ*%Aa$*I@X=?AEkxC_G{q$ke?)*=si4=K<Vy{PuQ9-Lw<n(Bk1_ zNlO;k-QAbxTQ@hqsMpBxF<p|8(s}m6u6XLtG7a|iXt7ETur;*MsYmu|<UH;w<@;3_ z=si)IjB+PyRtIfi-ImH+`+T)qZIXAXx$>v!UsHRvdo>q!Iffx}2B*ncJf(@(H_pX7 zO$-H#RuMcU$wfQ!WJxXDEu32@r7Gl@fgw*cwNUgdQr0J}Chg)n`DE);r*_nMX{u^s zXp~4RIV=ag0hSfO6~U>g+E0kGJSN`EtB1SQELjPv#SnO9xLJ5R=MoP|P$$wJ=RT(m z?YRosY?Y1mTKKKEHoRB5`+^?#mS%qrOr)n-FVz#zSOdSS7z#AE$=9DVAeWMCnX^9M zo!dLEC^|b6tC+Yjt?KqDUJs+Y)Z-~CMSlDWn>6N!#c-lfjFNX90~jjL8>0ru4J5XD z4Vge!|D&JtuxN{5hi0Uu7gY9~@HAVFS=Uf=soe_&Q2qlQVR>I+Ue@auuv@OvJwus= z9C>>dqqb31(pdc&<a@HZdqta3*6d(;<uy=DdvR87@Y%bPYU6t7H=DU!CWnVbRHojW zU(aXUXT7nWr2`crX~JR*8)y5(_MMS4R+)x+e(2ua&39Z+kB4VU1awpkjeMIYEjeZD zOD+}q1GUps%T;>GyuuV=+kJW+^68->!|<@upDVN&w+;_=@LJ^k<V@ev-ldmqVf#^N z5qD`Btlq(FB?t<HU1!^8q^(mr?kvjF)yK-fx?QF<tHmYfz8S#iUJ!^M31us`K;tb2 zzLa`ioYqVMrT|=c?+S1OeRKXA5p<^)zf{GWeyQL$chUN{pLWv63x3V$UlXUzr&rSs zzZV4<(_ed~;@-^|L|-h2TY1~MI-cC$Y^jxQ*Uk+L<OYq=>XtVr2HvclWt;Y0yZN~6 zj~C9r!C5_%7B#a$jkTiJ%M_lGdE&WonT4bls2P{e>NsEY?`-Yu?dhtAFE>u5&gu8D zTd0Z)Y+qSZCrjTFK>m7VKZ}wCc75{h^2|PQSI(Z0CK0SS$#JAg$CSRcj*nuRJaQGi z=qjcJ3}phMQ;dqWmzte+E^bFxdpMeE3&FBo+CH=U_f43|LnW^gZ`Sd?LYSLBGO^Yq zM9o@?KA-(sdEAsr>jDs@(a$&XsYD{-95p3N2d=YedlCBiOCDsA`YDlO=9UanOfem@ zCi^hLBw_YV2T+Z+&%}1}x$uX{oAE>`vu*q##z2)uO;Ce}`POMl((m9g8-Sa&uF7Kt z5)LIgxc(H}9-f18QrsI;6a9XxR{yQ<Rk)W}TXMIy4|8;TqB?ySDXr~EasXg^9I&gO zWOO4*%m6Hy<?Nob`KxTuns-0%RJC|MfjbERd^8oQ|DR&7`B&EsArXRX(F~?XEk{Id zW+o}6CH77WF>5wNT#GXG1b?O3M{W|P?DQkMXu3J8x+$2r&qV|Xdb4_DCn!pb_z(a@ z9Gu_UT9)c>b|0m3kh7kt6G@p}V+(Vw8_&~4o|qa%sk7Bel|dXz?pI||aK@nk`)k&Q z>FDUNbl7ka4M)Zh=umMV>%k!)J|rU8E`QGJq(9-v_iTgD&*OHt7a!>hdQ2#qV)SpA zN-v5Y7*L6%r(!2ZeZa|l6{d%Xa^Cc?&BpVDSkz5(C$4}J*5JeHpXYJud&~grjMLP< zGWMH+tYBGnqUZ=Edn?zo_9|}VN&XP>ev@&{lu#*5%p51su5Kw<#oo?tbFyc5nn1$T z!|;OyuMtyozw+Kl?N`4782jWOAMn!O8qGKv)!LqBL-y<TCK-?Z>bU_yBZ-@uB$)RJ zF(oAh=;+GpHktbTgtvMuIXQh^f`<oQr^cn@LC4E&N_TZLJym!4dNRUiW}vAHj2P}C z6*ju=5t=1tVEi()F*&b*tVDHD2{DKi>y~GTUCdYcIX!G7wP2imM-kvs)_5%#iKg{! zvR>^A>!c*7ueko8auj1viZ>bPHR^$vA&zJoeQN0LoVe0O7AXOT)A0G|jw`H9JchkM zqvElq^Z7A9pOwNRblc!)J2e#dXFAP8S(;sOJs&{OuS85(n3BBjBZKtPl_RGq#~tF2 zG^&zXKsc3NmA?gP*G+eO@H#-+Zf5NyuCMCh*VIhC!$VE6s^5{Sj*-tvF<K>`B|k_a zdHD%4h5hBHgd3lKMQZQTRWI~-=bl}#(+ZatvFy>aBu*UjtpB{DDQ{bgi#RrXfwn`! zk@xpkEfwd1_R!{<X0L=c=ZJJFkIf)C&74~8MZay2W)Wdp@^EYm4ls!Rrlh_#Z>uBg zZ^U>qKZ=mP^LS^})E`6vv$#bLPIlE98F(Jj`c-@0ZrFDe^NX8%`3RY3pH9n|m><Rd z6>CbZ2cC&jD<Zi<uP4(ztXG_$fYEx+Gbgr9_VbfATd{;yD?T^##oY*EhyGTsOHt7@ z_F{XVyYeI>^zM<{E^Xg6Rl8Ns`l;p&bmx^{t<}U*dx}&&{#J@(vl^Y>at;h#s^of9 zo&ogZ`Om#94~uf8<ZrnW?CxA{=0yzfPp036vfIusQ;X%JqbxGB)*DL*wF3`>q$#@! zCJv?xpLq`<9d{+h>jYKWa;50GTSthv>+`#xJHr~Uj+buMGeZ2Vm$Wt<>XS1fD`%b% z|L)m!-(C%=?$p72eqG*e9kEngpn^@H|4*cCMlm;pZ2Ju7HVfa6frW87NUMCwy1H@C zqO3IYw!1I?@i@0?>hGG5>BY0ALgU#N{q_Q4Bz%ufT3m-ld}5R$6Ru?HA!ZmoRw`JZ zlX@dM1v>AZux***D?@jJUcMp;?AHBT<8<dpH>({uopg&in%GSd3Pl3<sznzLYAyzf z%QNb)1KB_x7iYQ@Iz}%5Jf9J>u#|M6`{TRA+g#$NqeWOoN%TR~rxBS%*k{evRT-5k zpd<8Eo<Y`b-dUdYM+DtNn(yX(7fL~_MT-02_bkHRLpO579K)h@!LDw^&TX>X014f_ z$<MsYz_%FmX)!7<cVw303V&X=;EJ;NtBh=eiF)k+3CwjeV@(=LJZX(%B@4BeFG2t8 zyfdAm72Ug=3MI{9s9WVBz!J#ABqi6k?drxbgVRaSU?+WA7`&Y9J?(NXZ@RtE9Fn+0 z(MCkvF4%-a0F=suLomd_ik$Dsbs(`%nV7Huv8F&~7_T~P|HA?|W|4f<Q!t}v)q!zj z49m3IoJVu$yvKa%+Z4qRhrcDCTV1Mm{312CyR$cE_8GUAQxE9fnXw_aRKhdvmE-S( z#A&NpR}!bratxmP7Hl!|PVR7nlwdZP6CjWg8hWHjXi(8LgdKfbvPJwNt0V7|%3vBJ z=~T7*#%XVB%@V!KZN}#0VEe?GA~*0Xp^Gx}p>MW*qLT-UvT)=&7JPN^xV+X<u@xW( zR8LJ$w+OlyGWZit=}0}CfX}m0X-;yxe}JYTPnYmhdLj_c7%xT8Aql(iI&ee&^_&(( z?j~*Um(acT_Av1qNcqBO#4kD_bEg|A&qFNL`_p-5#s^w3ZuCNCsaC#o3dE|lWl1Lc zEagt1TF2@iMmEP-Xtn6D+}&rMeUGmt4Jizn#RLs#H*ij^!^-}y;?m>Z#Z=~vhV#X& zuvK;&IM3@mTF!jw3J!xcquWsUYkb~S^-%JqBo5^_o9R?S*2DDKnm!D8cirDH$5AV& zET8ZWxvkgwV&=C8n=0NGJ|=gwHWCKDH+?OQJ_qa0=Q$cPQa5^9DbS~pbN?2zt{X9= zSN%6r?>6=~#ltO+{##Pix4--#e0k5#Hq+kwKEk)3((dJ|tH9r=3T}-~)x!LIQxg(; z!(OaAh@Kei-rXDUvdvoB+Z`I*s!Z8#WA+9@@0ts7FO}nC;-8NQb^a;9W^f!~^Ll<% z+`{TcB56RGW;Olrl;J&R=5em?s~&&D^2vP&SBX8$2fezgsXJ9W$Uk?2LO~o%Y?k^v zOWo-*A6sK@b{dN|P8kr8Wn6Vezg>36ECmJOEL_1yx>kd=;3Fw9TsX2nOctKH)=POO zy!F)IV@5I$`>X<9<9sn%ldH>RWC*na7rR9j)BA(+)c)w&wOssJ3%MLv66FzaEJz;G z)ieLGBkCI&fu*8F$~{jYJ&4P8c`^hdTjAbR{!3L>?u<_;r522c%j(khY}kt}xY8va z`5{AYqK0TR0C0^+nX9`hlSW00@rnw%>(^^!wteJ;hUmjSgW8M2@K012UfV8-<6$6{ zRrkwXBZ=x2WsFFl=CO|10o-@>^`|Jfji8P<qg_cfb91*~dVmmjkcO4%<H?Jd0R|E1 z(e(Owo55>P@RLflKn`ZlkY&g0M5K)G6vHipO}pbZoasux(?RtcH5R9Gqu$Sf^E;$U zesfiAO|^s9&Hp3nJlxs*+xOpAOIxd@_Nr=aQq*2;DQzi5OA(?{o7l0EsH(lH_TEL+ zh!K?7q_&!|XYANw#Q5d&JkRI*`v-CyxsT(1-`91%&)0blck+3}C-nXGuo`a~{=`Si zRp+>jEvAj!p7wYEVoB*;DwkET%zY*3>|pMzmzG+WaPM?E9K%^CNRNGyo;wK{WwjGZ zkm^hKhOF!bj7`W-c6h|S-AU{;;Iqt!)a@ffc&cX%5=j<^vE>^wpB~2-m?u=_a#8km zI_Ka2Q7EQf0HAao+IE}3<BM^pEw~tCs~OMVwdJ0ivt~SRQp36G@LB7~NiM;DE}3*8 zgC9;h9O<8G`bF~}smcA=(mQ>~J1>U&if>_>UA!H&`K)yMr{ox8pJRs4;#x;byL4S| zvL~@JsAXyMVmHSFZnoJJLd;ojYtWS9dIt6U*s=oJV_!_po!(5rZ|}R~o(;OND0SBQ zWAsq8rJ89I%jRI**~aA9jAuzzRjzVF(Z6o6{-Nz7L!}JxCBE^P8igJ*D@|2sl|p$S z%o!o~j!#2Zy8WL8x_c|4&`1}^{8XW`(QnUFZ4W7ZP-}b2)sx^mEy~B&AOmpPdYK_Q zn3eJ${=9|vZ^@wsXgthgF7?Xe6lHHdk%puk`N5$5Mb9jV$BvgDZ;-NnQ*6`lu{Jd5 zek2PC+8OI<2x>O@f*Fipmw-WgS_fM4T=G=pjkjntigoE+V?`o3iJ7Y5_8baBO?O@4 z{Sq*(rK!~>>6nl5inqs1#;AKJGgodva#yFp!?)E^g;JU8qg$u_)O#kqdg_a&=EQPl zvJOpUEFt1D62}jPgS7s=)fy_;2tG*?AY7g)U+@rG>>QC2OeJNOY>lbMn7s*?hfaTg z_KW*_SB!u_rk<`REo;h#wQi?J9#RIN1m6El*d)!5iws)fv>)RG{ZBT72Q{#!S=nhj zDb1W@JQ-Q1zJSDJ94OPxVKC(9rayGMR+f+Ob$G1e_GKxAIET5Ip0DFPYkbG|!?E*I zMf4Nue;i;W?*8oSof+r<fR`TZXOI+^!X~AY`JnNBUjlfuzwy*0u+cntwu37e<VvyA zII{J`10_{zUn-2Q{p~a#2F6##xSl{ziM{vgtRL?Yo4pk7PtU-Zq_Nqxu%O`qV4x9I zk7q0vi&{IRNW&FR#1$2#<WEkgAJx6S7r-y59hGpjmBy;9E5PvMv}1C-SRuq@XKdc8 zMq60>p&Oay#o3vwbJE4<Lyz@{5nNU8zOj5&yPx+)GKEZJInKq|Wjj4-apbiHtwO`z z+#I1<9R0UVX{U65&O{7#cgseutvKJad%(TT;^ySl4QO3&?_qDZkdRP55q)gn2V0^H zK!$XNoa;#p1!aK(?kL2{SNEhCdH?**W3C~8E~#>%t#!QAdRJ`T=Hbvbt@mMZab9uN z2xUZC8pAnMo%R?RpqnSISmkjUVxFf!9rSH?d?eS^rBS`u7<>0}UN5mJh0^?F<8zW9 zMmK-t*T|SYU|SfF9$>?AdN;A)1A9@=mMkzST`{qnN$8uOHm``!Fx(?rx0Ix#oPFHE z9xwPS`!^s_Z$YLCV})Z<HR1u9qD(l<Pl*w-AjhcJaj*D24t#VU!i|r@T+Y3ANE?Gs z@2Ni6ea)PHq6|a#T__Ht;X~jM(dymoR|}v+sA~T-FRA8V@Hi*tm2H)OyeguI7&o<Z zJv4H~b*-5eA*ox3ZyqbYJXs$GdR+{JkZ6so4^F74%mnJjx$}!x?i{qccRJRPKP!Dd zY3m>iv~~cPe6e|@(El~+^*^C1bBfd#$-`~O%tWH{ks)*;zIC&E)+-r5ysk`W<gYSr zvje26w-&*xr)?eVf1xF3rj35v{fd*-SyR(H;Y94-+Q^P@;tqcCcpuhck)V2<sqBRh z`k3svNd}$h_1!YNl%qa>06aq%7km3G;#|iXj(Us}8oq+wPT>zHbse0{EEn3&t2to{ z={ZEMv=mNdV6cnDSqD9X>9GCsf_tZ%EdsWmpBbjV=E~ntAdR}J%+gg4uwMWqNWmD6 zT~!{7^=j2YEo=^#*zy6ejou2TMq|e(X-xV!UFU^(9ttI=%d~2^<?PJ(WLH4TCq_;) z#hUNZM<OLrWSzaIw`@PgB`|>O^ZF^w5nj8Gi875n80k-<Hx)z+c7iNDpiuq(bfu&7 z7{~e(Ttw9&<upY4LcpkHY6k6*R<lpgX0OFzdFbisiLN^DzSq6UjQNtgSt|bM_9@SM z<cBS?aRx_CnvUQI8$XCoK<YLy(D&oJx^b*&t;^wIm}A3kagmj_@;Ky4Du~^PwWx2a z4mV26UblVGuem+#`#_MP$Z5)$-jVuI&KU0<!tTW**ydWofI{%je!?n>$!m9|c!SL@ ztlLUU$sL!+)bJJrs#_p_StwLd-<tI3KhH?4J!~U(4^<Fdk8jlPX;?aZ{dSN0$RgJ3 z8SvTKK5jrpV9dVn%T)&Y@;S1~*%C)bh^fNS-ku!*4&I+CT&W|JI=s5Q7~`tPw{_e! z1*e7Ep3VK0uQ+*bsH)faOY-)G_uV6S;uq)+yDA;e*0;=Kna|e#rul!Ze+h$TWDeJl z3_ytGurz!x!^%-zQ<%r$KrwC4)a6b-U*z<z8N$Vu)7S3yldZZY56qpxct-VPyY1=$ z&*hNOueSz-qxl=Qy{quO_%KJM>Wk9~P@#$Z{_BM?)Wd*IMG8L0+9MUcYUKk}n~R+g zpcE)@tif|$O{`06T#`m*Jbyfrl^*|nmY1t_v8lCi+E!`|kTzL!Jm@jnPnwG%c0L?T zS8J*7{A<%BXM!wS=3_7Cr7xuHs^m92nM^-MSf=1ML0_qy%Fig|#D7taP1PcTdRL4# zRcqTJMU~@Ox(V-HoqkYT-BLsl{8uP<?NGa-EC@Uocr~-s&0NTBVamTlB{;HeVAqVt zZQ<e`{Ohu`-Cd<8jNq|R)XeFGhSi0{#lz!(yu-1bX|m@+Sb0UnX3Tco`L+V0U!>8g z`$ExUC8r?!qK}X9nW_SJxl8xE*FgnmK=SF~lW14-Q%X97i}iK}UVWQO4{&bgPc$g1 z*4GBr?=4klz}NQs(Jp)1-e}X5ivW5i2Z*A}4q3*<D$nIvBz?7#so)Y{#V*rR(lrIA zap2LIRp-axa+ye;A1zou2JL4Z9k8Dwf98D4MZdP)097`57!{Y6q$3DxD~QXW{>EdX zkVd!TILJ*=QNndIn$~w!dK*6H*H~qRAfSNhmkjJrp7_32Dk(o=;#P72-Lc5GFQAzx zl3#-5gE)65+T2gTk4LdHhQB@6mpn`_n~#)zx8f2mevjc<DYNprum{Z~o^IhH3Vzn8 z;6&u$5?t1xC);gn)j@hac*-#pER=y-tPcHDEGj>yL<!udG4{G##M*6#-ne#_mx+(S zN#r-29L~yK4j&;JQNLk+7w_3;{obWb`fT7cPN$S*51Lvt*iteYA7N%?o2$-7!;3mx zxIX79jdJe-O&t|NTl+NCH>XeTz~pQk9868T58EAq7c*nNj<_l=1hucS$xqpU-4I2e zE%=UJkn&z3D5YU>2D2B36yS`Yc(N@NDsZ%&@cd72+MGD<{`*~t%&OM!sxX0I9Hfz% zBs=|@gp8z6CYUzv;Q<$03q!LP=Y6B6bc&YcciHc|5*-!K)<DNh6|}IOp@5{5)>?kS z@A=kE(P0JfD#5maP?F8nN=|E4LF~@>N=ha36{Ty=<P*k13HqRmW+ujrlf9MdzQ&8C zOs30CNnPfQ8F`=Wpv&c%AZ23F2-rg*R_Gn?0f%%hBTq3a^YbQ{xp;N3h{kdEkIxN} z*2DtfE!pWW)SIBvX>5r|>dAbIhVMy6{Onl=mz(jSNXZq_M6-A{WGTwTaKxdwJCyYN z@G5LWE}r4P?~;>5Qw$UA&A7C5tJ3~o+H%)~lCr$2H)m_hJ4TCFK{L)XJ7Fn4!rl7v zve4RSi?Cv0yXH=^i%84ZwMEjlD-Y8S*qLXl&<BMFMAUrB`;8qd*OP;2yJxpU<JlFc ze8*Shrq$EF6)KfmWy{Gc%R=2MMuD~Ezul8Bgk>&%35sIRB4}sM**w@Mh<DiKynxuy z#m*1njezQbB4_)Y4(D?y+PQcjf><AYJg9Z#uGk{FMb9?X_1oUqK2JAGTte0>Q%-+k zf3&t+TZ*-p`rCetVtwGWbmK~26l@NDxswy6a9ni4FW3qe>ISb)ISW@r8H-C1!U!Vr zQ?HHlX*vQkeyOY$7H|3-?0`0a&L77lV)XPXVkCwzqXuK5ze<bKwkzdNOB-rD-7kq; zX8=z4+3xI=htuq|(|gXtW7_tczG><!nYBp6s#SzSWE4}7^4}2NL+hK=ME)lZpJKd^ zw^4sjKT*Bx4vp)=w)JfK@n@6@r^*w76{g1Y6)pX{75nOuN^Y}@+GnR6T%HFj^KzNP z+egQ7i2&Yyb(cYM=^fB<XhR;EvJxo_gAf<#Xklub@7~!!(wN`nvm$lm?34Htiu!tb z<E#i%<?i^dl;gjJrujTd>9^?V8E)f@l@Hox8_(&L52HF(j;3#8K74Hq=3fXd4$Wij zils?0=8~4A_*n?of3p#*I4-wnXw2Fg9E53zb*?>Vj`!0q&<c;jCn-}&L{HZ{ZRKe> zSf%w-e#Z11gw%1#@3pNU;1~0>=bEvASmJa^a5uP(81<(8{rLyANc#6dBQWs;9R!dU z^ElZ3rvTSPaKvhg<RsyY6t>3M>|gLiLK!sUGe^Kv=KEqNfFNc!d2=1gC>GCLyw9ed zFX`ihxZq;SC$KjqtUN2lz!!n#f7w<0@CtGzD=q~Xi^UCj_fHvm_U?)_98$k1l+Tk& zwcapV5ja>Xjf*F$TuTp=t3;FlS2!hN_-2lfWKkEJjy+R{fA}hD3uIQ^7eAaj=XK-) zFdb*I2Qc4)sjd7qc5xWHb*+Q;1_@+g^o3mOo6a^z%7`_VKB>JN#TS(-582GgS2?YG zG<7*Cv~O^`!~WkSG{2mbo&4T^2LAe-xodBfxRA9;0{Q|B;|uHLm%1}$mJ;msW=*uu z!WnovZd*Wqn0)j_D|B4gJBOq7i^_T-*H<VPO8Y$rGqqft*p8gRU5mVDWhZWD568a^ zNhv^eBdOh6nAmRb$k<fMZ8r5R{Utie?#%PJ4te;+{m|`+Qg+*D*2bqK%Z!o{A=;^` zEY7<bo2_qz`KS%}jz_;!-d%U_`qdgpmO;aIJMeIkk@%Bdc_zVlL@rHKA+UVJn3k(% zrEgI^{SVINhOEf3b8E{*?YR6l`uy0+IUFTNKFf6Hr`Y&UC5}4QsfVZRLBJ>Mw^^hr zGE6BU#}ToAe?&6X{Pl*xDw9Q|q@{fijve?oGm_HK0b}HIFUV5mqGsK<r<LW!6uquE z5ckYqpA>m!(`t3dj2nQbnO?lA-I0b5fkU%E8BoodgP&2wlaPw%S&yqOSCJGnsWQ7C zQ}3iQU7w|X?6JB-M&Veum?N_Vl^dj0X%l<<ln4`cT}MJ>!X3b}4&Q{i!*JNxo~<G= zeExWn935ArpH@Y)B@IV|`>e?ktWsRj=jO^4l4A8(KTYXuC#Ug4I&;P|<5{sq+q%CS zl&XW~io;)wFODM)ZF;S&x<2xCCXRlFqV>aG;E-#DiyjS*r^g&op@w%q?FS4F7gzh5 zt)t|X6T2<T&$T8eC?1P<WdA+0E`{0GuIG22iS#LkW|TeS^633p_`wrBy$#I{;o;Nj znc5%VyG^gRKiAppVa>q%<ET$@?=L7s5DfP0DR{xg06s`Q6Db*wZ8Ui^g158w4|786 z$1oJ>?bBD!>|d-m({IyPJouv;u&^X@gz(&)+x2NCTP}0JUCk2Hl8Wn|eH<g=|06vg zC^vrG@Ofqi&{+CwEGJ*g$xl$?bK$rLkwc;yF(;u@D0hRVj`x2WIL8e@;%%Ka%l!Nu z4eJw+$(<Nf)1Nu^<vC%qdZ1Z*7qk30E4b0Mw&h}Jf?0lqAIaH`RH$zma%9~7!Yg1& z@J{}4@4LhGV~?^y6y;7$leS$?qyeG#oe(jXndwA)KW0%qiz7_DRuC~>MK9#&;_&u$ z?i*bI%ljx}iolG@yxqX|7X{RWU0TwgeW&nP+ErbY>2l&j;fI1g%{T1HsRitt3!T}q zlxC`Xv?|jcGpF~u`tA;`3E@qgh)>|5G|gaM3W`5%ZEX#&^Tc`D&mO>j8KrS?ab@%) zHT^CRQ=e}1%q`@1E%xHx%BXf+#3Vk4$eC%4rKX5I6_}2l>YM+~b?4sV(P+=+v~T{m zn=U#HAJP*O0j*~T6CABv;FKzvFGa~DgLOMtQ2jXZSm%J*eNgS0Lj-e|zIj`$)Kny8 zCMD(?JE#4%#&5MoX>sQ9y|}%&&cbut`jY7=o9d~1XxjjiPCPi$_|~%c`jsB!2d8}T ze8tYJqZp|sf(j5x2NgGEr-#f*%CQ#pgyWUnD5|5EZnwX-u_Tyf0h2a77PMQ#8OQ96 zw4B<VJIFO_Hw|}95cl3^=;V;4k<QIygK?i#0<iE4sHD3Ya9{LIKZjs%57+vUkL-nN z#6Zmekl2$YRrdGfPPR&+L1`xZleApMOwLf%&dQgo-BEA0g?c#}(l#FH)XKe2S9E#+ z;+*XMeXKynDbAQd8|p}93<q^0A-24pv&a{jrFQLsV1Y%fl5JScC&nkJHA*t;TFqFI zeonLy6N8X$h0wq1jLyzdwXP`gd|v|g_s6KU6UzyilbPzy7amGiX~RhD2lsIFD63UQ zqj<-~j%^ZJM`+&gp^z1ks*f`-=vJCDVnMZsDs5`wZHCS^`U#g6RasS|07b}LwjkxD z*|oN++`>_$Q#Ua_Vt~@GFO1KC&fAZ51IIWZ&Q|Fc=$#P3-3k-`@qJPWCJdhV<{}xu z4-#ddT$Cj@$d2a(C!Mr+B*k2Vu3u-$a;9q_p{5Q6=zcYogNEdLl|Pszu3o&U8RIxO zJ-t135JG%j++mxsnM%S-C-Shj*|^1)ZZq)s)tKpd-3wvXEp>4+tKQXc*ZAbzLNRUi zF!I5^hLh@}Y>MjPj5eJC=3q`0^p-4d^+VpOD)8@pIw2e_HEoFfy*Ov28b3plJxGZK zyX&lJp@j}FohU>8y<(urmacx7Tl$ZIHZ@1_Q~$&G=K8sQHQe5*37kFgWtrdQ`0<H> zv@=)o$@NZ{`KPXjU9+}wB_rWC3@Ez#*R)>_TTj0Bx!BFrjK#e8$bHr9^Y-s&Y&=0^ zaY51++T0hw{($R2=^cY$>nSaV_gu{@6ky@%+qT;yyHss7a*rutoc#BjGVc4Qp5o%h z_`n4XKhyl>Y>KL{Z{_%WJ{TctSC{wuA+8xOm+SmldCvhN$PUvIy{Sr{o^c^O5=%ZA z{7Y*5^G&QW`si9QWbfsWcKEx)BZwSIoysuxg2KMLU15VkX!FoA?)*eI;QVBP*{4W0 zP#N7BYFNoK@AfRsdNn5EVF)vgk1cp|e^=DyfXGr`^4jQVp<9<hFGIo5y6)=?-P{0) zD-20rmRf%rn`W``70YdEY`z!(dTSwm?&rvB?#Y>yVoV>^cEKOZfjrDIk1XG=G~%h& z7G?MiF%LRmK@i{E9tMoOy)P>CP;2(no%hPSPfpocTJ6BA^fMjj%VEz}ZeBj1=_l)a zT2MVx^CP0NbYvwsGRat|SG7wUB@@_$k~CuFWHV~)qh$8FqQt09X|$kEc8yy_lCTsn zee1BPfn}b&qa@XKvxxx{&ka@J7>aKuZ!Xo+Ais8XA|xFmTAA9x3m24FqJwSLniE|F zYXRvG2z)xh=smuP>nKr9@SUq&?-mQ%=_Vek_0qV#;e@x)VytP|wt|dDoU*!^W0aoo zFyeVyJ8l}@Uuj~#zARL`zBpPbwT^U0p_A$Jiz5d0<ON+%=+Px%6L-<byi6*iKws4Q z>Ax~EX3lq{$MQoJ&@yK6J*u+2naO2GSHkJMpyD&TCJ(|-tea`v(lQ)9#SHdE13!XH zM9V3AuWhs{s5_zVHXhR^9c?I~u{RVjJE}H}A!ugCzAOVVn1uN{chk;y^Z>h>65Y^y ziUdP1lenfN<hNIE*o8jY&V^=l6`;(lQkT4UCNhDNfXuI#Jh*7%fEmXFOhb%JSy_mP zm)0TE2ZS9rSg2l#rcz|gC;U$7YyQVtuLEAbc9J%4L^7>7&G+71Wq$CrgAn2>>*f;X zT}m?tKN%>)%ji?zoFJKIgzi#sGtG4%3dEZGJV*;cMhi*>$|JFKC!wz{B=HZ`<@X$B zeCgSziWM?v0OlJrqiHRNF)r@->|O`Z`(@hzVHwH&xwaW#Q*kxKNZ9$gLaJ0}FfR&` zsMtOqCMm;K^*-uq*FZh<jh7V_Zi6ajO9{O%jLxQ?E(FVk+nU3TlzuLrKLIQM>sn;4 zaf<0*86R$AzBFIRt8zcfV<K8Sc1oK&TL3OsurR)m9qn5h$3c=5(Iyrk69J@^RH%Jc zn$@}H=n02RAMxrN-99m@3~rQZ&FrDf?|I2*GPBNkhv~7c2gy%-Z%^zp%GcQHdBL3} zb+<$3uWuf<hcHaBv_28bB>bGo+RuF|Z&SK(OlU4js4bXcQCXgl>;gz??=6IpfQ};0 zVr}k*sHvOi$4#DsQGFDG-k_TGosI;TNeoLXIlS1Ci~dQZ^bg$1uNUo@2Fk*f-k?_U z#S?Qu*^xSXdhuk6<ObiMh(}O`u@BuZ*$pbdJb}v1ahR~s!UdI9U_%WOcn~WbPw7cT zHx%s9c}HdWDJCD<He(P(z8OAc^HzT1rd)=46xE2oX4O|E2m47-P;tpDq>T}C&nJBK zQ~;_ZtH0~cK1r)1{?qkPQ9R9`;4DN8<XT`AN}3uZF}8&N4+JnDs~5bk{bQNWcOvf~ zB~^VA-?+i+G<3)DC1)8-wEOjmLXm~W=3xgjvG0_bxaFOMZqPF;nhu^<@7;fVnA4-A zY{T*;vLcM0p6BQ=bs+a7TzCHtTLMB_l5ZLMHCd*0^KGdSE8)wB2@ve+7(CIkG;?1S z4~M@NCS8i0vpiA`7!!X;LkJpOjNrbf<eQ}>=jx+jk9jNAfIXYh2$aH8qXFN^4qB)5 zVXV!O@r>|cnUKUbz^Gw!nbvsKUzhG1ua@3R(HKXZ-b{)ciu0BBW&&#4BJt`WYuz6) z`r&jE4E<AiqtR+z7eXcZmPF5k=wR?k7AIGb&B^c$sO=l^lCh2=ijW-M2y}+qFXABh zp>bz0ID9i@L->!EWfkt*x*~!-TVm0Na3f26<mk^k6IKuxi&Q*wzXkRP8}a&oZcTZ$ z(pfO+CghE_R+(i{D{FE5@bwuQr>hjc*%h(fWxKCKimik;*LvxQgDy$uX6P1CROqk2 z{d)ltXNe35=^L^E;-~B`3(*6wDyQUL?T$|Z$2#8_y?K~k9jJ3K*bzv4iFW?ZTYXPN zBSc+i*ZP<0)Lk(56XoI&3N!#n1XmOhwZ>Tqd*=L)XhvvLwx`XA8^|sdms?+(5)9zP z?|R!2uii>MW%pNgJr)v~eT_bjW0IY@@mp!!8ck68>-=2ZoZmO#sLtuiI-lEt{ueox zYq)p$#5T3)GCl7NdBl?f11U8Hj6vg-KDnDbYwxw<q9Q+n!QDWqU=CwUrNxzrbs1gD z9Q(?&fO&1B2V8N6R1v**dFl^ws<Eb%Z-Yff7mC!I9X`zl46eZh(|JmU0`F|hj}8jF z>z$%OE@I(wYA{srkb&hO_!hqI3c5t+%VHbs)VxdSX#VobPlFnmnb6rw5ClCSGpySg zG7|}}_?OVYG-V(;NyO<|h_il?^arNKM49@@We1AJ9}FuEbQXs0zgkAc!JCsCj|ds1 z`q&sY3)J6!iL+d#^m_&LQSWwC+vN<Mn{i!?+Mm>R{=Ou-$<uvvyNk;|*Kr(YrWzuv zL;wV7Dpjc&1x?qLjF5LW^G{y_p$F!M?lDq~_2e}#A64<Ed=>d3HOQDnit7n4<aj6- zILeoGbgQa4LjnnpExbFn7&RcaO|LwC^VTJ|lpt^MRk4LX%=~&sX?IoDhwe0d4qt2? zWx?FOZ~mETF*CHF&{13~oDlN{Abhn&i{=WR&mp9%EyrW!hJZbF+SG4nyB7*98kk77 zxJL&~WoM`!<~sA&N%3T>IjrrRLYwSr`&n*fl6x^7xPhwOk@#=j%+RTiE(WlOave%; zEc+^RS0L)+2ST5B;JD|(RL7vs>czeq1{L`Shzv(=xo+fYMZm){??LR^{fcWyoHNOM zdkEvIxpE&oGmIs?0E(-U(2egbNQ;cciM@vMdc?nz?A@Jdu3Gy@Urk$c^YCJb{p$ei z^%+E)dco<h@BQVrd2Lb^3<QI220~-1P#K@}>t9m*W#(EizulLs^mH-9dh|h24vyjK z!U5p6NDh<T0^zJ6sZi5SYQ=z+1?l9kA|XM!9pWk{EPvxybWxl>6`VG0_-UHq^p5<X zSXZvRG$uNp`BIn-+pUj(7Pnex_cvIZ)QMyzaFug@sS;LePJ37u8R=8yEvAZgSnRU9 z4+nqeeAhx0FYQYUjwV-oJZr&lsg)WMpB=F&xQb0zSK+H>PuH+_pMCY~Wv@nZOHsb; zE0AP@>Eu&`XT*ES{-?YhG(a((<=7%-HQ`J3;7Z`A+3<oj%ohpR9pz4;<p`3B+|j*I zWAC1+{HtH5dc4cbtk>}-)9qpD74Q45Be^=>w>kD34&I_((;9Qo6MyO?txtki?W|{m z%9};-dS>=*9;=eNrM81|K1EIuK_^c?q5E&8eX<T`<N0?hy;>?A8laHET3QYhHMe6k zK4bdP!Umb~TG(#tEDJ%>P4+}o0E%PBR{%`dqp>jiBG4RHY0Hh&=&ke(Sy?gI&O6T| zisyqG<nE&?U&r*egC7!}FSGvk$Qi9nnfNQ^%)MFiRihSd-QZ1K`>Wl`Zc%YOu7K64 z$b3*KpbK_B|FAe{WR-$F;$-J~d0U^ip52wGcZ!cSGp;p0e&)*p_ShFdn%`$uZx032 zkx~B<Ru0&zn*wG|7ocnkWFkLQDlti$IF8Kidvxlk;X2@Nk^w)$vQF^W8h6hV*WV8G zx||75T?Ef$ub2aDH7UTmlJENEHR@~Maen!@(b?;uyY8}%2R2;rV;dqreDI&9yECh^ zoMhhSx->==R&<cFtX`+%F!Y(ZZrUp4U%2q=MP`3j-UE{1dGAKbVX?zSn694(t-{?e zbzg8f?A`aeH(eaV;daG67q-YhrdYx9j{6IwzyvTKAtdogHPnpAJk@k78c-5%>>LNQ zf0p!<LhUa-n}|oWx!v(A`RerRZ+C<L1fH@mSqaqGzVe^ckZ+Zy7AhG6h?E*gyWB{9 zXZN1xiFbC|a*lgj0x>6Cg^@+4#Qx?JrS<m^Ru%9XHK_hsT6vZONo#rNau?=K;^-qX zCbU(@vos|k{^BJe)wfNQNpUVJ=W5R|4|*TvL~PtDVdYoBlpI6JU_@M~<DVujFz<r* zTNFw$A&Zl>{gFzl3xj%xW}5-HiL>slEZwefxDl1{x2}d!pSOp>z`>{%T(*t;?Z2*U z*oQ7g-qc<E-kXI+YZk&}a-2UZ4rvx{x4D{|&)Tq0P*f^zw~G9AUd4`bi~2kmLLTa$ zc?DnUK}(8lgQq&&JI>i2rHWDfa~;c(HMUL40k|b4A=^x9I+!dRF%%V^s^6HabKEg) z0%dlodZE$;kb1@9mo%xRqD<o(@^|f!H@Ad3T$~8=@+WgHE_>f?`ToKe@^?=7zVWHH zq|daB2D7NQ#XN3sUwT1xc~4P&+`2B-L*TA_LPWe@gkfD1+t>p|6!1?pRYak!^DsEm zJ{KLj5e6`Cp+>$~kh7?m^Nxa4%j{pPj9NXf-b*I={@eCmUHLssR5_*e62DX2tLJxX z;!&#;Xfh*`nxk{AYvYjY_`^wbm{}W2@;+26c80#YhwTVXu&J>x>?y2v*&;10ecYlV zw@PGwM~A(=c3QU(89AHWT`V_MW$5xn8CBRE4SB-oaHUG(K6Eu>Km)e-F#EafcCzo+ zm6+aJBa>39`Fp#h<CpVPE^<P!fW~=^p%o_bSUL#1dfGOC*R~kcmo(0=en&H)pq8Vg zWY5+e-!bx*ts7DORbu%+iYm_m$+}`?85&_A^lQet9GXv$AU{*QE;^^`<Z*9bcC?=X z`@Fi%6f02SSQ3vN+PDElMqBkFB5_NAw|V9nJ%8|z4?<%6hna2oRJ2Tlmz;xe=$YSF zevX}2dJB*^SR9lGt$>7!)dEl7vVmrUhIotPV`Vcj-7noU6&(bQ&2vX$jmR#60ka*| zfaH(fpI(~4!lXpyqX6v%1`ye~jpAF(udHxKr{Ui<I?C~@*nuo`+-!Rp@ednl;k!<~ zcfS%w+yKzQG<F2D!@9C*f6a2I#u&5J=H*TrdlIzGyjTD7yFQ4fwc*PdPAWq#BzZIE zt--5uhYQ>kA{`Qzt;WiQK-Z}Tc-#BE>~)h`4f=z+nRKK?(cg8_O1G~a^bu7Yi)HKn z&ku9g>Eo4I2me{u3X>xLHqRu=dWxp~+YO&%ddpn6&4odqtR^f7#Z?c81fvkNkx)5K ztL?WF-Ip-wLcY5SiK`R2Gy62kJrW1j^GfMo6@IAaGiNi3sg6-7kLQX|n=ejEi&CUy zF&&ByM0uFgt{0gXu>!HR$FmW6=wgjbbCvzc4%XQh5BVMirn}a#7}1-tS1=n8`CJE_ zvjOJ|zund88fmXo2htKuUMdDmta}vXX0HF0eKeDLFD_%L?0hrPn@Y)BG{je~Wq_%* zFHZ+br$VuV41KnFNB#%C`&{?&y8lY-bce^9LsHAYJ}kTNEO?ZDQ*7Zox0-^19`<T* z9|Mn$P~=C_xbR4Yj&w3eu}%sk6v%|I4>PhJsn=3mAXzMelv>~J4#YoM@7~arqmWC` z0JuL%@4%^G;<b9CeqvUOIxsFYxk{2jv<cL4oej|{Yc^cSj*y9BL`wpM{xik80(3X^ z4_0a-%38;=eVqD#i=CtVvFmUEEWL4&H>DRDQOprfy^ZqfCp}xNle1+x(9HjN5_*&$ z2`G)lO6!Mhy5%&n!kusX%|^#~YyYH=n@%s=9OZ1H=VvoY(a@ehy~oCB7aZ|?@<&;b zXB#B<M9nPa?3I;k_$pR6j+KiWC8Y%_bDx#|@peQ^I8fWM@?PL+)aSe4goa_L^nQSo zj|M4bLe4<r1@lMYIDY`N#n-)YXZiE80sJ5fVIJ;}Rr?mZ)^MQb^+q{cMP4*SY$2Li z+Fu5>87=22GKz%+&iJ7LQbyVfSXp|>E2}G^`0sq1pQy-$P?QGtZIbHz`<-5-v`S+L z^-JM2jDMsMTvbEOeVKceS=8G8>B_r19OkPc9Nz~fomf7|z#@>PQCRR(9FF?nXMaBp zJK?6NP1tti)q%i?aixbpLII!CTSr5*Bj2W#lC-P&J+V*D?ONxe|4zb_%~7x3gd2>f zC%tO8{~4s2+AMU@<dcqQ?BA2^;O)9G8qu{GR7FS35qd!wqr3qvPP5XHqI{G3wubSB z8riu*Lm@ZEYnD(>la6TK!$PW|d^)Q|MfWdq;cQ(=&tC(rOh(TVrAF(F0*6zB0eJOf zlKZe%_S$gJ(Fprfjn$jB_Sj6?qjt8R73ixUv!7A6b`4JMDA0s^FU3nd<ZLg|kKzsl zlu}C2gby%*Z#KVtYdonPWiiF9PM&9gD$g7HUh)FS_%5DQTBP%aU1i{5YthSzxeryU zn|GNX@x54adA7Gto;zV24h#$L#}~t-LK25LC(2IMifulyhr%1#%-$$*EDYthNw_sM zgt6^DV%|3=dM(JT3?;a}^J?jHjS`RtO>vtIvl+tv?}?EB8GG|zExzx64&lqxDi|7O zm(_39legbsKch+A)%BweWgxT~C7lO_-5{(O>~9*?HI>&23z5=*j>9{=XmgAtn^0Nc zO?hzmb6_CZF4QqV2=iDmBEyu2Ia>tj(G33FJ8&L{3>?=%H!#24t+JTlyRqfJJ9p)o zkEE5`)&5N~&&Mn%UT00ErA4gT?GR4q4yUI$%c*;hqih9az&apnC_?Ks5aN%BkBIKR z>%$B&zVL7wXTm~D>gALnj}Xe`JA5Rd+ulYjmfDdV`DojjjXOuojq3oLFDL5SL7p2v zDa2-7soxg7Vs;Nb)Y12fNCWe-myLJ<p4j{7bv%j#cbiGLIOICNqZ+rK`U><D$6}E; zbl3N*oJO+QF4#Ro0m_Vd#a-<w1GZ_9&wUt+RRH*<rlJig`Bkhp&m!0HDF#KOBR;h? zn(+J_7eD$V%ejE|!HUW@#RzxnCqn#v^H8hjilCY}IN5sX>8EaZF*N62-4j1oXHV$u zE!Rah*&g!Rp(f^Ybd|sViF#{M@#|}tQ-By@3L1UBJEB1Bc<pE6uyUe4PonO3#h7c~ z?}#P;p-&wiO1`QbQ%*&GEGD91d8>!+`_$+3mFU9_@?*mD@yXM#iWA=w-#KD`w$rKK z9Q#?YM!EQL_o@;vDpb`e^2s+8ge~kNO8is!<pqZTSCcl(!Zh8uBl7|(tf)`O%{vkJ z${zkVD0B1VoPTi_iDkwf`8}VMGhaQ<b(X(ibEbI*t8zEP<YHZ8+6Z^v3Pdy$=`yH& z*)!ihIL-X#4Whb^c^9Z{Y_rX(d0cc{p5z{p85B{(+x`~K!yBc6xo#kA9EdF!R=Bh* zmY%fv#eSP%61o63%CIjvA8?`c;9lF4Q3`*T(d6)Q(VFY;<G?HmanA=T*R5|uS<?C` zLK2>yPSncisvnYqaP$ho4{Es%)(|Xk<5I>ana)p379UiSPLoiK_DbyeaAJ8W+-Y-Q zQk;hZ@;+nZq<C!1`sNy&n9fu1E4HiEbkipPy2nxeOhk&KUL=14_@6|+)pwql-YD@J z&zSimE7V(aA%Afn1e>o?eN#HHzoK300_GWyo2Lp)xAxq2R^WcfCxtR0FD>{4`n%nF z$+=Ny&MLl<`)W1#>H7N%)%ttzY=DC<H*#<QiAJ%+_tMOL{G{~l^c+FzHcBB&yO#%U zKayQLkLi^M-L|lMhIa>z8!17x>R;x|*nQ`HEK*Zq6&vJwqyL2}Z$xdzhnsrLk)IVu z3sT#dc28*0+r^$wXtp&>Y}s+zDc5Ksp>?%9>ep^kjb)5q<<vGy`ID1OX2g}<QIpr8 zP_o|2OZ{_2iLNvw+>VZNQ?61mx;ckb0XCDV+;sHTdZ%0g6L-ykS`F=@vAg~XQJ0<t z{sQ1jkcS1etB^bbQ!BJ=uBKOj6;}d|>BCP4jabKmOH+acAEa!ml@Q4GCu&pOuOyBq zwSMde=ib?Pqry=KK=}Oq^9XD#n#~(UqvP%PX0X3-Ogz|p!$Sh)R?j*0Q;9`r2gy?h zdHjQ6tgq1Z53++0<79lG*Pu^juQWUSf{h}iCK#^){&W0TWbC|f?|&OjH3JOZV%JS_ z_+CU8rWyH1ktt8inX{+E?_~>zWe1N)+<=ytm}@&SVypEZ5L$bK9S$DEw{JK3)ybc0 zzF24H<+rW!iO|m<yF=HkRZ(SXCnfzGK8m_nEzA-}d;#bvCTI)V)Mb`2UV+uv*B{o{ zH#6%Vu1AcLH_*Ng-L)cYRC&7=Q@bvwBwSxreBJ9(#L`URpjPNNQL_p6o{W#;w#uKj zajTnVWV%g`ht|#Dk0xbZ4?9%1W41-e1wQQ0@2?!8EyBXTM@<xf|9tCoxK`GllQoN% z^pKJ+c`ab|SqPp6&6&kNk=XG(e6WFvn$}sDa%y||Vi|`3-bZC~&HnVtb72yt?wY8Y zFe)7)$vZV4{@O^Ph<K<(_tI<r!e&gwx_Wb@AJ||@$8`<-UFr&`h@#jMU5iFOeE0=X zI<|&NmXygff?1f9r@;5eZ_7^ow$+W83zhgqQ{vH<of#3Vk}be>F_ru=4PP9G$j`~J z+KC<}HOKf&Tk^>NX%-{99NfEOQf~Pze6=XpjvR&vE@qSZ@iwiM_NaEuW<<U>jamSA z;FCtkG@NB^TKe=yEQf{FU|}FaH975);n`Ez?uF(D+M;LcM7Y%Ilj<>w$G4uB%l|8^ z=<i(PYMiw6c1iVBy*=yfzuj^3%rleGDYRC&`-K-ujKAE#?h&E*J?!X>Us|EMeO-dT z1jjD@f{IpDIDMu<n|;+pakpK{O1zYZ=xZ@iJ*rW=h`fD`jndI%{79;4W~P<4O_F)q zM~gJr$%EV%qkldWqVyYdnmlWm$ya=*@kU_$LREW$HyWXC&0^;+cNljVu}|4;=eXyg z8htx(tKWUtU#TTy#>hJ5;k&K!-8J~GOId$}T25_wrHiGHkB?61$qP@kDahCas4$L) zdN|RTQ2qgCuQV%iH%z^p_@dg<F9xu+9~DcjOumEYX=-ojBlQFh;xquS#3%sG)uZ|V zNJ&Y0XUp06zPK=y)uzF`<ZFO~I;K!;Y4kHlG(YE{rnHvdyx1F!M4Sv3_2S>4pNg$E zGc5NJx+X?6N=aoha;ElswXbSt?>Qb}gSxl8;m&tynXE}bgaJx4&BriQ)`@zi002mJ z_$31Rv-}`2;h>!jL=CA0Zk92-E336QbDa)AfAY$ZmnUsznvguEAh~n%d=#2ja_85S zLp5rY30h+6$q*SAnaI??D`U?!bU?%L2=B%3=a5250-$N6Qt)kJcQdl1WZDR0n*GMA zRXTz#6fuESpevxVDed6EO$Q_3wR18mjE+D3Bd&P9H<larwOP^|ZHrfi&mrI<6p0dh z<oRwS*VdpZ>D_mrsNj~o_d>ozz&e>7TZ%%}`9scsx(J&d?__g|e#bV{DsJwoZ;_(K zC7~A10f$5<B$ufH;#ZR^W4-!*^oOSLb<6PpqrhUfoiAdojYs5ch&u9_L(faA3eRg) zd{uj2ULKshLVlwrFCGdjD)q&aVAh@W_5f03!?~0;`BN^fP>CeC-iS&CJ(yxorzAKZ zvkEYON}~;%Ug7$2S8k#*jexP75b)Izihgve>)0ml9+*1z(Csy3{aIf*8gB&O4dUyE z?aTM04;m#W9nMxMl^xn{gqk+acB|`L{JB7Ttn8nN?Wn&L{!_Gpw7cUKN3+d?6WUz8 zFoL&AmCSP1+2fU}aZ;T!za7_hiE*Dt^E47n5rlCo-=nTLA;7_03w^-LMp}%fXhKR# zhO#~fS4I%Tk67rb#_@`!IOWs~6z<?_m@;F)s?iYx7flFzHQW&lI5Jq94~%Npm+Dr- z`T75-LpM0%Hc3w6^WK$=lXI=QJOKO7w`P4|gP*PxG*ju_O!J9XnK)ZRX{o<^V&)za ze`Kuk*-2vt9wSxKdj#x*MwrHOl5J??Yxbso6Gk`s)4ccC8qp0-CnNw)M~{p)uP<|K zyN_J~YLx{{>r|_Sv4iaA)goWegR3J~s%^ipiArPMac#6EuE&tvW8E)Bxi!KVx_1)& z^6^?=uidi|Qh!-{5kTq0s^$aFN`N*M>bbj%t@&)$;yAw`Se#Ym(7km$P-H4`@2h<! zD;m1){uD2NR<SYwaiWikQ+9;X)L-t91)=|GLsRfwtMffkmL7{2odf<!@(ZHtds8ay zyhQNHF}F~N>3uOZ8*GPbv&03kiN{A^n<DfePeh}RuBHl4^Men9)DA2AF)fzgEbz<g z|A2eGM1cM*?3D5xQYWx{gJfL;Hv1RJAgvk{DlR{W#sI$1))>35B|<Z%m~<(mJ3PnW zhSdT*@CPdrPx0?S5r^@k0t>A%nvJs%dx+`9e1!q%V&8Y{XQ@f+t!A%(5!Rl!rDH!E z1M~u1nEu@|*^bwTY~8UYe39ix({OoX!`V+^LU!}+I1Ee8(22ZLHhVYIo_${0M=K9< z`@#S|aYKEPvS)~aZGyKyZ(`MH(le_jat9~7BZ^-VpUIzPX4s?}eo#8e@2}t8PM3wR zX&6V0{_M##oWd%B9NkkEaSNM0$JliKgx2kX&z>y76k-%qC@iLU8bj(nNb#g}Sq&>@ z#!xSY1j1)d?{9-at8o#lU@9CLysT9zbu0`yVi57H$5Zn(iE7J$LhCSj!+0_b(BQSa z0Xn^?xb(JhSQOU0v8kn*Gd=+v$JXCGQgxm^+uVIF)lxM`1I&SX_TDk5l8F*vlCy?! zy+N0&gR1)L0Y^HOO0x?}q38GBM6gVBE#q@&@fsiwN}QAPt-78l?mwV97u<TGBVyn9 za{XX!h!nb!l47oAt{<PET_rz_sFIUX)=x|9`BdSwN45V2<F7z-g5<7NDCr9!MoF0q zFF#+~M6OE|7)lx{AFBwsut`@|AJJ=Vft6>RcEwT86caktwxg(KR*n<Re~~`6(8Hy$ z{_}Pcc)8p-ZDfqTZ^`q+aMG~Y0U~T!@fUk=c46#Nt4V9_KIi$h_U=($Q3%W&WCKCY zzUA6tgLsj#jEWu^JaOe5FzAh2jrriszTu{+s1Kh9kA9_II#=qU++<T2m7gYz?$uT} zHXH;fpZbcV$sf8^GXSi)J?}QudLBMJUKWapA-)FFzn5A5&ElE9)?KSD)x&eTej(=O zbW5FWm?zR=I=?rzC^35;F^J5$3o0;dd;H0~=+k3m4#d<a^4`<Emb@@+_#&<7*<4ZM z^yfu&t&ks8RkheaGNFX-sHome#YCYc;yL06Wt4#o<T2+meS~u4$1Uf}5x8m!mPt}S zD(wS?C>R-e3mPBZ?cl@7qx1v#2B$p{Y$U!T^O^ZrVdzWPMsKf#V}r}GM#g0VsYF)E zaNs$q_OA}*v`f7sz{qEHq~2~T5YycvHnh^OxBekt)(h`O<t1U7X6@-~%Vscy*j=PB zO?lC(<Ny`s$v;p}vUQ{C&p4jAcBEc`bUQh#T4^}0BfX&;QAWl^A>beADwnEBY#}Z* zu5e*#YQ|plOa6osyQ@D<k3p*5^1x9<mq5zT_hZ5<v6J0Oj<%Y(+>B<-O@+osoYMEZ z&HR-hBa1IK-e*9(xE8xH3_Z8P=Tpg}l1K!#20+nue*E&_a>h{hoG$g+nlk^U<$Q<N zXe!_yhU<9M%2!BlnrN5b52E73{sV>8i0<&^?&jz;9@Iuv@R7=K(a=)`dH98R*j%<! z{m-*cpM7iF9jks-&rOw#S?-Tpp1*`{Oqsdvc24y5z2;32D%X_i+Btd})~MHPsNwq& zzA`nG4}hOcbP!}~e%pTT@e+^e{p3Pn$s0NA^XW1uax<+qpBX3Q^z22$O9`dH;I~ch zYkHO}@ArLfYkJ=HUCw+V>c$^ftWtMZI-3sJXWx4N+VPUHgg%g==lnstP`~{MYqyhb zB39%&U-`Fw11)yh11ugxqpV;2Zn>N#enUb=k=!k9^dyai%B^eQNeop=9rGU{pH~C= z?aht0a@%|hT8H-o{dr@WJ;24JF$b|xtTziZHkKd5LsK40_wALB3pZ>m_kl4GFM9-H zn?r}2)nDaD(73?xI0L^x>-oz`?GQ~c!d?0SEbRr^E+R!1MmWaUr>2vDl_G=w3?Jz3 zU;xubRT@K0qSNoDCzfHjt|dQXN8&)Uag?$Ve_TE@0we}>*o(a|Sv+2U+6LdeegBh9 z!=ExQ+(mlOcb1gP!xU}J(xDQ^65-U}d+TAKVuxR#W=e=n?3GzbG5F3Ov`^IR3HJD` zfxZ@4GR*am_Px&X4*a#;gDsA-MKd>p%}Urcodo&n>wFYl)({BLSaJW9R!TI(r`BZB zP($AG_DH9qMD^53v!ch$QM7$5iFUcM<<N@obP%&nf!R-8e|a}&n8&^?byqPU#kB7I zq+$KR@_GsYR#Dpk(@}7&X$D&^>^RWA;c7fW4sJGplYpou?NHs|jW6d+^z-OOlW^Mv z#GRUN`*VAXzA>FRBew2@QLV<E;)#WTvAW_3%k}-9wsf)>^)0yl!m1)y4{p!GlO@Kd z$Wc-uFTRkdve5Ii>`=*P7IwU;Qv%z08=$0YUZ~iBqa>gvOC0dR8E}imy|7suQdx6L z1M7Hsz#g(d{N$$Saiw&^CEb_fpU5NA|4}+5vcNT#lx}yi0lH+6QkL&E_1X}w`(4v= z`{bq3b%e`jN|!Two9fApQK%Gaico*4i4rkmjEPiqJp|bUh_zL)PqozcUumq)o7vi& zW5n<u-Nlukm@EBUa;<%ke($zG`V-!M6J0ViIQTbIk1{pTIp5TG0Pps@7g{~EdPFf3 zMt&W>r_%rwUJ|NlYS&&~>a0wXm(||B&a>@n>vejaA(Ex$mu;2paWp@+cX;PmtPs}l zHZuEWBuo5_#prI9w2hRp6#ZZYuNBb4$+ahS(^?Yv=k(1O?d$vB0rvzS&t-r=C)Ino zy7~vPGJfHP{JQVe)5P$ubj)EfVUu)Z9hz7Rk{qOoLif6A0_F$AAv3wtK$!ddVfAK< zokuBI)DJbT^wf_=^-SMi@=_Y$Pt0Wvg!S(S)+63zbh|-z?t2;EarI}KK8NIw_=5v| z53FvE!?M1*#)M>F>njxlY>$wAVunudd6Cb)xQ5Y$4>(i@a!J(QG_C5Ek)8vXRs<<r zKyEu)k#nZ7*X>ENacS;2*&hDx{k@U+uQsTic~NsPdp_3KX&b@ob3QDKYN+j<b*4Y= zyr#{wQ%QAM!dntQky2G0p&^t2fVslw7ZR$+;!Uk3*SiN5{#$)Mhe;;&7Jl9SZ)o1+ zwTs>BmvfJm^gm|!Ea*TTY~n<UODaqoxlHvCUz(+9)oX!LT`NLy$Xz%tq%fx)88Vsu z+>7fHmtyKsG#26eUHadjC1t4pr$yLvtl3eeeJpa)QMTveMEUp;VJWP%Tw{!}N?|94 zn)BKM#~{n7b=7G^8ooQFo3bAwY;u9HvOA2^v?I1m5c)>+^TW7qy@pS^i*d#A3FRs3 zfpI6WdvQ)91MuZVrL9yHjo$Y7yK9%b5#32rIT#CnwYrLmDm~+g5^4PtjJ)n=j3G)_ z@J+8~Bo{y9?f2|CFs73ybxHkCRN1@xS$~YJBr0E_iH4x{L6cJxzmo~)QlTX0x|EWV z5~wh|cR3q)_qz-6V2UO)6>C*_^4K+eS%syzLk3b5()g^d3R^HX8VG+Un9{38BB|U+ zQ!VHne`H8h!$ALQ!$Vf0_70=Kxkuw<>R*B)IbJNT2yv#BvfMZN+QIc)5Rqz+RhQh$ z+w&}x6Ek3E%jkTebN82rvDTO9Yo5zphrn_+U@Z<v{X2q0t-9ik@^vQJy?d6j6%>*! z=aVc!qJpv9Hvz&dz6pmjJDayl0O2M@!GqgSV|-d~-01RpRpqv-Zj--Fwu~5BTF@YW zhs>e_4visf|E`Tb3j`?JlBad_sZln<YTnNVeq6VMN_8>q<3f^Jj(ZyH8$P`9-RzXD zOWK#T{iQ=HXu$86OE~pZvf@uq>7-8c+Cq193jcGvw?VqyyV$SKAg)r3Ys1gP2*vrP zbB+7~+dpq!zvqeYqgH-CVvCYLJY9Z`Y9L)%qxKeBTH^9cL_{0Qka~5aYlKw3&Y_X6 zhD9H%?Z*9qGa_xj)~r6i>Y~$LTjSc>yGOmQEZk9z%n2<P$AtS)rhak^d};?^Qg3SB zL7T}MSU!7<mfj(1R&sC_GHd`4`Be{HAB?jq6)kNTx33}{L01|RJ-0UxcInk=6umd+ z{D?)k!E}4682^y0HL9M97yHf=9!mD-Q5K+I!xdhU$KrN?JA$KD&cU-Ng;m1u-iX79 zZma$b-}NqBHvqD|DLj~QEnidX4TqfD&VYYV6uXx-6iSF!0741FD{}O~6KF{my~k~g zkKF?+Ebp<w`Q(OoIeKX4p22;rymr^y6G~H+iJPP;tq@uipv;w#`BpfhzlQ`P&h1We zrpP-Tmymer7{6|pv1<X&J$tMR&uc^-=&nF`Okf~YJ6?t;e^u`5dGwRV&Xy8Qvo#bu z@<5b6W4~ys*M8?nH<PI?-oBK;G5gH#oz-&WmaO;Ld4+mZBkigB4&Ts80#r7{l{SgI zTzQp#J14a1aP%ONxW-!;W~ZA;UA4$?g*4nvnSzWOolXO)T=_Dl4Gm?2W=$Ua(%i!# zJ9p26wv!bRM>%>FkXm^ILG1-SInmVr$J1N*H5s<={|X8sB_e_n6HzBpB3(m55RnuC zX&BuN0vjUIB_bsyA{}GI=#U!Su`#+EMvSo$zdgUt^L+n--LKc~^S-Y0I<Mn6-p@{D zJ}KO_SWay;_ppDwv^z)%x9?2mMtK?xWON-)2szl8K<u|iH<{}PrjtC(sn_7rGJ&33 zBre{|&-hqM)iHm%C5=1<b~o;bKT4^9h~ty}sax>#K^1LBY;pMkX38MVfs}yOe7Q53 zn=m9Ic3<E>Z(yZwSqOZD-1{Z%K15mM@6rU+<JI`eVp=T|Cj1SMtvfGN%PhqjjqMvu ze_q$Fd`)C&pGQ-w`Ae$#?Bt-e({5W&sRK;9sVQJB*SUcXhQ>CB{+FM$?OAV}6!#bx zcZnOSU_{cv_d&$FhQ{+2b?L+>GNgqo)5ffwDVd*5YPpW1czjAdL*ium%KdPsuEpTf zyfh{_%ENB(0nhzsS+(nUfs5l{pNsYe`T<$(=l3HCGjUl8o$LJa@0iWMIX@b5DVW*l zyAwdIS3o6|i;Uf33@Oidv!s06K^Fb%vlvGdG}Os)zoapMa4yzzKJIaaTd7l>-~6=S z_|J!(eOk(A$VT=!=<0%UzlF%$)oXQ51%{~GuRVf5Rgr%HQ+Cs1^$Z@(aC+Ly95rp= zOV0o>Qt?~nDQ8O|v!t~5fdO{9ZK==&vW{sv*(!!zc6P0;SrG|vofm4*gApY3B3_x} zl1NF<Rxj4ed>ec6HJYzaWkr;5+kpN!SKzDrJe146<l=0m3)?YS60sG(f{jWMW%2R% z@Yp=&kv$)!p1)daX>q^oPr!9PgK}aoxoV`(hZ(a7`96*N7lFl^&l4YsUbeBCb&|-? zr#JsmF>_%wP<58QGLxy^!l2~sY#xrsG>+_l!2cSLr802S)vEa>gsrTrK!GMg8}k+> zEvn1(%A7886<*koi6_}ju|aVcTPy#9Ym~J(VZ0j`r7!J8Zoi#WyxUV+sEkjKm!<-s zP@wQ6th#&V9lZ<bNBwFLtIb}Lr~5R29eR*>RqKZBr^X2;1cR-INEC4BHlyrO9R1AI zzpU7I6BYPuzIg6IV8VB@9fOXPdkGe#^HMVF{@a_5{lx3#U2ETOJSiYnPuY*x@MnHr zJx-Rry7~m!?sV~dSWWBKzmP1l&a*tG3?g`3?ffUms$t@c9Qmp)z{EJtL4k|AtLr{B zqX@aPso`G1eC$oIf+D4N^f&d#M0W^T*8^R{CO`AVGXcoubd)KvX?pZ*DgpW4&T*}y zJxlVqd+5BYe;06WsZ$cW*tk(`&edFW9ic<V;<3EVHR${02gcAcJX#s<q~rKv9U(tw z=j7sK1l`<>61cp)Du-@%x}4PG84oQ4+I;>Ge`HJ<ILpA#f*yh%x*_0|?fj;O*1PJ- zJ+j^uWK;(;%o<{cb>S0!uJF{-erseNhZ(wH)LxX?V1Q5|?T4otTJ~Wlo?R_rPcM#$ zaeIL@gPwnMYoc1}J6e<rG24|U8pmfTE|l)71Y6}5<4qV*I`&Y*xjGXWQB!2+Z)bCy z?FCnw6{}G(<ShRAF7cvLNEun2r~u0ZU5T8BaHmLm^>*WSQ|opU0KQi)m&c58m&=a) zhC7}Ocn@@seo>rA{YoaNwC}s&vNMblA;TTq?7UVxWSHf0mNJ!4wdyy_Ej8W=IcBxA zwy`<wAKGtnvHQF^-n+H+;QO}EY-^q4S`Z}%zEcCb_2KH|A9)zZH6k1TOP;`yx1a*! zm^YcV8V;H`B|t!;h9ls#lZE69L5qzkIp=~nfqa9iE01{MVqyk%(Eh?C2C1ne<WMTZ zyZBjt2x&$+d_fOcNw``KjtgAcZ&zHEnpIcoaGTiaRwa<LB^ZF4xR1nA80!E<=I<p% zEj}T1lDDR|+sdpx82wL&H1=k%nkQ7(1NAZbO*E2_{?-%kO*|LiqJjQ=T;MV*562-c zxIycFp&mxGh_(#)NtLnDaJ+Z<@`01Vv(wp0u+XY;+{{x(L~cZ3#MXH>=2cxml{ao6 z-+wpHt-qhG;Ub<9aD@&GI3CfsxZMwKp0cwuopvqrZBeyy%R<cd!atu<a$pQ7>c%Wm z)aGjbnmk1&g#`b3<zqIF4+7J>q(d$!OLt?Q5**~t+`YCIxUvZTK<L`kmCI_O3?=0S zv~1ofiX|dN*SN}hbmm0gDaE9^s*Xj3LR1{5XiEC_R2eHjB+4l7ZTbA#-Q{s<x<+&g zFr7Vy6FFpY@up`sN2kyoo5d9FV;Llk3tqvck=}3)NQ->8wuO1cH1xfv6qaRyBw337 z>e?5d{8@GHwD?RI&W0DZ)0Y_gU2Zqw2G_1-1kDB@)$o-zB+KUwXGy$_Xq{2)E-5W0 zjK06}<b-c>b3vs-_|^^Sg(X^(s#T8%x-S$<UV@rz_BtRfP)s|3C<fdMJiZbXkqTs< z4gy^rM6_qkl2QfOm^sQN{(X2f5kND>l{EMHd49(Tu2%`;$9AV({mT(K^8{XR7LFkq z8rPc{YXT&DS8r>_?A!JMQZOD<7d7lx+>IN1-V1+6<J$_dR(`vm&Tm||q94c%^W}v^ zl(HVbtjwF1^6X`uHyU#kM(rFQ2TASK9x?i_pB{p5_AGpq&(>_Zx+DhLSy&vt<mWY8 zmW1;BhV-}3yFX5o0rXC8!UDph7+8N_HoAn85b1f3oor`OlDndPOt%>+<L2Dw;~9OR zY``1B>CbzaPdOxUmkL1VD{+%yFDdr+sSpQKng=ISZg{m9FDNEqzYg_0QoGe0@6wj< za@TH*6;6?6WQz)6dwvVc6Pq&1e<J}xo$g+Q$<sjm{?B5@%7E+gMh=~?W5>^j8~s!a zAO&g@3T)A`j&z~%-PfVBx(OtkW)IqM&u>1H@l={$gzeHfZP_Q#axJL=09dflXEvGN zZLF}9xPDZJ>#Knk64z~KOgM=zY#vi$g?>>sYVP|OjC5o#BiHuNT5X~j$B2I;TQGSq z1*=a<F$4sEEx0}dGv2iyZ?P5N3YOJ!$f%Z$G~N)YfUT2tH5NAi%s;btWFMb*n)sx{ zo|P);w@(Dp&0@<nZ&zq#3w!Nc#_682w*WYN9lxx9TR<Lh+F|)TV{RwI`T|ojwlIb_ z2=>hZeqhywsE!L0bN9<KMvofkii=Vw)~;}x>A%xoG4}IiS?CjczdyYsohN3d5Zf~I z!y)ALBX)7BjyJbS**)MyIK1wHxGxbvylDBn9UONR=dUqyWSSxFe!Q$~ldm3aRRP}G zR@oR?l^$LA)(g4OEB4Q$Y5V<qLUv}sK!AMqPV~$Bp;_&N(LC3syxPLoPrnN!2&}xI zT(jQ)!X5dIfy9k)3vjkS+*t8F(WJlfi|iUD5n2Y#H5}w^jS;2t=!GOPyX`cEAWe6P z=|io%OnnrxxO=Ndb%hZ<7m4paWw9;4@vSz<D2`Rz307TvY~tugeH!Evc3L|u$tY56 zpsYeES_Toacp)?GE*D)%SG9XYKVwPV**l&IA)b7_|JAh0@BttTzzUe3YNw{*R`$(W z%YmTq<zB*cF+qPjRY>keWqB|Q){-N~c@!Bs1b9hV*K<Z*lUTIu|GM{|z${<;8$4?K z_`10D;W_+?+aBPb4B}jc)>};hSq_(bkhl%sb%>#@BO|)@TT%u)7HX$vp!_$~v+t}d zyndlUvR3K>*Ur+^R%TEl&y8LsdZ3yQDRy3nE*KsDz(zMxeaj!r-|-A)y+js1FCtxI z=`{<7&X2VH=fP@&?7WL)kJxmV+<?o^ZFyU}L+-GLVDy{sWrrCi&n4A$-QFnn(@~$Z zo#*Il7PqcIkCFyAi85i%<Ppza#Hi_5)6XXHsP8ekXv$LtMP^5Q{Ikz8c1{t>r#}++ zmfI1a*t5g;y<jM;UGEqh@GPO{O=labA1>vgRoLd$@IN|XUNEq>Q$BMyZNA-Lmku*i z_HX+$$?UO12j6%E0x`V_8O4u}|EmjDmi64p47)_{M4VojPF0N6xWEIx<)dAN9{S#W zqfsQ@A+fq-#N$f?(_$O2d;CqQPCAoY=vefXGaY}?;aLIA<TM*H*TTH<j#ZR+pwjzP z<ly>1h^Q?O7VRbxqZ$yfVNfn0nyyF}4QvQ6q|A*5Bl|2XB#cTJ?q0vN(B@C>v6EUQ zrzO5X7%ND}GUE#X`{X!_uV1@zB&u6F2GjDUAXV|kA!BscF}%{>U%0~gp0cIq8}TQH zVHzdNngp-O=$^zUA!G+r#x+i~GAT|tQP^E^ewk!Bwt$k>r>BZ^{Eb>2LBRVdFpFos z%H)&Grg(*iu`%@@P5&&bD$0twZiBzgRZVpVc&i!Fu|~=$DegRZ{A{GP(Xui`zFDX2 z9Tg>ADldn?1Mxoxm}rSA3beM>4ZVT6hpVC@2uC}KctyJU15U%XP_E1J?=g{y@A>nY z2Rpe6HG8d(Zg%;7H+a@5UPKiU(O-N_#rnNild5Sncay0@9lXt*v-RY$*z;FfoXKL$ zKs@$`K#~Xg{dHzv@mfx|4L0nm(4XaD!ISn-a9n0i7w&#MMDnWs>^vG7F=MddTic1G z;&)t)WD0OdDo3&ZzqLa;J19!od!^L`QEdz!(4{tkNy8k2TJIeA-klee>TY%Wn3;wN zbn&_xiEErI-1%(JmjLkqwj=yMkq}OM0{i6M+({dKj73kdopm7d%3)}i;BIUexM1xY zp0<y&qYf*pi0t9C#74e|YPqpeHfNj*3?t)`_!G0VJgEHD{A_emiI}&=7g9A~Ii4s- z^PZ_c+3l14BoI<3%iMulzR|&~a-`AmxOq^T+fAY)Yr6gm;}tLeT(>z5-V!VM0S6!9 z>Q2?O*xnFy0fdZCvL@h<Se_^RU0p)tMDr=W*E|4lt0pDxF1nGkA2UA=R)mb|5`78$ zsV$&?<>zcXc`WT#FB4Uauy=m)%sz@5#F-l7$@P@oCt_{^#}d0HzsPo#Z{tLqsf}5a zY1~#-JKARzGbjxJ^B#^IW{7W-;IPk2zI!FYreuZ7evuVGzf9H5=c9wv6QsOLZ#GQQ zm-+9o(@BI!^vB%@f=u(w{R_OlP2{c?C2I~tsuCJgyP~bMTu{r_M;Yj@=Ix_K`sDs| zr9D7tlJu_gF-BIlPghLz%y1-zx%2gcWa|;TbkZNAP^NdQwlRqnvNMBL(DEcJ0p~ST zu2O6@;XzVxrS&>fN{sZ#JB6$OiFjrOs?k4mJ#UxJcoWkDU(*DBZzp4ZuHC1ruOyr$ zB!<fWxPO#g>+#*E!uMcv7Fz~j=dv;#J9Nz`8AGTZjrj&hOkRFS`z8bbC<!f*XKb0Z zCZml0{^_A#K%7oXa24{q3n1EPVSnO!14qNwKQ_F6#T4+a(2wXa%}@1nP2y&FsV!C+ zXn#z%xHu5ycd0t?K48Und8S~-5U?;x8?%jO4jIeB|29DnUra3=!Om3^VfUp>z6v)b z4yCoXl~+0_RnhPo``w(#MM>z$uY4+aRi0s9(xmOKZQPdGr8%r$R@*Vv`h(T2u(UFc zy@(~_zZ#*m+nI}2m7hd)xk=dK7l!&Kj4-Vp#--N_^{oOe*1@3Sdt6C;KT(P5nKGm( zn|XtQ3Nh~r$D9On<Fl!;Y@p-{+dH=GWAQ`?BzAR}^NG^K^RK+-+pd4Twbg|7?_;J| z3_pjy`qL!%fs5eU+V$C-_8^7Z?}pRP1$*d}$*OjY*-qBX3%owz?_Sgsl1HcWyG!)| zzs2Y@Eg-IiS(z>8St|#|*Wvn(_-(Gd!-QtsVVJ~261^xsg>72zOMf}#j<2XQgx71c zkav($8=WsQT&Ib*n05y}gX>6x0dN%~H;AnvkM3gxNjvx2NTk@h-HIfb-JS;W2bb~C zJzd=Xvh5TeH+mGHIGCoS^W&GsR@I!+_6OWMLZJaZDK?SDRID&_!}mYvP35XgLl0Si zHywKvj=|ymg}9E!j<{{{&Z_Qm`9wi;)6?M;>AhPZwyXff|LSv`U*N;?<T)+;^YZaS zL8hPd*P<l4qO2deGPaV0q`o@UI%ak95yrNwXl7=i9T*IUM*GE9Q%GFW1)l7&UJ2f^ z`OvOjpd`My1pJ-O5bIO^Q8Wh?`$P6R_Q5Z5?8<A?{40L@(MxWS5}n<8u~eqRsT50S z5UAlK%H#Hr%gpeN<cfKdyJz9AyQ+ltyt5pK18v`@rX_)es$v-|eB+^F^{^@0(%A`V zmecuxwqB{Nbo`FDP(I;v;^egfX!>*SG$GD)Y-bzU0Met)x`qX085AwnGhDmmj~$E0 zro%&5xg<MEK8ccTRg*l@tbHIR4ad3H%18=Dv3sdtF~sd<@k-Ca=a^aiBeS8?C}K|} z+y&|3^zn+~zr*y}!ef8PrC?zln)|X(+fYhMY+Hoq&f70hU(fZ-7oHd2=h7{UhS&W1 zj8jhb+lh)I_ilawmlH+acI`@ds{H3jF~0ahxp@C;$2F(F8NG`#++H2az|acL@u^y~ z>!a#Ro-}>Ri;;1|Y*g&%EfBm0(s*erb;G&Xg0QpMIq9qkYQQ}`<2Cg+&CqWiN3Of< zH`L>&a8ELIa+jp6Lnro&nYMF~*Gi{iH>0vI*aW{DpM6?3cl#)9xGs-&0HE&~XdI55 z%XhV;_QJwqBDo0#;VN5HFG6QVtyg}qG=Ebx4z~&VIw`MJeYQd&on<4ZBno==w-eVx zyMyO;4YYHq(kkE4;d^ZI=S6H;PolzB?Oe#Q$5!F{X}brzTvc&2BiLWRixG2E&yGJ{ z+DHA)I%Xn)$eSpL?(aS9Yct<En);{x5py8pz0eG2FHO*?`CoPfsqkXc-W7J|Ju7l- z(6y;nQf*v*7NGOuK=kXn@{+?%f@6_^MJHU)yC~kqw06?Q)WmYfh^x)C+U$){>!P<{ zm%pfHu15K{47ZhsenCgwN#3u%Aym#MjHee=X3M@q`2(u4Y*n;i9jV@MP|<z=y>t(% zf-{wgF$8O?36b1R<mn-g>}K)78O!B@!jU!&z^Z-MB4%q*SM^`$^q6>iIT%$P^RTa5 zAnj{c`SJtsU4>4qzh`L4j$uPLFGokazZ+p|KMf=GT&65fj4RBs+(zmUl`(g!X~I(N zFi!Zsu<3=Qz`x`no@DF~>_09}E->}S2K#XhG%JC@t*c_mjhB6CoUtl%`}g{2@caFm zwhGma&=_v2jItL&oN6)LxXyxk$`Lz%Qqop3Od#{{sUe*+Er4V8r<P&eN3Vh|!KIzd z|F=Mv4ZT;_LGO$|F*L!L%{uGdA`kKj=S_dMTJhli>QPBNPesB>IK;`WwHZEcqxb9g zz^Xn6or>Sxzp<K4;ouCjPQM6g!4FU7sO03BB5Vi@KS@CfLC`@Xg_rJq(%x+C6fU;L zvD4|79GDws?c1&>jGGgyjmaDOUrh9Jtn)nrrI<36jwEujfgVzT9Db8Au(dqFklZS3 zi@ZkHDAH*NIcg&Ea6Up6cK$Y}?oP%~7`wvKky|hOB`J~Oa5e_SlxjMZYvU;VD0Y8v zWk^7{@I)@Q0}>5E)t(2CZbUQU9$YE}_N+xM{@^kwJGaUa44J`}v9&T|p6b2gTX!?F z>=bcy)Ql_LuO1ei)7Q=i%T1M|V>m=ZGdJ!{cU6dWiMJ>!Ur5-28(c7twY%1D*7$-k zi;(O`k|w~|LP(pQv*4@gC=;4^lAEbwKaQ%P8QB#cMwTo<2~eA{nEJ2gdqx<~%xLq< z(LEqqO(VLpI)?93J#E`R;`WU)`jd=z_zN*Dexx5dy!4oQXCfmU;$hdCX$*GEP7K+O z<&DB)HznF%sUz;Feo>fyGPeu~kKyEU(<<|vL)}~DQ903)2$y;FBaX$*(O={~5aSB& zR8E(8$$!eAz^s#HkWbCy{HtZMFd#F%P(;6(zd&~X10XAF9DRz3`Fh59a_3lo6}M7z z@!TjsfbS~aojk>GJvk<}$&ae5VmbfcZiK7_vV7UDX^@@^t#>l~(D)?w-n=}?!v9dO z$H+Z*3=Ggt)(!sN&KHsVYfQfL4vE7K|B5jnmAbM*9Z$0o`mO)0(m(TJ3#@Nh3CTL5 zM-SJ`JC?V2d_v*5Gh8VCBHv?Y^xq`)27|N0#ftv&ribBiLbFl+LwVwlZ!)uwlVp%j z6;|4QMCR8R-Ts}mTZ}YY9o_%>zY3;k=6G`!uBL<3FVtC}7V}+vZ!$?1<U?cB`tMCJ z$;^M-)d*2}(>t4;6qfL6XVa@|Zl<TaI#zr)(kv%d8yqFb`wd!EDZoU{fc5oxQXtR? z%-<1Z{tC=)f9Y<B+w=+&JfEKceZoaFFE^{)9I#8kyQ9L>8@H=fPk<-W-k#~<a`s+J z=wxFd-Z=8iq2=UyjT^*T)gx9>gvth_?)4r)3QxN(#B!OtN+rW4q$AotA4ZzbpG(G4 zMQ%%2)l}EIPWKw|&z7U8n)b!(OhN~i%L7bgj=dkGDOe$(IvHxe)ECp<9!wNzE!Dc7 zX`u@U=HC1P1jT^)8_`PtZ4}kWTb_8A7+HKsSPp1J)OEJ}77x&Vap3%iq?Xl60%VCK z*}x{;cY01}{LO{h`GsGVOb#3@3sc5$lr_cyjRqNow&nZng7t5^NDtX%RQP;*5Gnj_ zCxKphSck}P=kiq~Q=qM}S=O(4gGM=wj(;TB)G0uOQwK;m*8P3}lwg#koVMPO{_dUd zKo>aGH)9tSD6IZCuV{8rmiNl}cl9&(BEC*eR^1`BsWHiHtONpC7#`l-_&m<bdT1To zzFSi7d-T%Y2>1#iL*LGlG=`$29M5Wr6MvdtF(JrjTQWX9wxu${X(E$|CJ1N5XzVA9 zW#CXxVploAG=&Ca_S-%AZkvhkoi~+x#FOS)lj<DHg8x?^N-zxg1LLxzxBb^@DPvs+ z;WOo2vY=Bk{Ay=ytv<h^V~LSvTClV~G#C!!!=b6uqD#HpOTvIQuHBMX1klP#6efqZ z${Z11p|TQh2z+%}rU~lMSan_VUis~<l+_h#jbsdGH0gW}3Vo0Ed%48Pjkp~>L^}BA z$X`^suys^xJXc$ZHl`_P*$Xb+PWjhte=CFD3icZ+YNUMeR%ofOlzA(kKxfPLFpI!C z5X=+HmqRn=U};j8@AbQXZ0Z&2`BHN+kl-1;<G0f-;P_q@6KAnu%R58(?OpEH3E&Si zWC|AM5=~?XMT!bqzTmI}$<l3EE#o+JXgH8I$`%qw3>mSx*XknEhIx#CnaB~lU(RZp zCf=k#aLA?F-<H$`C}<DZ<d+|}X-t}7w14ssDE-+dx0iYc&;r+eggaYepZ<@BF%lAG zah`Gyp<6sa5=E0ruW`NAXMtuxpN|Ab(&mQ8ypMo5d~Utmun23aO*D^@iw&$3Y$iUt zp84$)(6*V&C}SrVL}n@Nth)39u;tL<hDV7Xy~w&J8v=XQ@qm>Rgov4v?Nt7^YL-x> zY?-d51+D!^j3SX+hts{Gzx0NZk8|PN5x%1~D~-AV%mp9(n5N2HSR&H@qU$zMg&&|# zLOB?J3OIjM@XaFV4?G>C)pQG(p=q*b>sEDWYqr<PBaDZ}U1#7KbnKwC1qdFOrEtF* zS*Tz}7>SX2LvJRty1hACJy{jPDK8D!bqZTZSvLODoSi<H8C545Jl8N)i?rnJQ`j1H z=Vtw&y!5<@dK2mKT5l?c5Wt%xU7jkzYspK?UJPQFT9CL?ln*Mp{ztSgY-0eVFPF8K zmaSaHhrZi{OEjb#0iGMbWsk`La~5bEX>k7U?`>^KVd3|-$$O>`*EH*6O*@~Z4QlmI zgaVjdDN62Hp%tt9z1^SUCPMg$%TesO(Pv=NUdKd=2JY&q<P8f4r~l?We4>U19*d4% z`f2Pq+Je@po|G5=V)H^@2Bcf;%M<U+xcz%OEpc*pN-FP0dy9?YzkMNez-bNhQdIP> z1n}APfxfnegQ9mL@;YIR#amhi;jzrJdKU)xKK#i|={mR|?`=n-+LSWMq`}F0=)M}` zB4;&Knk@2kO{uT--3i}PN|^~wuTG^~&)x3xq6Z>dfhqwN-;6pRyG@A4Gu{#W5uXm1 z82#0it+sTmCz@#rTYk>^N6g}rq~dm=09=cpIB++&a$O1B#|F+IXN^tl&-FM~{ufRa zlY_YTSm-eO%QU80{28tbHCGfWdTW*x!%(j2ee3um4OfzUjMLfwJb|^`3)@<Snr8la zz)z&mMXxiG*S$54%(vkFAGTthF4WfV?&g|aR5Hv9-N#CPNtdq8PYzUD`@}3Ok-+En zXRXa#0l<mNdDEE>Po#DJ=<ygbw$RKiaYw3oF&Glzl>ZyYb#}*4?9gJEf&SlrsEwE3 z1c4WQrnDKog^-&H7uA57x28XNFev5cb~K3}@E%%ZP8z#9fYqF@Ap2qhT{K~Z#L4<8 zu&de#{gTZk=*gzy2n;D;mWgF&hMyo}`jD^Lg}xZG4()#*u^u9~n6hN-o1u;gmF>wj zkf-<^hpRkpW|=YR2{r2gy4FQ<vc~bHsSc8yRYo18G#CMfG|^TjWv<<yvR7W^!hdCc zlvm9$S^Pf#t1d!2lG9b3%p%BZY!Ur8CTz>{>F|1!)}^(wMS;&b%M<rImK<|zlC-#p zQbxOWc+I^(IdvxxmE#^h{Q~U&!j@e>w8mxrRDB~VVX`Vq)!g)99Uw+^1N!7k!V75w zEU=@pj?H2H_KvpHP^JN(+=bs0m4+do98fHIBrCrvU9lSRX-iAsXy>8(XbsPmaXRlP z<3haq?<QdLlx!}?Y7RuXe0JbctM<x^@EF%gHfuWVv((K>{L7qsI4#jAp**A9Br6QU zWz%A^%>9^@J8|(3kxb;wZTLw?93&V851ZVP@A5jMiyA`OFAk3Q4xpr;c>L<x`xPD& zNk1SWd#meh2Nvb0h22g1+ThJP6w(B{URE2f5o?>l)c1@pw5=T5@#^sNf~cLJhGXn_ z?i95F$rZ0WQ3!GzJ35nV>9`yPksK`P0(_IV7L0&fInV2wnpFPR=iT$WxK7G$!opuU z_((eDo7hNPepnzCAKf`upsRJLEa#v*17<^cM@ObF(}=y?W|FXD!PPz;%zLH(X!@x- zODUsB(G;XR{(zON#wX*3WSPxt+wK5nd-bw)#SerX@2pWx_|9}pl$MIcl{E2-pj}Mk zKAb(oc%XP72Jd$;&{D>T5D#pwcM6nQgFb6Ex;63i{Oz6=7<IrR9XsD!9j5@c9_es@ z5+|^=ADMU`06!TNRFVB5^N)jz|G`oMS5Gasi{NI$`mdkU@v|$(*}Hdr#s=C?@pro4 z+miDI2j*7vSiU+SJjyH@RziB{rDoE%vQ(tKCP<#NFS)mlA##>yH=Y-GY@SKEjj~<W z+`fRTZK8&ID2w#y|8Cw%e*ck7a-A*i+a^_h@6`XMTx!{vZ8*e3$gxCwt>xK-V|6=e zhnB5aAfsyrm*{j?zR&KyFDZeWp#W>ZPSM*Ka>Ter3Hg+egm{<Rb>uaT{?LqcZdTiI z$Of0v*}|k;;LFx48N(rDZ?dYkCgO*%e`#gFbE-fqYNw4i)UO@#hig^RI-0%?DW_g< z5wE!h07E^apD3I@?PL}_kAUHlpF}DC4VtNSx`Chr=Qs}AT$t2M-Pa}?q&-)~_mq~! z3D>un$hJ<NS)l%Qw)P1d!hW@tF;4*s`Zty{+h<+_o>F{z#itZNGV*T^{4#cxDOH75 zJ>$Umy`mu95Phr3Gg?UCf=iPRh3JR)`7_F`O^E34i004HqhFRawHVMDvl3HY>oosO zM;Txlwrq%p56yyOOy2@&DR9amcip7Vgp)W%{KDuK1*IhwHz&@qalk^*Llm?sF1kqd z`g&h?E~#_=Ql={BsRW2`?nNFbIQp~dIWlQDGYUEa42R+qU5)<~88iMj?)gKjz~i|F zo6y9_H<PxA8JIb#TJM}s<&#pJ$}nB;ZYB*dqtJe#kia@*rpYcz21kS0vRYtcXLdP| za<xbY`aN_b%hy<Ljm>l&8*8ZgAX9q_P}R^xaqO9=o{zDuGBCW5gDn%lFO^rx9jUo$ zO2SS%LlblvXX8>h=eZKf^Yw2xet%lKwB$X!?L{ORz#eaqctvt9*G~1LYv}FX82`a( z1>6B8HO~N0iLyi7zeZCp-T4z~;p<@3b6dba)d^?VSdo(p|J(R$^d2D7lBi?~1mNid zM$I}E_HbBI8iT^(53To2x9pKCd<j;wx*iQvyH&OFFE@M|N};f^0bFI<1LqiG__6V; zxtj8$w7dQ*tVr$I9En{Dly^~flZ))I&9Fnw^uY8pPmzO0)c$GxF0=*n?+vW>A>&V? z1<<lwE9S>TL(iKp=ps}Mr$K(%-W390AfXp~h%~8S699)8nUU~*4JJmeX3YG8jX&mX zh^=I7Os>!5U$4o4;P+zJyo&6?GZl!pq6@Q%{z)K+TM`clkJUqEr*QRrzD|*g9%I|W z{ufZ>4CO{PEavB?bVXKqE_kOe@4_-G=lB+S8eu^#W03<VdPaA{W5Z~XM!!OUiMrrx zHvIv$s{fnUu{74kRD2Q@6YA8k_O_?RGWWk;K;EeSBBaG%0d4M{L-mxyOdKlr`FzmT z_n|4*)Q=Xv$H{`2OwGoW$#9#f2x)Ys#;rsF5aIx~P)edUI9Z+Wi8D+x)5UoE`#X6M z57%&miO-XTIKm=G4O&>p>&ZV?1bR)?5e>pL@%yn>H^UHT{jGN)q5S8sNroDw-nJvn z{IShaCnuw_35R0s=u=ad21I3Jb){D+(oe05^+DoLk=knqMiy|GfV|WDKzBKEke?}h zDCAhz3~va!4P~>`Zy|v#%6R!2xjWO<YsO~Ka|Q*Z-&+N^d_1jmR0?<`5&N`0KfsP{ z=H0M5YSi%GFpI87kL{S>kC3%?FlpuS6w|vuB)l!<pdIa^wl!We#q5pH6=)9^(0rbL za+gM?@TnH#eiV56XD0*{8k5S%B<M||>BMq@Q*Uj5W6QG9&zql~Gnq4}Jr4cp?zgMk z1c$p9lGNSZYln}n2R<-e9i@G{cJGz4ZfsI7%N%OBD*cf~l#*M|9TL78`C2Ec#+R1_ z@7<fMK7x5Ylwy^SQ&u4nCJgGPXN;PE4!}8Nt$o>qc;dJ`umPfq$P)zZglc@y@yO-R zDnVRW414(JpwOdN8>g7+YKM~vp8PuPQKyL-R@SLOFIG$++UUkziL5&x_Je!#4~Lr- z*W0d7skrp<4`{58*EyLg_7n_0O+dL>SyCNits2Ihr=|olcMPKpa{lX!c5OfQgNSOC zR&4fAkrcHk!kTEXs!}2C4X6=Ixk<}V%a!#XZOamUYuLUeD$B&N0w#b%`^j3=>fil` zPLw2I8`+6foQ?Eig=**#ib(lyz^0}QA-%HZ!_m!3(>+grf-zZ>3CzRJZF6FME?`^W z8z2AN?<`w9Kiki3>+^QDgCWF-+SaCQ(Q-`h@6A9vxQg-keg7wUS`C-L<F}#-R*BjX ze5Iu(e#@l^^F~G{l08hV*KBJr)p{oWCqoEPQP@hWD5aim%C&j$Qonf|<f?#HxOM~r z|DJpphl;$vFW|D075-#di&d}kay5s{K`afUCy@U6WGOXaevv2sZa{KRb>DhsgD>F( zW`$kfKVt9=mwcJl-+lFzAe~i}7=v3>!i+*2-<YYM+nUBzH?j1YJ91swv7Tu>D2gu~ zvUV@gd<b?(7RZ#nnm#f`n;3$I2Ck+2ffkz>%AU;l1m;&)R{rQ){gea{`ck604vguw zHT9hJOMZ{<795YHy&8d9l<Zh}thQQry;01%>|0kYAuYlP&%Fueq@m_Zh&gb>3p22K z<RV??w>Xgh3eDT6RO?ILjVi*jRTKuMgdue5*n@?iwp+)2=5o`KRm)?=KXX4&wa!L@ zA0-QTlioO}0pB%d>g){L^eJCtjW@usswQV%Z3XU#7>XE;|3OAa{$q_8^3cjqh`X|7 zcb2i!5x9CFNyjclX!k7QFxt6k{1aBL?&M&#+}1bbZ1Q>8PSf5m!y0lz5*N&yh+jNz zZjTX|JMh^KSGvkwk4~F**%NxF8j+hell+Y>?dMUW8S-i|X(z0BvAGRYBbGETUFo?< z(uvtQ!GbNO#9KsOB}YXPV>9ua@3RT5(_MLQd#L|^lv3-Bp(`m;$Wo0@5(K|U#O6HQ z8J&0o4PrHsB9k3lkeB0N)>`=MSU6&{j*u#u+^u|dS>h`y7XIqudU}<Os~{yamAh+D zFrPN0@$K3x!8}N=SQjcxpH-@Qb)CdNS#9w<OufQx^=_#&w*GwT_OKK;IX#I>1pS?t z74rA5)9(%j7@0=s+ow&ggHr+X@sBK10J}@1G&zZwr^j%ak-DWnY{a?r4y8Uz07C1& zM)aqv!^A$9fL*D1f*w$#<)m7PWcilK);Bekn&0!Bo`CnBD|%V*X9;|12oLcZk#<Ws zdD~?FM;#qT?0mXT>qTG*U#%DLn$8s6+&)px*kP3<-GaxpWRwo%PMLnb6v#ZAo4N|z zE>^YK0q0E=xQruek}7#Wr2NWgsMdV`Pms|{=RAABCd_@>NVJN9wO-acnr&v@M8-u+ zyUR&VeTR4f_1`>1i)CIM0xnOfZRXES8a`<RJhAon+B9mJ+Wc6we3ZM@;n}SDHS7i6 z#*()IYs8W9v%TZt$#M!I+>JL1sk2{EbL`iWD-DjVPVe|iWIun5s6_al&3Me?FN8E8 zCxOMK0>;0iAaAMphYh9DiVtd^>)GHqdXis+h=V%5LmEUULU$Er7T~+z9UctWZNH7O zqLcb8&2n_pEk@kkgpi>N*<E6ll|D<HKie1M&j>(Jf+e1&lc3OrrA9Ke8IGUbhk^>E zK^&`568?LF2<Ifa?cW4neyd#_f$bIVB5s)xJDGXqXh!6yN4J+-pBWpE(#!!g-p$q7 z%+RpG9ZT~0;5GD2F9`c$V#)lATyNE>^Nlh3TcR~J?pkh*!gZ&bI&6JM(yx*j5@eed zm)%)d4X49P4^=DKi?{~DqhdCqlft7sp6^KQcHyQcm@_3$mt3y;N)r<VS~*95ejxKm z&+1)Mr8F=5KTN;_4<)xut##^7EG3A5p6}H;y`0`WVs39!`;UyQaiNY4nm>?3Ki3XD zvjO$oPtrwG!<ufwSQo3g4wmUTmhmhbi-q@%sMr0BMHx@fG!CVS4N@*%-U#(-$z8u^ zX+crHq66|hL_tE89FOr3iM=tQ^8}Oo^CO7QZg#6DHT=e(*QU3o4F|mal^?RK<P=o- zSd;SXmFWUE4w{>Ml2tpoYo8C{7)_h)*IxZ>G{`>9P}%AWtg|T+IwwDG8)O$7>^Twt zX(hQ!iGCkAyzT7hWGv%xc}~x7+Hg3kUW$m`2mQEDk-*4ENe3VabxBe#Kzimc5DjzD z)28p7S(Q2*K9F{t)_op9a7w);O-1G18d|x*CS#sxA=l(e>m~%E%60XGhj|dxP~Ui< zOBt(dXQBE0Ua^n|(OJs(7*Bc1A?@yR1AOayP#s)8>O7*3(`u2j`>r4L)%j*HH-*Kv zZ)0%JTY2=GkA5cS>Mxu#H&5zIr@OXt9Y~vw-`QauGZw6kAK+^n{3}_#elWAROg{hs zU7A_>4P`rqu4b!ezTh*}2Ht)nfpg_?>~7Xa9eu0h$^@SOomi2_^ku2o?>X|rj3tPN zTb(tT7?QX>YQLO;;@R0KYNg{mTMEb4bVNQD=G-I@9QTxizo}W+m#+a8gwk1I+j}^* zCQEUh=Z?A>Y}S6^@#ORwDY&CCVC$y%S429JMjEY`cgm3la$o2AK<N_rTR&qqx#u4f zq{T%x#ardPag+L+znCy3{iAvXm5e8sZjz)NfnYnkZIVgM*#xp3(zUh}VuHMI`%OaV z=1KbO>=g$4$ZF4e?8F-B6fB5ssa8J{0diUa@aKPbbHpemy#JZT8DU4aZeXsn2?wj^ zn9SF^TSFET^K0~m8fToQYF_7XSy8WowX6;qd<C6q{^RoU%+b03-{Zu~7ryGIE~03G zi*Y2HRI`19Mzw8o;vPXvhj_Qx*9$;$_?LDTXuCtplvSN`<>c%q+3F_GU5p_Q^}L;< zi_taK{hpr?(8i5MOa{sOKdC=gHl?>{IrTZd@QWuJu5D*;-&ijIcw?n^8GraNh0}W< z7QP%^zt4}~6xeWG%pI|Hc64+ySu~YT*LQr$eeX7S0=|{$UMHQ=w|0oXXp~=8QDiaM zKVXTB$IZ4zXKV?mN$u*EA}X6^9LL27E5z?c3z&*`xxM4~mE$0zdrY~gzL?2<i&H_h z^UKMZe@4P2@a)OJi37g0@Vt{ZBml0%rw3fWO;U<Gin7+l!AJJ}J5P39{4!a8Dfnh? z2yYt>WW+q3A>6OLhc+SsQHsY_dr~hRU_-=O_tqEvYO^n9o~AeqZ!e|+Ck+i9sPU`) z^2@*%y3gJ%j~!{bIg+hSz#o6Uz~k6$pc{=dB@yl7hh=-!4>1F~6CoxIaB>Z#LTqY) zpeaWdzpf3=x<bnw1s+n3oGK%?r#wQ5DCOM96+O`3I-M@1V|!UjAUtknRkauXukdG| z1@9NNUwg)Ub)bi8KKq30+C17>nz*Uk-FH+&dRw>7{k@nu7-ya7IhY4ZGX_o)3{~}- zYoNPJHCt)L0%EMy4i_fp8N&aEON72c545R~E@%H^;hDLEN8UVF56|*j5}e%gL{;a0 zoOG;y00k;OI!K@ZaU4WbwdnmddU3yanUNBihm#f-mGDp&?frOpwR7Q9{-o#g0+pYV zVo|<T)99auB9Z!$+po!Of6IO8xb~=<Q{tY`f~&ZPf2B~3zXRAoOsd8|Fg*iREmbLl zX)qito4v*FBOYmgL+;uQ&WDe5a#;C_iyKt8^WQX|YWERA^geMzGSZKQOqssyy|}Xa z96|)jNOK9bU%XNB4l;pFS<b4HBMJi(J;mAR!rI-|m-gJ2UB%gAvu^oT(?Y@i*6!&S zIW4DYJ6i)x-g}2$aMxv!7@LpS;W<^HSMKa4+`V)ZZBUPGD(x)3g8G0r8%pgzOKijW z=brwa4_R`TD;V3YP9qiGh~r0M;KxWScl6F%P#P;1TNe4ej`n!-1t;h1_a>I-02=d# zS?BSz821{C(?9<YMQQs)39~1xmedDqpQW!&%_MQwzc~icfabjGXVs|#LlCph6XuQt zXcOJqb*@k1)(6|K<x3c@t{-QC+T$3Y)eIClv-VZLyriwCFPh61+u>iq%V%<Qq1?FS z2t!EboJcF?2HpFHPp}32F|p_#w28laP5G;l`HhE@QDk#5JF91HuxpDN&}GzXkrRio zaLVAX%U_W+(c29Ruum)1{%Q33zG-&eW=03aatGS)8i>>!&w{e}qVaOg;YbbAi6QHG zO@qJzVUy%tP;b!kFimtP{l`cRT5<Gh3&#nHJRjw9wPk~5wGpW3o4S8?1|!b6ia%~M z1s>`*q0Ji_8b0cx>xGjGGiAQ-?nL{^z$P{iiEKEFb=;QMjl}mboig667C3$hy)9<) z{Nsy06=1h*`p~KpK-_PIi=HI*-s#vtU5^u(OR4-Ila>C{Bkh}=($8V%@7{B1JH;)g z!z|_*TV94V6QM%OxrwVa^Ps>zQo?Lnvf-{bEpB|8$(Q5&f{2s#+{gNZ+|90nlq>3H zZftvX?A#-U<RDqU{+zk*sKS-nJU=e_koA|WjOlrgvj1XxV9w;WQ?e+`lw@2XMv0X* z8kPQ>VvKu`qJKY<>w~iT%xQcMaPO+Sdjm!Gt&OhO*&>(Of6sA43`obAx38*bsSN&W zKAX)_G4C6^L=zmL;|1QFPAzt6AtWB+x?-w`GYiulGue#$vaU=2;@<B|`L<;7L}Te+ z2W7TgK|`0{QV~T_(2fWn$un`)&fuK9scjwA?I}I}%*(;G0achtQ3I>Wa$8&~yby8( z<RAr+B*cNX*Ol_L<^s7T|FoD_38)~*fm}3VlMezc4Nlw(t9&<Os;OZCmAVEENr-|F zk}z6%FVGK%CuTm#AgReuD|3d2g2ue7Gqyb5@1C@(ka?W4>cE9uZykX15Y@h)FGl<3 zc}d&mn7s~SEH?EVf1aJn6$iB>9JB*&9p+RX#EuIXzWwpB?edh?{vj#JYP<lmlz)@b zALTzYVN%@O1g~_vtR}U-ErtRxqt2UP^G-KvG13RSh>sW!>alJZvu-&kv_TKa5an=7 z+cv0)w7!6^Tcj^FRvbUwy8o{F*DeA%y&D|zejkz`;cYQvb3J{xdhsW%4cW*?+C|+= zF6;V|4@HxrrXZioGl3TT;l7c95%g2RJ(Fk4%L4Bp1agfln;{V402UJy9lO;3A(K{V zJ?)kEvBAXFU+V0*s${b?_2D-%x3AmMs#|Kf-!hf){+Uep=Jb$xdNB@A?aa?-dPeZc zyaLQgo(^X1>-HA6y}rH-2v~@qKQFb(yd0jFbl>PER!GQFe-Pk!zxIQ5I`**r$=x}O zFY9I0%8vq<k>-$Y-+1~`)j#JIWf(;)Lt@lb+&94pDYlPIgE)1&-3&3)i{3sGTQjSK z*Eo=CT(R{=yQ#P@euO??<-^q(c^veBIVwb+W9i_5&_LYT@uk^$fh<FIM#W9WG=bUV zTeE}Kj9XrxR~UzaZK>7qY;BxlP6&r>RXzTT4c4p6E4Ssgv>`G3#2@9F3xY=nLRpvo z^w5oj7LiKVV~{NKjgnx1s}?kMXi^{o0nmJ7xEa<*<|h^T)atEHoJFVU)Z4#Ps|>H8 zG?|T4g+C{g1X|9|0j2?)4p-Z_t%1tyS7flCDN=;ius#1ZkHGzI5~KY6OUYkh5`|$x zlYi60Q^nAto1d%9no%Vi5_W8b@fB~G&%O<5<zXB@@}%hvWlEf$%wM^P!J03=o_Q?z z9xfB*_A=?O4g=kG3R@1vkT`Zw@7G7&p7mJuNX15Cl|r~Z1}XO=FY3FXBI%N`MKaNi zS5T7zVA_y2<zf_g!qd{?yT%%*i7}|>{dqeeD^-H9fs6%Vsjqs@3+V$T(*OhQSb3;5 z!&?KywX|-U!yby0PDv+n1M#u@^NfG{50+aV*mMgQn4mj}H`APpwb1DLv*|u&(~G7n zXa9?xzT;k2pEy=h6}z4*w#v>Bnukbq;C%h;@5@o5tM)N{Y;?+GuDE^5%>6ScVzkE+ zwkKNYP^~_B+O%UU+Px+tKrKMZD}WS|B~X}{A$|&2A1zlVEEAQZLe4zI?wgWEvf^%< z`LVUOM>ETD7XvMa|LD(gZ_O>U)~ybvf?8#HGb53YI2?r@>4j8<H1!Ty{o%hI!`k~t zbjn;>E1yW7Ukn$GL+-v|e^*6oWu7+v4|HrUkz&T2*9FYW&j;?KQPcJHb;kA9BsM0I zBLIIi1X-zT@!#2q&-Xy@i1())*i3(xm1zz^{b6U)*k~gIc9qjoU-Al9$He8A={X6M zjMeJ5p(^;Y0ELWx2c4x=xfk&uZNPnTYo*9##)L}B;1bz-&x>BwHI1)B0&D>r*nC-> z*!<No5}KpQJJ^=eUh8W5!w}cbmQyf*hlaeG_W2|Y=7p=BWYc#mrauqm%ly6we`JN9 z*7DnO=`|}c>%D<|@8)Um>}+8_Us!t5=`k^TcTU=fT?o(qJ0T8=*8^O22wXOyLvr?y zD(m1hY(k5*7QB*!i$@HxX(nbCbeL|CW8XS&PIa!DzM`~%V;C;mX!<RnFu`v+cBP6| z^jyTg+f8~=hRcv8jV1MyIGMMc9d>lv2^?gxHry1KMHtS%n#2NSv8r`T-Mo!9i&H^u zwSS+d`eptBznex)j}DgQyt-idA$i&Scw5tN$v6H@rO3O2D1yqnLFx)Fa02xa*BEhs z-lQIHP+4Co2W$M7^;Y({IqstRLl!>fD!>ucIQnc1EKw<2bs!z#w-Lr7m6mzRbh6>X zBQq1pQa-WzH^u3bB|rK;R+#mt)vL3a?v<79j-cgP@5)am4FMF0>7i~7fZstdGV{DR zaJ}_n2*MEydw?JB#X`sM75qoNWEBUW8Hg{kG}20WJ18;sCA@~0&5FC(Wt~Y*66zO- zKXihNkY{2BY?vC@%jT;U+*T?8VK~A5tgP|D8i$zkV%H+6$MTmqxnbD9j<%7-nj;L$ zD$<I#OVA|8?rl=p0~Tg(!*svs(ePB)JLXPWOAQ>vIo$+U+q-T}?1rAkw-pa!M?XVP zB+?<w6=(7B@@~g#1j1Qj>F85v99`>a<HGo&0^odnOyhi3;m9LjGDBU7pnQ|&4Z8+I zcHZV6KUCM14r@XIBD)fQSQ-gH!2e9;hziVr?7<2ytdesv<+O~aW)_YX)-~Fn3=K_N zbjp5CmG`-Fr1h-2gNGn^@YTY&Og_k<pE>U!Qtq;pQz+9m?4*Ei8*e(UB==VgY)&Pn zWqj+8==^*)aHd<dRJGwbMd^{K&n+uqis&!N0xQbovVfA(Iq8~exHm)Y+dDVT7=Zx7 z3RnYj>@qO8D?8_0bC&*9dD;9d@P)N>^8kMp0~6{kyR)SXZ*9a@tq3NbcVOz-*e;)- ztC`u7kf?-AO+z&l;tx5q$kCl!x}8$Ttc0`%1nx0kjRY~C$}(Ac<cQ1C$E7~!xG$v9 zn3Zkh()X2hI*%}n98UuY%J>93;qw@HvLV`mZDbAm>ybIj_}#*c>a=8Uv7~XqU}^)B zmv>ko-FK<Z6p&^h9?5*?Sdrh5*O=mZiF;aqdG#K>vu7$_S@eV~@LndcH|EW>Wm`?^ z%tn8kycKx!ofR0X-Ef`J?HWw}g?c|g@(eqVhvmhAj%z6eq?+@BJv@bU+dP8boFGT( zdF$s)R*o1Fec5;~2yIcLtb#PM($*DcSd~e;iN3TcfpLT$Y_awcsq+b@zvzbnd>6oh z)i2@unsI?bS^#F=M%k3^@5(nP>fgs8U*23a)Uq_L6r4toi9Rqv+N1I$XO`AAx`OF< zN6zZDa3_5e8EMG}#lOs6j<>}~ReJxYPvuwyC^<S-b+6gvqrL0e3|!l?+{B)Gi&K!R zZv^<#u99V)obzIK@H-jq$rrZ8opUqJm5Gvbr_b62wp$rR&wATJSnl8%!6BPDL|l`= z0T!0Ud1mD83ANwCHy5Ib2f&^>C)sc+$ccezPvPR-pN|GnIc^pYRZ}coh8c+J`2)Al z<e^aO%ghKY{3hpG!a@8}_wi*Ngnp&sQhYA+i8Pv-g6c_37&=SX*c6Xf{Cjp9qlOEc zUXp)Lk%w7cP9WZ=WBdF*Ttb{GD?L+2QbxvyKGsy+jVv0PN;6H$kfw~WYagd~0FdLV zsk01U=JpQpvwf}=7lmus9$-S`+&tZ()>rYAP45w?-ERr~&4PiqI|$!~G6eVRP`JXW z-Bw}(bM*T`_H;?t9R|*|)}2OiQICbWHvEiWqcTj=I<$l20Sj>P3VZ_bc(xKRS_^A3 z5li5Uz7M3IBVHQ0MbA%BV$U7<Wd%LV+^<Nv`^94TH%v)zm2E)V$;^QBgH6V3#`bhe z4%IpEgsuC2?Bdp69~qLK=IMw-k<0f}nf+E;j|HW$r^(Ey)-l(5%@dC0b``QN-}r%H zxiiQ6Qxw{9s!TOeS&Js$(^%3{8uqCIY#4rJyZ&G6h+@R2M(IuV54?w4a3Z~XnL-)g z3>jx{y3)KCr`mv*?8D_jNCRlnY=I4G8{>p~S2)1GgZNZPm7rSQDWdgxDHN3I+{N0n z{%m1ft7+p9J+om87yr<IGv{2OEO->D<Nq<IbOL1c**d)JZKxkG9&-2d;ir}_r>VCL z+0H{sA2-?r^)J^5Xll-zOy5n2t;o5Ayk*b2eop+i3_PKXeK2%N&6w~Z?Ay2CD1(>i zUK=vNzSf`9k?=%OQ5~CUY!7XOLIgUJ&!R8cI*taDbnzlOdT0Tr6e54E>uEQW5;pDD z!EG9syN@FgvItQ}(rL`8-8#5JE`TA8uX*SO+DK6Ll>|_cZRn^H$}hHLQ+X2`L;prw zmO?28=o>HiCNx4wNBy--823TS4Bch$>68)Fk%HMlGkSrCI}MQ0y;i{`GkIUiEL($P z9Ei(W*BGYGcw!CSka(Q*qKa?pR-y;58=hj`X2IjRAxjq3Q_cg6UdlRnL@T`o>7pUT zFkV^iXjoEyx(cTIBS1~!ho$Op*JBxv|Bt7)j%)gTzsE%cL`s+v(yh|rKw^`Sk~Zj^ z^hS3h-7#qakrt31pfrQgog3XL-SwNF@9X`0?C<@t=kDiqopW91+~;9u%Xq`glrRHl zw!P>~TQn9OVU4|1dv<{Ho&5lxl4<KI$GlEIlSgH34x)7JtyK04C-5W5Pkrm!tbp>P zRo<(=x*0c?Ijxj72A}qV)_pt2MbI?m>t^29zrRY1=ECEf%9KrQ0xyq#m#@F(-niIz zbZlB=J7NFYem9bYR6PuDr)o#Czak&naS=-8J;p5v(v{!=_Lsh;zPAWRlqp`duF70; zc4&5qvQW~|`2wHIMgs1Gghd4@Kaf6q_hhtvC%vXjE=p=CC8$yXf+n6M6<@sQBdE`B zgW$)o-9Dpb%TMU`VZp<E0EQXX;P8Nq*W{&j^dU;0p=q&ec`)jLC<}e1$TI#0`nt)g zSqG6m3(?%Q(UmXS!~rV5(88o&p98h29noueVWzY+VHrgM6^}nEy7%qV-K*ui9noJ? z8p#RSF8v*sGWXzf;X0V#VoQZlPp{=lVL{++hRn?arja~%CYNZNHx<lyziZGUiJ{wy zpRCokX2`e*J%1(c%F_Bzb*23Lu1figEZ*hivj4r?R#ZcU^()c;b?*CnjpXhO;;xq9 z;)$(m8%_5|*rCZO={Jn@<{_88+#`>Pfv3~4KrGD`Dc%{^jD#VC_z4cq3H6s0=>}+x zb=h^9r@lz%x!+f+rSR0W-bzphX_JZ26@$b16b~0qK&N4^V)2?b5-H?=oCK_>_1cUp zf++$=L>LYVAj(qWI&s>>kIv8b*Fg9ZO@*xajEFq$eE7|eVB<)xWh*gO{8=Njf@A)o zk0<3puyQt-HKa-l^pN+&O7ec=l+q7ZZJ`qmpk(67C|8s(W=jd5_I>B-k9{C>5m_bw zbq8=%k!5N6l6h5MUfqF&VwElP6%Z!#>IFhEfrkZBd``Hql~{--zn#z*bOlR39t9Z5 zZY7coD}J5(L0dvH7gF|&6RMCgQmpjQZprkCPFw<Yz9(I3yL<mTOL}t8RGC$BM>D?K zFpc#lZP^SN7~9&HlySKyt)(+6Ej%;-#!!&KCx;%c?suS1=od$2iqoJfY(LuX!uv+| zZFM*O86-nLv$1;kvr)Z<IT#HspZ$e8lnTK!9^aGT&rjw|Si!SF7rI6m%n%R<H;U=3 zeK)hDKcYIFA;8e}>zrku{!nnTo}}7LUMgFCs#iUJ*mKFBa;r~m($BR3YoGu0m4P3U zoA9_j*Dgzuu5<@)u{hT0dDIzeCfkGv?zj=|*It&9gD*GVm({kzJ#o=wy2-@FlTdz6 zDAYGh#r8CnQtu8%{0)w*S&ixr2!Id?dy&g`zH&-~89uC-A#{C4D8|zqJ{0WPYe?Ss zmbO!Qgou8!odW@;u;R>yy_6>wr%6V2&QA&MvOlL1v*q)CEsM&ARg539O|#_kI(5Be zCCQ82sTSo>6nmL`QZ4HBzlUbIZ#v1eKi#(?+KlR7>JhV9jt&o=TeP2HXv3pxAcz_4 zlzUY2*KFEGkLNUT`_E43cC>PPuX(7X$e3XP^7Y9{q-!OcsjT{Gkt%u5oTFpL{o1EZ z*T{5~LTIPRO*<$Ex$`h>;FwC_@+vTUGt}(f&^&`s(BxYQtOoeFHA)fEC90e8_=vR- zLEat(-{5R<1?x252;Y#WM^Q{}D_(XWLES%gMT+Jl7+Sqwa#jf3NWa$BOnnpCI;<BS zr)|#ra@~Vu>9q{h@kQib>|Fj~?$nc~$y7gHLBicD*|MkOs44PlHy#(g8)5Z1(XJ!e z3y#@e#Y^k?G|`VJbo%~lHOJ*krCQ*5+Qrq{_tSh>8sDW!fHk!Fc{R_rvkk2lvO3W| ztNgdte<d|UPL-{I17#wp^O+VS?k#|to$p+%yJ>kB87Ojly6CcQ=2S9vG_CiiaX4{j zW^hORpv6u_c`%ds3$$sHgmEU|8yiQXV12_NVcur1TEhDsl{WZRSN7hYAoknX<qY;$ z`8$Ebu~O;|XB)AF0wEN%eibT9D1lGmalUCj^!f8%Xrra}o6q#$59&zG)Y&}sL{D0G z<eN{`?kA2;%}dp--bypjt@Fn)>>^_DX8ClUXyltX<xh`7UXTyTUop1&9MFsM$fc1o zi`jrl8qHZD7*py)SyP}%(A2G_IE7x7V%u@v8*u^r?sjsQ;zssgPv1$9PMBe)OhF&t zaBTa;JDmFK)nPjbDQak;Y<z)lfx9oH`AdDH-r7HSu#6($O<4-pTktyHep8asza|KG zI-?gmxxHKI3RJt+a+3dhQJe#KkGjwQ(6ezrKl{9r?l{kCY6Px+6!f8U4gU3kupcV| z`AjQr4RT4Mlu(wW1!e!qsE$8pRPlD?dei6(;?eQxqT5v3C1frt^+7GXsl3B`gsN6p zRWpP2ib=`aFQ;^~7%fNq6a_t#inKeo!Q;6=fPXT6LHaySfx#O$2)d{FezA4OfbX<r z#a+B9oE2||OcPj~LSW?yj#Igv%t)vivBqa{9n!fvJkyHD){$MMgcTYN*vUlrHbm$B z&1<IjS3j6d6@8{gq!_m>Cd|^i1Y)8JE;+JYh^!mf^Chi%eJW3B1-z}YG;bcaCkG1Z z5L+tGyo~zY!$;IpNMed0K>k;<EbZ^V*5ob^zR>yf>%&EV_(A18w~pxcgJrzIv;C9M zvg(pO3pu%ni`3v?6lsS0ei>ua-Ob(fPQ_KzLTtZ;?yj>J$S|AL2)-1gnQ*MMdKd)n zVPmw;vcw&l8sqH`g&YWM(guDxxI`*Pi}c+-sunvCQS9%<A=)B4Nr@$Iwo|UAVt0_f zZ+XRpP-s5)nx1d+!G{9#q2FDl@6@?JdNazlA5XtmZ7YY-0@J0Ikt^2oZ)8rzqjRUi zRFZv_r*d?b!%7L0^&E52oR*2s{tgNcyy1>cwr}l@xherQvXaId)rg{;+)Yh|S$Q^r zX3>}UyMUtNZ|%M{;c@N_94plw$eov}^8w|{l(zqN2?E0BM1VT`Dm&MR(qx2AL7>|Y zCs8`EqCHON$#3p`LFi}fXFeM;IFRMOUyHr_80=7iKAC(5o4^5FM?Ae_Cn_vZNf92h zeWT|~ik`%JdXzA-jFEBZh~M>mFL7&BWYC0qNBU_9h|3n&HMvlTN?XPGX}jkh368ZT z2MCyJtk)gV5(Qr=Tcy;C##vVH6Ln<l*H?5+xV^*?gS6cA-!NnI4SX;U^s-)<ixXC5 zrJ(xg;k3ttPj%TkIw^WuReSCoD@9~HPrl7%TMJU5mX8J6t3G>&gzt-OQN$sB+TH(J zEUIZS?36An+0{4o^+V&3gJduQ?p#;1VS2L_Xg<h(??eb<tT)w@V67$v7CrqM%N<t# zwk2-;Uh0fvp$avR^e8)jm<r?nY7%}~2@Ng1iO_ohw5pl}E<I=fTeiP`(&8j_on~5w zF{^KZbPQKiR2qHrG->?nXOY+TYXV&|_x6wdK}c5955N--Y3n9Ot8`3U!tqNj$Ljdg zKo*||&H*eFBCNlr!3;#eEd~Iky4v#LZ*tadt%NnTvn;fRu-{VgHC}!*l<bKXG?e`X zXWMpeR`s4$eW}={JY*rsxO0&jgh1$&cm^ZbfK0y$5F?P|!2qA!8(}*px=DGLpRwI0 zkhLVibcv8Cvlf^@Q+93VJ?O<_-eduVid`a#j_@CfI&9(Uf)w(dz-1djqL&2dMIa#! zN*1~1@%`tLVwV%cDA8-aFOr*tnq?=blF_$hgcD}*L!QqljS@%WoGkUWvSn{%@ZLB- z%K3HruA2SBuO;Sc-grSLF2#iRBhD}Cg8y%fNc@(7BkV#yre8&^ayXtvPj~h+&F#8( zX#2tF{XyJ=nsBX!Cr&tAPl$Hp;1zrZ81s3<7gZf%xBAVfvVnsQot(lR_$S3Bu4lX9 zWbA8XuEUD<+KRo|s_5a^chbt@fLTht7YvKA^w&Txm5>{3tf4e!A`0nd>DQi2g?n7F zsuF2aHTk%H<eI`|gY)X;*6>l;RbD5jK(%P)!x2-asfneCQZ~wDq}<o$Aw{oEz!8C^ zs&4Y}DC-9Vl@CQv(kV>@g6s$EuNJt^*EpT(nf#M<VnuYa@asvM3JNEV$DNZ^T~mm2 z2?nTh>}P)LOA{W&2~#cveU*KfVL(<YEIEAeW#~6y*KihPG+VQ;wxjjy!ht?1^jPQ> zvyXRTWB)*Pvi)m!_UTl|nI1>l|A-)Ugl$1D7PJCi33Q^dcVVFC2%r9qpbcFvi15Zc zG;$BzrEXB=?ChMX@r?DkS>yHcwMsT9L!_(|aIY^?go>um^oHk+gP6O94q8P!KsOoY z8=nJ(WG!tN^X~2m6gK}PnxB$oE!9>KyO_KrZjvAij|crF&(DYm6sTu=ux;+8ZCZ~6 zhBvNIQ&(mctpWqDgoi}m*zQg-Pwl`Q0Pz+5_lW`GFBp?COOOhF<sDhsYuRRy&%)yj zO4OD-H^tIRqDa!k%LhgevT|}EZ)7_7PYt^Pm(s^FkV`3Ar~Qs|UjdRvM66X);D&v= zxd?GBHR`{z{rvYVFD)%kWoowrc4w=d_i5b-E(n^V$L{H9ecSCj%i^}B>NWQ&oAr6C z_PBS;^E^ZGq*^MyapalQ)T80=j%rkPPZa%c44A&Q-6c)A%F>zI$ssJB-J^N`<n=Vt zU67-cHGg1@529WeyB3>r`z8Twx|Iw5@>|v@4Y$|OR$lJr?Qqta`>kx0=uhgYrRh_^ zq9DaPj1jb*BRaQ^B0UoUYbx^0iPerhnJz5YWY0I~Q}Zu7&jmTvF9r&f0OWcn$zcxh z!u1pK&nxEzUPGY{mpxX*no!4=IbGVi%0c?A1qxvSh1WkynO$CZngNuYa~XgFjYEp2 zKuwFO4m5rxpG1;X@&f14k202Fs*>zqj!cDcPhEM1^s6@p;%F7Gh_CNyO}QXNK1q5y z3YbUXHUB?^!UZMfbE2kKkfNBm((+Hm8P`&)_M*O93nDZ=gAhYt@6S|!gA&9v*~HHs zdD@SNxt&VljeV{UXhqJ<pag)*(W_rI!>W|`YlgQ3fwnU7ZCk9cj)_l}%7!7qml39? zrF`a54@$1My~jYutrH?P`ZyCFJ0SZ%<vohgFRorb+WoUBU$NCktu0?4)T3z7Z7d_; zGc12O{QHwJ#lR}zeu}J`ld)te+0Aj6AzGi~if>~bh2ynN{bqQlA3<`=`d#vjS-^u% zL-}>W*LDsqLDqpcS2Azvi{O<hu{2ubRVxZF=5=r05Wq?Y@f#SuMnb2}ybbG+Eknhn z+`06<CRXo_np)nRP*hBXR*<J<1v+Lg4~cz086N7mb{CK0-o08Q*Gmk1LVA*|?)O~4 zk9nD`gZf^r{r@f416mm?T8nKsP^gO=7;ttnmoCOl601h{zei<RiL-sKgP7Q=sC7-- zN$h{-W$|YKNJ~EvI9Z`q)*{uVXg*T>tp~z68nM5vC$KO1_5&+L;6^>tm5=Sh+A)V# zGdaoau^%#ue3a10AX9=@F~uX{`|EgZzlT<0F*SQ)xSLF*WqPidV=0Q|$Ax`koT?H0 z&Ch30BaDj8pqalw!LUB_K(<~Pl>|d(JAE4#loEMOf@#PhTdC^EmGaCVzp*A7o_crR zsk7>E;aFPQP|<M7Cmw*C(c>hLO^T<Do-9MxL<@(I0MvBQN>^`eyh+dbnQT&uJhT)= z*|Xm{41}JBky8=Irk6KS{jc|ZM^#F-aG>OMK*?t5dGu>nhKJ$7?ThY{{zRhZy8U>d z-gT#vR&UpOw0Rk9e0oze!=SiYyMA^xvZ_ftYW1!c-v1RaFr-WU7*l<QpNEUd1)zof zkojtd@s3R$-x{9Q7Qn{&bnjJX-=@V*vE+j@o~Vm+h47uNCq5S9GmWI#R=YnFv+|>Z zQtL+tmEP+Ab-ok8kf=85Mzxxm*i?q_L=Htf6w<lq@>@-=qT5p7#A^A=u?=grny!9M z>E{Q>Dp9W=nnNl4un}9LKVUul(z-hz>S>6SxSQe*?yHcD;Uef1_h(psy?j)`7w)+j zo5&_vE#p@%=uE)_>aZTHdXdpL2vO+Mu2eA#WbrQXc#H-*d(S&WlB8#KBx6`AN%Wq| zu-p_jBlD}qVNJFF!|yH5e<Xoe@L3e@a0^(-%Md*BF|x##FfSZmJkqby6Baqabj8OK zrvs|+#%e<o3ndrC#6~$~!-T^wezW;oHS^8xW)Hlu>UN$ofS%%$cV{2{rzETjF0KUP zN~2=+G}MkFH**;eM6yBo&A<>OxLf`x8T5kv<6uSR?UAs|Dm&XHPTD|NHu_DPkv?r( z9$O~mdz(OZ7=Ypz&Ei^^MSbqqN6@+Ujd-L3O?kgrd3eWDy$F>MV`V-4Z6EyyhGg^1 zEFTyP!N$8~&(rkd=Ijh;dpVUxZom6@USp?9v7D{IyFZDGsW=j%=D9q!ZzYrTw(y5# zhL1mR#(5eR8cu1SJb78Qd2cgPFW8C*Y4oZs)bDoRJWPiQ=51gNQFVTVmeZT+GTl-( zswbP7kVQWO(WOHlpKi(juK}jG7WD7g1vWn)w|u2juNfSkaRM1!v~TEb4c2a=PA8k% zungEe_CD<~Pn2w~>z|v0RqB!zl%!5AMVqz&H2y{+e0HozT`EEMJm<@UeL6Ey72Qyu zDl|_1x7uL81T`ZC-)F2vwt@<VR`Bj)&kTlJ+Xliup=bexKotCjp^YzIYRNy7kxH&& z*RNSXV7W{28>x~pvaOS+l{I)=78~gm)UVdvMa>ov2}nhjg~xGaCzyu2YTmKd+nQ9# zPk%?X7%m*NTZi>Yg>3=|sTiR9)GwN>837w!>W>;-^cA4R3<Arez#_~|$5YvgT4T%h zfLubrlH=v-<}&RmO8}dZPz=)bnsfRThb7OMoBn@A%Bn`(dl<j$chO|}^?J)e)fD!j zxV3hqGw?2~+y{aL+g{RS-5A&OH92DmS=Fd9kEm7uMdt0vivVD_lGKI2!MtK<5K@jY zHFDx({DLgSNniV>`HlpYtb4rwmg-WIG4af!LIW0=bG>Dn+Xgn{NO?1J+E$Mbe`aA5 zT&ph3n*OlPc0JcO15#I|o4HxffAT6E;|kM<GcV_MBpky}u6`yGguW{n{pI#&H|ep1 zXQOR0X4p4O`if(FtP}b!^}%xfi4~ux>?&KzO`MNn4|(@ON<e^BEiDOi7{95;=cwZ; za(%g_;kt?@T&oKBiZ1bU4d@U>{n){8l3%C}6L+soS2R-?x7WQWDw{J;8jMn5RHT40 z<n-evPLUQ6NtNwsD{~guauUM#cFQB)g?U|_addtk{#wl7T-$29j9uNodNN>;cBd$l z;O2P}qI%W$L)H=(tVUuibAnwnA2B1u)}47d^jj{ZnV`LZ=bI>5l`_NPe+=sJ^)2=O zMU9<n+EXGAgkI4hA>)MtmPGBDEO<Y=-K+2hE{HIenR%bKZSh`R_EUKM`C#FqzK*Nk zLeAOB@x6d^EI)dJ^nD(NI6zD)wEF{<If))7FFn!vEsuK3m6n@@n_HgdoWYT2BS)iV z+*;I${4xA5ExPMVip!&{2AW%nbnuVyV7oMMaIZ4sVkqYgHm9orfjCxuPPpl;8|~;} zk*7Ot@aPNlxv=SwsG`qX(|?4)m>&4GIwh=r|I10aam(Wu@58=Hlnq&W`d=-4egx`O zO6N-68b35IY{lz$Ew21i^I>{c|G+bq5}kSryqq3#i1TR}M{w)o@82ZAUM|OqrYWC) zXKzwP*KC<vtzPP73+9eOKNSC=71@eD{K>dd#~o$o?;xw;!z}o+_L4|*l`SNqqxO5A z;8d5i0EVJJ3Aw20owezzW3{@K`l(c3`o;aSGF=yoUAfYRns40?==F)lPZQggTb~zf zwYQz<D=>LtW0=FUWiB^gH!$e*H0Vq3#-%V$wH|yyDFaTM8(faOpOXZ*rDpV;j<8St z^2~J4lCmU4MsZ=PN$nXexxhgi5EqkTM-547v~}~rMJrFDl_yJ1FmlAvO>9<ab4y1; zwa!-IzrKfmf1U9kW9e5G80_7@!tATDV0Cz?06tiQ-$#ygh|Mm8mrHS*Z+T_=fZe1H zpxPaeG*h<iwHR1q9j>d>7aG^@7f-^M5~>Ch7S9_+ADFIn6mvYfkkHdHs`oxUylB?P z%+z(c;kN{*n-_odIGVv2p=ag{+nSTE7<P=Z8lHcL#RY*X&9|;j($Doyd?KE4ZQ6OI zfYcrN>unLwFq6LwJeScmMBo-8TzmaE*FUq`y1!4i65s846U}c_O>@)eLHzm%#;w?o zBk5@?TUZf%Kec0C=mij{nzcRi2@?Q9R|7rW?TJ?$-y#s+7i~2}1<fDl<{DZF@LC}G zI70hJ1xDxXo@Q>Nfs?rCf-{mIdaK}~ge0((1*mQYA{A#5-7|2xRa0wd*z9l`YN{=o z;ab(?dovSBD>Bd&1Os=CJRFumjvU6{zw7v1v~1%wwG-0UP2@9${^9O>Z!dcKbZw-* ziYwXBqsj0^>7f+Pxxo8r-A3QF3-HER@y9_TZS0mN49q8|tisDEv)OU0>+)krKEcp- z6+%tVAT)j7=0oi#1f^PYb))0$M*;3{wtqA*4Y!v@e}CzF<6<(iB0B;a7aYclg_C5) zR@*t2$quiV+s!TDi-A3(TlrClBDzz87^;$2h{?fB13m8pK6Jljg&lQ?+t=e8rslh; zZmf9*5(`U0Fl(HzZU2*B{-J94jbB!MF?7Xf&f3B9$I~fw{FzG1bzL)#D4iRN`&wx8 zvrsqoma=!dh(FNcVe?hWIhH)sVO{ws1lHug-0J-9TM3%eFp~on40urh)W|@~{^k#{ z<-~|u=^E<!TzQo>otLR*`CW14&1Srv(~u(L?x{Hxo3fB63hs`VHn~6GQFY+1(O2y~ zd^>d#SfgU_Jf~u_PBFD)`7rg@=*jsF=VuEyi;K2kk>-P~;`zJD$Ve@tfb1>%w+dy` zg~_z)mG#%>8yiUddrxn_E@>Da$0HWO8f0db^tM+RMH*P>$;vkqTEuzz+QZe&-EwEK zjJ37PrRhnd^DS_*<KLRHPh1#L!q}Kp+uHX$$)B#7o<BKUeqVpxMXfxum?CgA>>J9y zQ^oDb_=BQG2K=7!D1QDH4!fN}9i>zjW)6YLL#a+k+KG$*+VUFuU3HY{d+%O=r}XO` zpT*F4+T|J+YhZS((@vmG{G@yZI^bl!A$LSWwNZ7-A)9y<Nn(nGEhD3y4#lc7o#pKF zj8Bcax((--7gV?HV4eEoEfGv~4={#+@##H7-CgwGHO;u**fqJ%{HoTj=X63imp^9^ z=ic+&jyhqnFu#jWQ^;dEkPU+sWXjqD?(EL+kX3!wpb=|r;=9{f6Cb=&^f*F`?<d*N z2_^0t*3J?hvcl`zR-(uVRJbWYZZCYoPSm>2LGjcdEJ|gDy^U#o*B++!4{``?SNGRO z)##1S?w+_A);s<M-~R19<eG=pZYSC+d?)gC?dhc?ZQXYki{5(uxCqkyK%N7?$qIa0 zp?0Tg4qdF})vxc2Zj<^a{zc6y6_1<$yS|t2da2;TXvxU?h6l@u&yDJ_P%<M@f&kjy zK(c3(7<|;TS%M;^{GwVhslPe?Qv_WqSA>CNWUk}6i_vA2o_YB#)P7vtaO+b6?FkQB z|4CsT-TwQDOK+Xe=(1OcYVfvW;&h@0sN54A-q|$mb2jg{w1V1u?RXvd9snnh92{)> z6>Q?+wp@SGlp5#rKntT&3u5rRKEFL?eOA@v6YSjYnN!)|xZKx)EkQ?}(eL<x&rS@o z$DdQmTaeO&4#pY_7%s+|F51b=tE6y_h_S5ZvI+ChCy((jiSLV_eyZZxj2@sTNe)}C zn8ewUt$rH|Kl_7S#v7d)eciu@UP;K*S+|wN98SiomD_gCEV|SbU4OcOiw~jL09c0C z@;7-+&&N$u|0Je#z1x)Wrh9zkVe?N@`Yu^*zG1&-a?;MwoyKtfWA@1N7!{sAM&E@% z0yWTWc=tv7nFl|B>ZPhEEEddodQ*MYAF^Y2=u0YtcHcZk@0w$q(%M#{NYfwZzoAC9 z6K=Kk4r+z03o1_5i<zj?tjm@`l|Ar@w(V!r35em&7ec2QSYZ>1DL0L&F+cPx>#aU} zM?z9zr)QPn94}9n7wlv!wyCMgb<?@vDUYgp#PU(71u5vTZzmp=MV}$&T()O+#2?bW zV-Pms@W{tc_<KYX<N*qj*6&~OI|IKV?GrW*sNr^Yyo0J4ZM_2>d8^K+CBYD-3?ku6 zGI#RYjeIOBkaqHP>Hnb>6U}0gDIqn9Hqc#nY~{!Ruh+pz?S;|u?0R6kgPVVui+4?} zm!xlv!4Rybs{b+(y>{s4I;rKW&9$e$-7@WoZ+DOGcTktyPN`}6S<JbjyM%hdBy4Zz zFK?OcudGl)4{sK;IFib@`qcrB56gs6#V$cV$&P=$e8IMZE_cJLTHnHs;1<GaE#CC% zHdcOo3DYmtwpD^Id1Ph{QgN=Yk<BENIOZ(UdLP%k6xZ+@A(k;{ZraNLWjy$?P8u3A zkFjvGvGQ_S9bp;-_r=PgIMzvHV^ns}_B(kgvyMSQS98r-l+gAG&Nu@Yqn~MS)`6#s zg^!!fs#3AxY)FM-|JQ)lE-I9{u_boM9%cM!7L|GQX|w7IS4f@C7OT4ZqfxqBGGAg_ zX1FcFs}RQ(6RXTi*Bz@muzX)2Yzd@kN(zrVQ%OKRj)~t~7)-2wV07E9UIyjWs!c9K zq}K>4ysxroU`ppw?Tb-mkRbm|1Tp0%*b)$VhIIUH>7x*7GO9>Jta^SLDH2qcw4GR! zezJvDnd+bN3i)r%10%4LyWY;aV!LX=c9luW<mpW}-b($L8RG%$mhjcS(IOTk)$8sh z){5}KO6RU4N0!FHm}zYfytVc`)jy;DfFX>-)(*Bkk)r6k`H4i5wzK~Y`WMRsML7OC zi<RgW|H1PKUFOC2)4)?>;Y7&^5|Gi?pN(B*US5%TZ@}-4=TM+yztqh6yTWy^*Y2_Q z>#6^~Z$E=SL-6yT&Ox&koVsk<KXy(nUT&B4Dvby6{+Hmj*$XTpI{UImQs*D&$J9pv zO3zF+5cS-OZ*~}b&v-Y<$#Ao92lKRDtk4I6(=HCm4i6*S+qd?^?4Hbq&y4uqJjkrg z;wZQCnr{|&huWT`)W2U(66O7yQo-739y>FP>f7}hC~ck5%KP_om|M#ju&Yxt?!F4Y zeK+5XQrOq2O(&`gNxK<7rPp+%;SyTVMZSX%FKsZiT*;0nJ@q=xwE{HmFury{9^a?# zmsfJ<H!p7*;J)iU4Qk5n%?Y+PHg4OU)4j<}jfUvDG3(lGX?k2v^{aJC1_|uVKm=<A z7JCOb-yfR#di>7hlr`TzAV7RykfT=5QfHQA`ASlFIlIomz$ZPqDf@efATvg}EE(%h zOpMOUD=y>VHS(&_oHkfiA`<0w_e+P!tNEO_v_kd<S0BM8A`TL3t3k3sgANI>LF)Un zq;~r@w5;jM1%nx{&hIS0Tt%Eg&~y6r-pgq5dCZ({;|v~-NV)$hHgN!qxZCe8=qy-^ z_3%ZsAW7r|GBaK420M^@Z;z+v-RFdlwH242FbI|Cl|jpX@n-sY*sS)XyJwkZ#{?{E zQm1~KcRS9uFem-y&YjK`<#v#Z6C-XS$mDsKfckt-c8yv5yUg!ENN|N<U$682um1E% zs>!mf3n>qqP18dKM?s-b26yYVg&Vb)s6qMxcVE&F*TLBci?(HDXXm)W7lG)rIlb_M z3ojO<E89<qBoV54PX`MuH2LJ?_KsTnMbrSpx7X)Q794APK5SiUs0*KNew3kn=w7-H zV|83*K)%(*<%!JJ`<;cS_jL9dL{4UV22PyxZ0v5!bq#;Bj6M2KmplVpV2gV7jOP@2 z^%vr|oeb{f)o*N_`)!Y>%Hnx#VNFjOD#J2Jb>NK{w_LpJ9{7sdB8b3l-Q(}4cM)7S z;`$*Kv$$n_DRc`gDmSP$jm5?T2|vcV=*DedE-g(nHXIx_i@EKNxb=)H?U*+NFs?Av z?`024UJOB+-LHp+Q4#gmANZCR)xI3Xnfvx}6)b9#ooF-{`8?d}3;)w(=h*C#-VmzP z=sWRio>*r*kM^UZx>O>_#sytdT6(g*&ewEty(t8~bSt)rv<tp`ICvCTUw?DfyywGs zK2Gr0>-zoj^7|{P6tWs~#vdRu=@r_JVZR2B1UF{k+pu5HY|^NO5i@CoU!+Qc9Q*pU zD1SG)<`_=v>ovLlJ?@=9H=-=d^2*jITT&C3Z^4PiD$n;8EqqVL+6TRD|F%>R9M#7w z#t|3@62@NMd%f^F`s798dD%kHt|i#n=Xq=lD$c%$t*;b=TJ*em!y3vH<@d+n1#G6l zb2o$P?s^LYJ|E3c(a#+^@CJ)l*)I)yF<eZQ(Sa_;oG!wP@EU4gWeUq)<oFDYbchu; zo9|p1N6F9lKc42u!LS9x9UG?IYDZx;*5cdgB7=<{2jhG<f7h1k&-rW@1pq4%C<f2J zlceD5gF&?chChRYvC3~AFq+C*X<qVutPB<XF5vY0GCVL+#u8MJ@Kv9#SIHVo6;mAu zX~JxMa25Gw*yQn7@6P1nkjSWLw?uy#_+XHz5`LvB>9EnHc0JOx%y=nl``MZyge$q# zC^5nA(Ti}vM-$E^{GlY7wvW!<+=vPX1?fx2ta9rZ$tH#as#dJ~DMtsRi_!NvO5CPu zKITJU+0D!@Vw|Poe+3*DtVY|<akbif=y1A2z+h1@X!x0`Y|dEf@f27VTa^vSz;;0+ zf1Ohas$wcyAWrrE^mN@-HysjOm*>58k|E$bwn49hYT=(b-<sM};3jC&-Tjd6Qn^0| zogKB!7d2E(H+LYvlS4P%-A~b6cm*-DR~2f0$MCy_+hxuyTAmnX2r=k}qsVfOp8%FF z#`g69VK(yXDi^snUVT%29w%nH^_t(SC9B@hz@UB~O*?;AJAbz*;#;80W22?f*SGWM zY*-$ATs-)%8ElS?T|0brxwvMI$~#juvJ5+W@k4%%Y)tj6_5yu~{`|Wc$t!bA&0oKT zHTQM~*BV_OB{y9$-d!bjyeq5LQ*r5ASVCgY#LWr;_+avOv6b~qGNb<~>H?2lS}pwZ z0pwoAUIEf|hN(>+`r|3N57_w<Nnr_;)A#Lj)-A2cduNyFx4PZz_jkPcyiu;S#Ne$! z&0d$xndEJiQQcj*+TB{$%C*MVZpMC^k}PJQD-Lq_R<3q@gI`IxAMVPBE`bi7zVhwy zj1IS^vvHyMi{!iAfy<Ms{X=WVSC3aBAVjG7yYSGgtKGZhu_iCZ-Zi3}6n+V7SyfgV zyL{)CvCxlR+_K@^VzPiEd>W!3QJL~MFdMOkjn2@sEAwLKqupe_=7WN}>$U0iyYlgp zorkys$Qj8!@!PJ!yNSgs@P!R4;3_r*Mf70lj{7QS^`1hy)+@c63*`vFk<91xPIW;D zS2ir2qzoeA-n`@TC;D>YvZto``mkQackj-yxI`ZwDbmh8gY;EnXiZ$bL8<xz;j~`Z z#dH7r-~YExtrKr0vu!~28(m<p3SiE%m`whpQ?I`Y#`}xK09NO9aX1BW<F28wF<NMj zu7ykCGFxY;kh1>$mT>z5%<@@p_#@TW1hj+Rb#O6ngBsp6Q%ZW8m?nDKKzCOEk9z6k z`DZ}E)9)|6mjVZG_ZYnv;?-iQP-`Y_1M?V9YO;aEWsl!K7*>}NX{wXUPa`~=D{?R3 zhz;DDVN<6JUKzc#!Li;i;9-!Mm{?-}Q+cZ7UrjM!vVkn7mb06k@MSXZ>!O0pEAdcL z2EW{K>q7@ZpLT8P<hAS$UMk;mHBB{0*KY%=zi^c-wo%M*imV`1Z|T%Cm8lEw{U{Nq zk{(yG5^XP4di2XIXxj`b@b%f)`@!2baKri-e9+A4qT96qugSd+xtw0<>l3l1(d;a_ zSw@XgXBdZn4xD1^ZX0RMx;Tx5j2^jn4^M0**1p8pOkUvNE~x1-zCJm&Py-z}8Kvlm z-oE)W?muZHPRaS=mfwfQkO2gCxG=7)`^F%`&+FcIUVlAx9S;{5<;`2=+BI+d=Rs6< z@IGw`9K5~+&-fh{S(t3dIr#F%(&#2Qj{caAgS^=W^q7$g+DC0eJ*^>D?S8-KJ|*wk zre7E?tfR~+?Z@rhmU}QKJ)IO_<9pYHH-Vhs)80_V>*F%DKKegpxTvUSRAD$zKTa-j zj9q}b5Je)GT+(RSj2ciBPbn7-gAj2{s&s{@>-p5cM6gKlYF_cID%>waWZ9yi0lN6u zxn$Jp!(c!d@112`mF+)xcbtu?3>f?;B)6^UDQoJkqXmf5#rQ6;;6L%M?ZU(9U3G*K z45S;)&X|C8G3LoVuMo3a<-o4fLwRXyo^75Kw&*8vMDk>G-k;4K(~R)^7lN#FMFpL% z7ZwX1)z1j4{w?>TxP1lC{6I_nQw#STbJ@@ATbKA-*iX?^8Rst_u@wI+$wvG0h42Cs ziLW}3KNC4s5fxCboq|WK7TEv^@FvT*{sZQ!)A@%f;BaPv<rHF;s*~}r(-_GK+gCa! zpShdu_vcWk&H^(3ukZs2zt2#|`2d*$(1O=(VM;X-&&J#Ap;N;XO^)pbo+}asN%n-` zSN-x&zD{@g_i`VLiISfMVy)2F;+E;D6!u!`7r$WR-i8buPITsCa(!-Q!@|LLKU1j0 zTH9=);8I3OlX2A4={0u7U5H@f3Bf;DjpS%l&DZ|M-AC_xo_gK2LRX7pTvyp~kc#Vs z^(2%}9vx!UuV*w%gG5YD#lAX2$4I#g(~1ppYoWMIY4i*}dWKZ7V%Jrdd*5;TV3YMs zd0_Ua@Uhbu?uInVzh0)Fz2_ybO#z3xOT%wTb*d!@U2G$L8<jT#zZ;^5#8}YrjL9Ln z1~7>9i7s))YM47yJ04w2pjQ7>-!&^^NCox!Z|48phzhd4?|rOIzp1FHmS@Zg+6bpz za}i=OwZQYk#?QHN5co0#S~Uvc`;|CF#HF{RRNwiGpQi1^xM7qyBW&omHK41=^})j` ze!m|4fI4}iu!bnDu5}bHnVF%x4DHuQ9@EYxSVB5gpwvyjFIiCEiyK8^Au7{dqVRyh zfIYm9?rxfz@4+osua!ldI$F+%+*jjY#k6>XK9DPT&7?Ve#V+EBT6T$FU#9q`5r4m6 z%a1w@{Nf-d$4Rxn_FFngEAfFxN+Ln|W~FV&V56m~2EH`_>hp{;%Bok!%+cth_g7qm zcXr0x(cQ|DEJk{obPXcihlY{?Mudlz7c7QPzgX6bYP^H@-iEhv_WiJ<kW>|$`Gh2X zM?FZ1Yo_Q3fJwkwa5U&LbRHTr1wH6wPw%DTG;f3=rp$JUc~#j~KiuHi{xRH=4L^|@ z<>dBcl1q;zv~ABH3QsEUI7?;HOKG{942pQ{zRj~nv@GNc1V?D)SjN%OrJ=?&h%+Wc z;6b7@@=;Ph_R72T<y5`B`d2yE4-CQ5!cYG8Vg5Oe!WYc$&O@hjLQku((*Bp@Vm3A6 zwR`RTSO)g7tIRKItqPi}ZERCY>SbaE_u1}z_NU=J#247>*hH`=-i8y_IKR+cuJd4q zk}BL&vf=H|5o7w6+G^W;+&e&)l)6vcMac2`W24_{YquSz$);-@0{v~A8BZ*)_-p!B zA3>zs7IToHTx%vBJK}an)Y>#rNFPcE<(uzQ*O%Spq~ft>vHP2e3QOM!V`-QZrc5<W zJzs+y@1hW&{E_EK4#M=k?>Fm?Ieg`Ji)ZvNM2-1{8De6jEUnOiLCD<P(_nv?3dgbu zl=qD@pHK*rV?C0BEuZZLKKfXU-d$uEbuTtmnSjMgGfIYqMohNXiOVxmwGH-_K~LiY zPZJ62ufL^$ri(Nb{v(GA0N<d}y;mQIPMU5K9vl6IAcy%e4}9r{O1XbzC@3kDlFC~` zN_0tL{vR%rXE`5^WE3V?vslbQ^ltU<&k<mcyaQL)g&}h?q~0_D)>eN_rd2y7@{6a! zCK3M|vlsWa$Ar-@A@+voMfZTD*WJSEx{K|cHZsO1R04f{)uo$-StWWK+jholwdAUq zra=G|4Sqyatbo}jQMgH`lqIoHX6fu8zG98Ql~jZ^?u`7LA26U=LYq<6u7@pcZYQho z=)OvN7Gbmu#NHC4+2_7bvGaC7EJInuyCzj23W1!^LcW|_@((V|>6^%Cst5*0=X5`? zWbAlkqnUq^JCrwH1ovkv+WQu8qOtd6gY`r`TIZo;Z9sIs+DNvt^fm=AK<g*l7U5I~ z3oJ2fhB3YI4Z7!M`MIP5chijgSJ|Q1%QOe>E>K~qP8}Ts;idKf^M9*W1$>Zx<utdr z!wM5-y0l!kG5gm)8$*m9-n^0oU!cfSb4m9y9b3foyJEeayc!;aw#~j##v^VbQLDW- znj&G*(%+PqyMdAw`L2pCLA9j<rl|?pzB3{*r&?Yulo>rcF1^2_yQm^9juo++tkeoK zaZ20@WSqlupb>l3IcN8WKV%ZFV7;HoE*hpDCNdSfWb7_}0c?J}1s?wdB#=ud@h|=O z@s8=LGRUfFjt+If5v@5RjjzhakpWXH71TfMUw>e2OX9(ozkKNT@m_JG?34n_ox7_Z zRIw5i)qbKaOpo)q@ZA`$CZpU~yra$&K?cg8F%_@Obm{vCFDDDQuhk0~wlwY*{6;6s zS5M31JwEVShYkU2;_(D(6WHp5w%}0w|0Lb*j|^dfPI>XBne>u%ElT2lN~Twu4L7ha zaxI?6$E?^$k$}Pd;=A)BZmnXM)6NM}FQOjn#_r^2`;X`(E*OHOu(`9~BC_Im{coR- z06seM_5Ks&RsD(w@(D{O2A41VyzmWP!W5<a7;wwwhXk%nf{~x<?^zA<jXZXFusxw| zPW(=<=dwe{tP%#-=mWk*JJAjkj2hZRHl_J6=EHg{eRVajq#mxuPnd^Zd=@xjDyj%3 z`2sV0XR3Wh4n))eY1(#S4wiaMkn{=)$SCzo)i19$5*taF2g6P@U=<%P6=^k|v~R$G zvb^!0wmII3@?i;)Eab4iYO4z9M6ihszpQ>HZe&<%whQg|_r5<$`EL}`FOigf%3wus z{m4<KEb`dvKP49{c?02rWkt)HdH$5SRdS8^c~xa+Xu`kY63cZY-oDX-7k5@~<*&V} z8uRoFOlhS^t?N`rh9Jhedf}UByPv6krt>>|UoAn^AMk66Wg5=;z{_IbIcF!n=5pR~ z>K1@T)(-2;;`?!Yvjo78nGTiORW9)*ys~RQZk~ma4D+S;e|ON_JqK}m<XidY`jUvo zgpC_PU&;1;_A1tjO8KayFAIm?DD`u6zU4*l-@Whr%<n_Zg?*d#WsYBkuxD1j)2)u5 zx@0k{TRmB!)`wHJ<8S=94KHQuCsR0v?|hu&+$;Z2<*41-9JI`4ZS5Fk<Wg1B*t<W; z3O)OVJr*$-oTfcvtg7fyJ-3aSglo=(ahV<T2=7~mb>K&gLDNv+<h;9Rz++Any8DcY zv(IN|Lp<YCvM=Qw8)Nj7yQYU(+E{@$E#U;<i1Yi70A(~uN(CU>7kdd5(T!>Tnqt6J zJcwBTaz?P)$j`QR&OBByoj!3fMK6}@T{@MeW}hnywY+WredOia2*P9<0n;lfg$R?x zQR*L-6@-HLu`<U!zI<V#iZ`^M%BCOE^S$}Wpj1fJtEkC4<Q@JEQt=+~utvm(eIt%y za;)Q!c%%4&2?%~61Of{inXw`$()Gu4+y$C3|H)oLpEe|`@TQxEp6x9Iigq1S`DW_4 zu*zdpEN#6%oX8uf`Mg~9arx07v(wqUkEau-q!=hdn^wziVK*!bx~wP&JhQJX;jouE zA90gf<)dDqcT~U26%$m*G^tnv+|UXeSyJg7rA0}d0<r~Q2P&!Ka>)FSwPeb7TPn1{ zQRxY|0+6&6&(VA%y};wQTrYAvSrx>ab^!ny;a{@Ta9_?2YNZ$l1!Y7300^}&ou*m@ zgrLNVE+E2WjU21^oZ*lPJs!<bT@_F~k_lsgSe9Ao)Z$US1{~!ZH`%eBlCMgmj@YJ8 zn3L2@;qRvzjz}W@U%Lr?s-N3R3t*fQLH(@3c5w7{*$lSd9Kc!hTQ(2zzI9h<O!Tf! z(WYZ|Fp*q4%2uHt#r8p~SJ&I`pLiE5dHzX&6JQ>+eLL2m9R=kJdE13HE9w&G+QsMv z9KVZ(--D3RWg!J12h_3!n*ekek6%I*R_88tF?DI$b-DSG8F~58b2PM9U9kn2*zNjU z2K5<#%YyNT{^A{-9-T&;4->+FE<)W=kN72EYU#T&WdvoQan;*8{Y&jP^%mg;kDDgW z+hVs~(Ppm$%W0GbSBKh4-)zFKbLli(ei4$3*^;^R4+cG0K>)AR>Fsc5D7Qvp@6?X1 zxyW6|)T-i*&JrAp0D7yO+qo$SfkHz{wr<}y|E<zX7Fbkxlg*BV-b3j*6f$hHw!5(N zxn<M?-h~BILEZ)B=;(4+ps}4TtZLnkyJ8Xu)S+?48@e!#<gDF#;Ps}kbWL8ZAyjnp zlR%5S3UxVYy3}Rj3LnJ&bNU9pRWZwgk06?&s!SjQEAC_fL<Av<^s#mmbw62z3Z^_d zfJK-#icd+m$)x<^{q!5p5ym-AH0AdUn%-yWml17#(z@e3Kz|;PDcpgd^mZq`uvgG> zo;^+feB0*%(Tim{2dLv$hx!OWVm0We_DIs$M@42~!km3~AMaP`55|rxa96yc%94n; zi=Mns9@9_eL`knyBHz#wmU6bjm?(_+$;qQ7il|?&fE>Uw$wAdx5VOl+*9208U`PZC zGu${?@^)(e(SHUu0sDln!HPpO$87%+w<wb*&vU!60MYm7!c)=m)?(;kutc#3&FR1Z z@73JlORwVU-mULP7lWZk@AW-?(o5@UqX1SFZ#NWcbdq6ad=Y8)?yV`-znUw(WF5(h zTZ=42bZ7y>@n_Z0@@y4GZ@6Pi?}hu`ho%e4!o%Gs*4Y&0)GKo5LiXFap4T;6=1BIp zV+uKkfD;76n9tAT4E1Qku|&CppbqNqPLVnPrW1H`E?PA8{izGPP<iKLJ-l%84i3ku zjUbArn6-8)ss~e)A4%f8+;xLMPlS^Mf=J(1+N-M)eV-=I;k0jj%fLcO`341{wp^Ac zuN<N>Rj1XJw`^q0XMB<=layOGleB|#ux#(6J-!uY9eS1RnB7&Kld>zEyUP#4{cpEL zj=N_E@5lcat)LPWU0%~q(R?2@JBPLLUyrqluwo^f-eBWKCS%Mjua}Ki`i&(l!vOuF z%9?-=ue`y8JwrK1pHgZBlkq|eK-2E0Uf2xO!Lj76V%QFyQtCTpN_ow;2Kot%OPc&C z1nB}opJ>V*3(!anLVR&JANc*4L7Eo?@E+Pxrs#cOH_rl~tXdE%`89Y5-!2vbjIKmD zl(vJCkHpL_JntzENXC2z>Ahe<3(%2fQPYchju?s%m7s(sct4*}T|*}L^H9nM&6DNc zyLWf2C@b}0t(`*2`SVPQVKuQ2cgPs7faF1<y-$L^^h!Pn4_#3Kh_d<|IAnxeILQ8W z6_*tM4z1LTO$t%KmkcdQ$10{0d@phSV}D`8+o%8LMA&SOhUn(!SSc{w9>;#q8?u4& zgDqMzC6a*%Dq0d(Pbc_nVJ(#>>oOUoJc^9SNy6&yL33O|i`o=G_19*1gR3c7*D3Za zbpuE*@S?&@(AucVNw}X4bXe=XJdK<@L}}#u#e_C~V9&@#^7<zX5DE-DXPz05$S+s< zY*m5Z4@Z_)yqfm+5mu~Rb#&s^oO*B6!kb^aq8!0Pc+&PVd+?=P8b~VCv6PHM(U;<f zT67Lh(nj(KCy5Zjc)^rXwJ-Yx#~9=yff~66{7;KTj$2ko!^l%vzxm=*(fI!jG7t{` z_Z#O_7G4WsD~$Mi=5#ZhuP5e#FoJ0S>s9RSQrp2*GyiM1g;f0}QCvGCdeNh3p4pT= z>#ZPqCA1L?K1X6Vp2d2-oclo8f34MXz9Hy?Uib#rtQKaRN3oDjaNu5(;?1Mg_-0!w zglSWto6Eff&!hn+LtwfrSRm<VE`^+8RATv5I9%cO8?8skRsl&^&eAhtfF8WpojRRp z3Ar+2c=;^15%GG2uY=Ty14US-q|}f5yUBA(`%LBWD9&jLa%7D5U<4(%L-lExcRcBy zE27C!(=_)qv`2+jD2pc~A;3(NJAIzve}8cRAUnK50D+aHCA#*M%qF=pVZ{S6Zk)5c z-<aFIw3unjE5f_G>)Sa&4%gWQw~OItJ`2sM;*Lw}kq`hXWe?9?aDX#ohD%mlN@Ria z#(Xo7GX1>hH=d1OVeIn{7F>wi{MA(j+Lr2?(|3<;-WfgDrFT((Jc`1vk#7UyNAkl& zvGqZmL#B@>U>&Ev9_+wUWWZ=L`krRODt;fhNw63BT$lFe6B{~1=iU_h@bn-CW@J?0 zbDC(vj-6&CmJ4*h^3(hPRb9#JD4&Kfr(7sElB5Pw2KO;9?db3g9f#OG)Oj$n!aOs% z4;M&OH9e3oK|J|277zLawi&P-4!uhGp21C_q2>F5Q@|{@G=`9i#X2Fg2LK`dj}3+f zGtkn$zzVs(y1JVDg4~4t-}9k&?_e_Ih#SO%TAO>G4oRN*{mn#y5AO`z7sBtHB-6n| zJ0a`WqIe3IHA%T{672Gf&z)I5Uk<sJ*dEAh`mj+l>abx!cVQVK(c^oeuPHt7NfkYX zQeq4?{jrXHL*V<{-4Ctnk%;ym-J**tF{TJ|tRR;CCHME8s0Qui;2!)DfTg!?A*1dI zh7s#g?<8ke>|FJUd;LRSU1(_tnB2-SA=1JjQ#V5?|6~sT^Gty0D0Q}M`%A#7pwUZ0 z;L8w_>_29bA7D4hKAK`sIK`2GvwkcrqFTyw)^*ezX&(6|W4)#H`J;~nL?ylVpL;<c zrhb`na2KBeBt}9@AN!ec?dHWy*(a>j;`~2pDJjXf;}z^3-LC`&D$5NFF`t|E+BrWi z$){rxdqZ(c4ed311H)J7f|+@~g<O8@H}})%jGk7;($ck0)-G!v4850`VuUDwqi-dT zYTc%IrcP`lt)>wLYq&Oaso*mHOAXl@Zd+nyrk_6i{U6d#HJ+f?Wx;QX--9&@9N4T5 z*q%qOnA|f6ak-NG;ywUU2S}QKGdXc4E@wMIMdhLM%Z8KQwmF4-3|5h=*pej`N><c_ zs@NhI9Nck;pgAh{6)Vh?bu6Ky@;0=mFGHA0`6$d}ZlbAmp+98ot(XlMFKv8;!;Xzr zPBckBj;l#IHt>fWF9xHLJMZ~n0B<wW8OO_WD<2sg_U`1adPW3~7%5D~03@$#IGwMj zBTMU-ZCmyq*tc{RqX&Y3Jy>F6YzjBQhU;BV>g~&*u<d&8-9l{W@_p=O;N4H|&ks@^ zrP4-=UETHwdO5%nONF0#n}`wZIXrWB#6F@LF{vibL%?DA&t|nWtlL=%lOHpRVyw7S zgx*%dSnP~LT#=noYM4(M`*|K7w7`Vw6orv8aH@cEY9`e!;6wp`;-~7P`+Dbf?F2Y! z{;?35opQ_N2tC|qazrn}J_BLTKRy#m9tN^nHa$r13&NzlK1ccO@QLW-uRp9P7r^=A zAS;kXfH`NT4($}gR8Y%>Pt&G=D*Za8jH8)hQiQDEV{u|4LgfLmPbo=`+wUWfH7zz0 zqqCFQwq;0SO%7zBVo%jrTt-x@6U$^b?3LrxsoRWH3MmFEZvWk(aBb1`HUo00gZ^np zNgvunKAhxRbOB}SCRsQik|qoM4>`*fjG94m-U0=HJ=o0O;)!RAsM3GuEtJqN_+@(~ zmNXGC{4p%6)SA$m-cF~5%J44ugHBf5{ozMQw|B?%$18@=S1nrUVO_s9OyN(Z|6r^> z*<h{jQTM#cB89BKM8O{u30%?CL>KEZ$>}yLmt3i3m~rb0?~p%E$B&J4{bR7_Dh^}5 zZ$Df%+B!AEnZzo+t0%o#yGL!bO?4tvelpKdC3TfLX7P-upqHK+?)paqz@kWIsBX|A zYI!fp1i2%R6}f3ELQ<b#r^liS^9>xrZk>=u+XB2juC3Gl#s80~^9+Y`Yu|nlAt6MG z5@n)9i84WqJ`$ou^h7Vw+vw3-bfR}6OtgsTZ4iv!iQap!!{~!y-pStk`5*5$hr<W= zy4Ss~vd;5&eXrJYT(??l+Z&&HwIgzFI1_{aR$pb6FjLT37a9llB&$w7_nF(PaiXt# z^_c~44Zp15UFvM;Im*btPGb5k=C!KGsQeSWBn<=g%mj{ZEed)82^u_<k$hO&zlJGk zJdBit0AH)D+yh8~zHzig|KH!oT!_~>2Hnl-#$B>Bn6`Is*muq!Fr3r3JWPU3yEWXm z+@sx;jz9D|U5K6Hi^}iVzpI^UH)f<nTuwsw;Ed08UJe_J-m^6`2YZj(!=CSDaBWE| z$rp^-Pugrm>z2S6Q8=k1-+UCW6?O>+1s|o*JdrA$LE?Hp-Q#>Sr2nQ)GTwBW3O~zM z9OR}*H$`{$_WqeXwMACV?15}Ptck?U?!-m)O3})PwUodNlf4X2ySAE>d?Ia<952kD z!YR$X<d~PRnoD(2zwp!U5W-{hK#&O?S7=`bqdQXq#H7EV_K2XD_k!RZ08)N78;kSG z(FHO}mlaY)<eTV)H{z^HNA5s-TPS}|nQxTjM<QfhwZe63$85%b<xhCI+9qEzz8hxx z9fd<z;vYUN<F&T^%!_pp5btF!{fWF(03DY`n&b!#37vM%W59`}_IdeBjBX-x!WKKH ztkx#^>R>k7qNy?YsO^H5WHTVTX2^m>y%t<>9~Rzd6GnZyq26-Jck^Zhk>nmeo?gMK zEthIoq{j&~=voWz5BtxaEZrVNkx-wm@Yf|Wdd`da8t}I<!ihyHa2pyYKGddA{+XKb z5Ni;LXsT)IEY<2Oj-od7sQXOer<9~3|E9G_0CI*5*xFi=9xEg_Tp&x8&L+(;OnQUq zSgm+Us9iKMYoOcUbbd9+CE3P>hkAMk;nq-52}eyvZ}bD(u6+rp9frfY<PQa6;*TEP zTKhh9%`T$~SU+ekL**yc=_fvu7@i6;Z5gT<EZLwFa`@((-KeKa-W~|`&D3>uznRS+ zGb)?ndba(66k&}S7%gkQx#+g1h>iuRU$Gc-k6v*pLK<7TFRF@1ekM((@@5(8{YF;O zP$@So6gzMmdD)qs9q$#li&`nJjkKBSG0tYufP+qH0SdXT8()2CVh;+wCD@Xd2Vs&P z@*n}IH9m@Er?DBsW;fT3E4rnUDYwbX?{_>pHJchMsy`jc8QBThd>A_MqV*dHz7?nP zC8XU&K47$$21u1bUWLj?ke>>7#_l95r)n_x%hLi^J)b(yhGN><o;eP9hzMK2gkV}j zaCno`(L+^^k7mE<xEz|w8(hzb_bNzYSiA~pRL$n|=wZLDfdKtjJ;Sz&5BwDyq^GUS z8>3wuu&_bp$H^?>7RxRL^$p$|$5*qqOV%}9V&CbXVB1YTl0Ao#ZpT&W^V6mo`G^-1 zDu3^4W5j5`4KGhQKz-Kzuv`uChWf@Xf0A!Y->`NL;e%JWOKU{J(e|l!lXQ@V88d`o zs>&#GmmUB_44uvv6JRWnU*G7T5Z12j%8g@r1GntPGY`(ry|kG*#ZiT|Ns4sV$%|bC z%Jm<K+6-$aY*I>r27Z^xW0I&fBCW-%dyP}>b$p*e(V9*3h)=U)8YkV6m#gwaCzZ>w zRSc!1EMdc<CKD0X?ZbZG%0n=7>!3Eygm-kaGKg?hwiI&y7laFLx#|l|o|~t&n1wlq zo8?${_eqD(5pRPdg_7S|n>(AFYgfGB+p!F4#D0YY%!>ug^i+BzZ_@;%ruvJrKUKrF zl{g~1S~e})v6)W-vSKB-U9?2j*Y<KYV@dLQ^TfaU)6KxeGDrCB7rbcATv#MY?wU)O zbI6EV%2Cxey|Pt}G+X>Syz{kZ!XMd$rX;nd66Hv3dvgP{n|6ai5u(_z3Dq@qyFEK| zh;ERzqocMTzdaZAu<Pv_MRf!u)~|NdQJc9e@2`=ucgw`umG#4d`vwDtMLWkc@Z<G@ z`$iv-Pqv$ey6QB{aFmr9dSB{k4f)^1!ZiQf%8QXKqpStFup)CFO1UkP^<&3@Q~uZY zltrB&D;qsa#{+>@T0Pq3JJwMhfqts3qEfCYsbNx8)b*YL7&CDZUUb?Hh-;#+uhTXa ze%u{71;wnn75$>JUp5!mFeeH__Uyd;we>0~jdraIJI7-!)^~rbIgwTmRYIgy8WE$d zgl(X-I}wZoL?|*rO|fPMsQCrGM312tf(KUL)bEov{Z|c``9K+nWZU=XnzyP!?ny)1 zhAP@SD-HsDO8<xsMk~`{C+K`j!`y#7G=;yJYQ}B3xcgF95(@I)l83SQ$6_k&gR}Zi z3y#{)*vh6LLR>=FoBZP|G0Ce$m()LKnW~wegcQ*u@fGzHa)+2{ider>2krrY7Y7op zmOXm)Sy3vX9LQQQ9h&AVJ#a&`GnMj*``Wg)W<$0OzNSx>wKi#Q?tOXOId!`lJ(Y!7 zSU8>}H{@%5NKADO^+0EbL2qhUx*7f4AfJw34Vli^YhirTUSGVHJ1jUbr7J4OSnMM& z6}||j(YNL+B!Myp7bfyuBt`u<=lmT{cK3#A^^{H+g}%jC?BIo|h~M^V#QLmG{V0e9 z6S_=@|7o!%So4kEN}j%AGe5?cTMNOa6J#&!$KxMGoC*IHIUwgft9de!d4|=5!ch|^ zW&S%*(B4J@?0bHX*(S+6<}^ai?||r<1dPu1aq@vro%rYh@;LNiC_dvkcP5R?PEF&J z*By(`CE@C+#tWKu-iXbeLj#HH8vmw><4Mv)ILUkZ49QB&Hi7>^PZJciQPGQ4A*X*I z4yjW4-9@oMRp#KNMgNTL2fbA;{=*S!8zR@i51>;a@GJPmYtUfpJ-C=9Kf=DskPB#J zsN=O#G{x(Cd7;ZAZjqxn)1-go@q+*I<(_NCAfg5s2;J~_P{GLbZ<Faj8R-Y=COx!l zK2BFDkB`T_UQ~2wAz;cXtsA<7-Bj+M{V|;aTNVw2Pogc@ttN%M@&_I4cnoe#Y8qWK zo7t}ndC^2(=%$Lp%f_2iu@N9I;Pi&(dTI~x9+s*&moa5?_UpI5B6*$4>qnI5hhoR_ z6)*Us`Pz!yuHxs}7d-2H0l}!%5B^A%l@iS=SW}bR<H$z^tJkmXeM}CJDAfK61SDjl zJbeKp^;#l`Hm;@fqi0oXbfhxmbl^U~%5?2OIb3)NpR-RZ>)WRH(Gghu@v88>&n&Vb z^d9>6Kv9GS=kO&$B`%hk-&mNiMF}ympeWhE&s@`ppH`A4W8UA#%;(?{Jy_<NdC2aL z7`JHI*#eB^hNh1o@i?I{CAI8>TS}SRZ1i)j{J`#k?e&g<BZA8M3QlwtQ<PGg&PHlQ z*vB+D>BoMh&<IX4@Cu*C;;;9qr68LOuI%^!Gq9^96$zfNuw#X_ClQuNKf?WMAawKM zjw1jE+xfJY&bkKaW-90F7eY$)uMak(75&SrU?_w|iH*d4j8l24Ctm&(qOJJn9POvk z@JOMoq2_aP16>z_z(}GOteJU5kkyvY*dsNDg#JnGj)s$iF;+dhO~5FC+7rS92>4h9 zB4vf#`Guc4HZD7{u=*~uta<Os3LWB{dpOFJ<-ex#YLD-2;iKUFyi~u;L;+9P?~eLU z%$7A>@_q*Bv#W#s?*YcP8PBkg%oFa^XYLqxY`|(D6vu>A*%zPLO!O(&R5nyL!O*K+ ztI5D*P5WE(CS5~fp1&v43JuABPQ~n<)^)7Pr)udcd8nL1j-*m?ifSf*Pe_M1<1y9W zGt513tF_K&3~{bqrM5IbGcVj+@4VJI*lBB21Sx?JBdXnw4hKJ;9EccqWu0o5wU<4j z+3&l5|5kAR1pO3ki(<swmAq?ByZw1FCaWjX+zUnbDpNU9=pGwA4QeU&f(=oqvg`SE zNCjtvLD)>U9Uzbu+Z|=K=oCEkw0YTrw41mw<s-{ocbb*gc))zNs3BFL8a)Mil=5of zk5=1@vH`tko?%Q}&Bd`sO(`B9p#QDX@N#s-(eBq~Oo)*Q3yaM8X1yZTSK3h-(6IWK zA=;*4j3RxGa4XQ`(E_<mY8e9UxNoiU=ITY#2WzSZ`j>Yf@&+rOQh49^eBDDufHdRE z6U1p>ozf)rs7$|-+l`+6V_|)BJUh7?^48Uz=Y2=3!h0+gufF_nxLqL8rQ4;xjpmD5 zDvXrP+E?W_AbNqlI-k+XvWnq{KcVh&&cj=i@!8pEfjP0gskSoD>3|4#H;eP-!t@<H z_DB|r6Zqj4Q^82`t>>Dr%6SFCQr;`eteMcy<7+4lRg9f}vF&(2){nTMm_L|7y<4*o zJ^YlURG#t+MOBqcHzOl-)}P*=FPtlC+9Ebz*S>IZpXynuA|Ud$LZ8BhFn^|7ky;Ui zHyKn4*H|>H$EAu`I72@b67=40Jt~yGSSMPmq6PNwg&vZym6L`h32l_>h?6JI()0;G zQ8@s`Ic$$X_U#Ys4J3^g;htpv5?_dTmT`@;g_|5qHc`@@Bfeol-(O6!2<=VK{5r&4 zVOg>rXM9MjC{fiIsFqW~R}o6pW?!IFG%;zP;$D_nq?uxRG3NX)S&`<eX2T%Wrp5Hq z&0celgF1S4ZcC?Rak;sA^=~%zNc>rsWY(IeXVJpW1lL3t;a({{4J~3|LvA`PHN?eo zynpO+oBqkOQ&wnJw%l<PcE~*4PkBETlC|7u!aIQ$Rq(26IO<$1RoNdgzflV}oSkW8 ze9nTr_bhQuAWVhPA6YNQ=y6<iZE-Gnhhj(#7(}GDlG@39iayo)@#r^za$f7VV{Yf0 ziY!(f3AR8!C9NtIa*;)pbW^5%gHGu_w^75@<i(QT7J+{y-0uXT+22_4yjjQPb~yVQ zT93IU^*d<6{=~>YyR>v7pi@S7`zO9+?#F;n7K`ufR*^w!HL5e9h2JfS#UA=n;0*x# zM@s1Ey@`GYLs3k7*>c(24}BSm*)n$*$1F^2R!}Qzv6z8~>#WOxj)B%|@lYb6VQIKe zAqB-95bZ%NBDG*xbEfF+EQ)s6?4@{5&GcQR$$m4h1?8sS4SrZOyzNr6&$*s|b%X1P z6#My}g5!XhOJ_(sHkIiqjP<j3!xVNCUG{o<aGE!4Dn^(tX>q+b-j`<nUS(d>fHEQK zCZuQ8%t(8&FJJIsZdTj#x~8*#>3Z~PbmwrwR<B6^b&IJ5<QQ3aBL_wn;>m$e3o8nx z*>$?Oj>W#qIiwlKG#Li9`?mj*f+dpp1Yf<9uzzr)@Fnv5SD4svD0`-B#>89m%iSxi zN3PlFCc|H!bE)ptq5J<JNtCDv9fy}Q8i(F-H@lXStyEK!Gjxag>&>OBix}(?$3g-Z zTJ`iK*!+nS918@L<8`XJ{S^LVaUzq_ejVS&B2JWAm4Li?X_z`JL+FCTKB`970b$AJ z#yeaC+q#Q2(J5-FV3w1&Fgv71m_LUwT_w8!6CcQN3(JM%W#o{=$q8m7JEXlp^hMdS z5nAevJS}O&u`z?Wwv@FQb#2IN4MYzwbLBI**PSNoejHXF`)y~m&xv-fjzjbLELKR` znF>csmX<AfG|WZA!68OYGeZ9RBU|935X@eLH={2I3dm@2c;u?UI%}zus#o3mdj_z} z5@AN}VkB*HeNPs4gMhLyLRG|9MA}S$%-LSpWA)D=LPob$n5D~F%rWVl-3@zdH``|H z{Kc?K^DVr<Z|87m08mc={JM;v+tq-l9{DI7`24%UD7+uT`jH5e)U%p*OwIr=E$<an z&Gt>SsN-he8>Nb+M%SO{dRku0?*K82dO*w(rl7LwmqEz}L4DgkJn_)~m;%#)*=oZk zgv6DdYTpXNv{qz1r9MiUC$P#(7IQR_WeDrsBpU_W6|=s5<C>Rsgo{-NHWUdNUQJ#K z-QHjtJvOfWCwE@%Ne$96Ecv6e2*4L}7vNK(W(kn%I!%ls^%Q3@U+=Aa`n0-B5zzi< zJ{jg@S|ww}z~pB<!O#1HG-n@2ZKa!--f?1g_i94X|H^x7=yndHm0MB6M(q%)Qx}mk zK?nz|UjW1|XWrTGR}7AV4u6R`{f(GnbozCd+heg6ECd%78#PKW>~M74r7J#cl%OZM z!*1#k`i%&8GVlbEY?ID&U|;2&+v*JOK1MRm?tMbqilFy?8mP62^2YT1<{tmENl~_k zcwxax<g!NIxxT%Qwle;7Fgv=D>elznRl__@+v9@131bTI+tt9#dB-kd%$n5jp>Eqn zt9@zb;0*qBy_8{<S(#&1%c^JmU^jI@-x*DOiPEA<%HU?>rLP=dVOAHeJ!^=aMKkHv zIsCcw#Z`PPy3hY)xgBu(36ue~sd=(Iwn;?!QdT?ms+B!YH{z2vvu}b5M{M_N+6a78 ziay7pt>H)>M&9ae{uvU7n>F(;_H%|)W8z6I-bT$52v1mUTP!UG)uiIPxza6pU3&p& zJoHua8>oIC#X%6wuo>BF4EW?Zt~F-ZC*@h)tk2ff#%&Rm_HI2jWVeu;8(lwSb`mnb z-`2}6r1_^=eMYB#QY}(9{hgDU*UAX#ZI{0<8g40>ZhULiFhS{u%^RU-N3nak&P86_ z^K64<6cUneWxt3hTkOE}JY<wCKA~IG(7PJeYpXl5O_aWZ6pNNI^VbzdB1g+x@E3yK zhd~I<$0jglf7+t3IV%X{nmKZkT{rB)<U;|z=?Q9Cardn~%#*<+0(6-BqpI48Yu9QB z>iu)8ilws``<*S$du=6q*&$?W=?n{#kE%2bVUC1gCDBaTGx~6dqSQC0QXm!_fGyRC zm0ywY4jjiuSrlzh?PE_E(^rm1Oh|E%AvZsey1akF?mRV8Yo^Fnv3S(Fs(7pF=~`hk z6Dj)OO99dX2WfNXR)#@s0G8A%s_eKdv5@iYYlfs7YCX(}iQwfoeUMNk7QMj|cFy4W zYo@q8505?^$ivSzMDXE(9s904u>hN$E&rXHLDUaozB&1?#F7`fFDiJc*aBJP7}3KW zsC}~Rwj#SqQ&RzgSbE>(+!r{2_6VksuFl`w3C5@7gR=Y0BH*u4A0t)f$OYh3vDHV+ z<oe&!u~1}eV=oL$`~;uZYLI9CWO{vnCCmx^@o5O#o6XI7d3{>F#QP9mnd0MMVO>L9 z2fFj^Ayb+TbbclW>S`M%mM-P=+#9(~G4xo@^4vwN<sxXl2Zdg_Y>$;BkW<BBM|vRQ zzHqM55a*?e7BMnD)dEp6MIwsg(!rHLUH@T{Im%U*y}Czho&k~~F8k{PaDuD{`Aqfm z+w1%2AOH=Wq~osz`{OA_IY^st$4yHUnYJ^>cb;q7Jvx(F#cH2W;Mt06&SRK9Gs2OJ zh`Bbf2Og<K)ygLzROzs?qhelVs)41J|95k8iz6zkYvzJgIbb`m8*j0X`}f5@TE6Bm z#Q%JOPsh2Q4kew=e;eWJz4O4^)Hd0!-K?|UgS%zS!MV)=J~j%gv42OxVO@db;?|Mm z`15Xnfr6Q2afyx2EE3&SSx%~O`K%gXGs^xTlm5q9=Z{D;W2ICkGby=Yvr1Cg9pGN2 zi5~=82gkmO3~FZl&_m7c1Jt_P6lRglV@Bx*tE&$7(kqizg-#3M%Erl<z@F(_bnv^R z9gzuW(iC(D>ic~%gIwLAet>@3WA4&<^bJZE5CrBUO>OU@5>sM~G_HOIqoI$CtrkSo zfND}*UvG1j9R1)n(4@)KMF#nJNL$=7dK=Q#@eZU#gK(Q&x%h5I&!Of=7PkEf%P5TV z^9r8RUMIvlDOtuzza$X7D19zP)rot5(irONZ<eE)_KkFd3H7*A-`Kh9#5ot`rQyk1 zP0~Xz9-AF`NjB$rMDY0YFemwLwh^WD&fk}@J8sBi_sF>55kk2jqnCi9%7Z#jm5=_v zBG=imGQiy4>x+_7RFzH1pWWzt&CUNHn?nhfBz>1GXM9p>e7dL|4fTvnwqR2;%3_T> zVuso60Tf=~kvM#LuM5EqP{SL#aD;dI_qf4Wq6i#bL^#Q#VIwNK3LhWIWl2;4f*NMb zQqf6dZpHlyutAEkM*RF9)sIgjM-?$6n@22(chl0pYVuHv5c&L>YbNF9GN}Yf35#aa zcEO|;H?F`vldkx*YX?|8F^J7VTo3(|$MywpQ`Diij%m()mLT^>q58sZlmb8AB#yxo ze(O_8>*=ss=#fPRv^^@4h!YOI2lD4l^n3AAy(7T5)$|@UDeA}u@8(TJ0DmFrGtp3R zHB*XI>>ICu(~xL3xowj$oLY7#PF=}htbqZSR{xUt895Ct2jgxqG_b4d_lTy*qp=hz zDh2DMy7A30J)K8tTVPfyx!I?AjI&>O9{gl5ff;{%V{Y}Yre}VmCnO`J-WsGnP^Fu@ z0)PHjR8ad_T#FRRrT(IJ?}`>SVOJTM%yYgu`Jkb(q4QTJ)zpf(taq)9rOs!+!;bbw zjSDa2AN%XVSExtdor?JsnnQaFXA*9tl482pTqDvQ($KZI7>@zg!4?N#g>TN<t4RDg z58{`yk5uR!6f;P1-V1ivDAmqI?|shmRjYV-Z@1{x%##XL#@IyUY~{xbYW^MeFO`B? zC3haJFtHR96Wb0lQx!Hd@+3un0ABYNxrOsinvOraeBykX9Fn*!XXjxs^Sb|(&*ha~ zr%(lB1nx?ziLv=p?^(Gje_4!LWOtYqarD2{AAwPxh?ir)Qb(nFQI(q>hPN5pwHFSR z%gWvIf#T16p3q6<0X^T}Ke*>@>7B`=<*q|<7_?%ZHbm{XuYv!(M&~r+BZq`r*iuIq z?o`N!H<8v}uf$4JtZ!CCpA1Dk%)3;CfV|JvUP%^fJg+FTuDIS{$TJEbJm}uEozn_9 z)wqp-_0lHzB#I}nbVjgUJ3*Z4AZ0gqnqSWOiRP<p3rt<iK`A8?K#c91h$$mw=<U<z zF$%iMU##V3BPyP8-YC)+-Sr$5b_zXH_#*K1Kj{%V;dV`qq&(9(`NJ>4$&f0oznE0) zWdtKq;;|O~F?Ogc7V|Y~TSX*Bw|_dx-=NM@QDTvadHxuV=qoGymFTaA3dSS)zMH2? zJ81{Hk?)VNf<EXV8ToX_PS3TCdhZ8g#T5<lzTEW}ks6TC;tFU-&O?nCQV11+PjB)E zlmOoU*pJRJySoS0!HU$xtCY$+75m7@lvwPp1MoMD=_Pd4AxSQov_aLLI9%qoCRK8@ zkatq)!>W4fsaBD{LjOF7AdAK$j}0Pcen|G)OhP{I;rE$GMyv`2y=0u!qF**uR=^#) z9pxq`kEflVb06hN0I8a!b{)BP`LJZ5;X?5o2|_+7&dun5f@rLHubk!j;)sr-Ru`p6 zj?VpOHb^a5BQC*`L1aBW9Rq{$+ya}osY`kjtfHq>t5)ZszbF->htcD?Ga(!DJJXB# zCFi)sb3UvJzy0_`OibF?r5iuXPU2fTJ*tZCfV@ZlBxY_G#yS@U#`C00?6O|E+brF! z1X$<`z}P69%=p#{u5hsmU+Y)gK<n2;s+SeYUm|!)Pd9EGKPUfW?<9;Iev6$Sp_g!a zwZd;wb`{_pSh*1_s1$n3X=*Bc89C3U54<wXg&HDat!!AYT7|Rcb2OZS4Z9}S$&JUT zu^cg3iA|C6aG1T^1F79cqxWH|VqaF;YxQv*Gp%&cNhLA`ajx?ZpmPEL?E07nnoGg` z3M|V-rf^g_U2u-!wx9iPs|R(|vgDl|MfCvkDX#}K=X!p;`|y0VPtdKZvfaxt6yMK7 zZ@xOwFQasc)fniNq~@u<5WLs19-{KmQL%hCI;Z!J9ylrem^D2@$s*xAVj5_X03M0m zcUbkHnKqf(7K2;py|D7R-&NlEfj=m(Vt9R2tAo$C*q0JEp4$J>RJym2r;v*ll3?;w zQ{n=j^Joji$_os9L#JHF@pz14-J|H1h#7z~;!VNPXNw1`dJyxnra4z9e>5=6w~+E> z{Q-QvxeSJRJSczUWnFe<c{KvdR-9+=Kx&A*Sy@h*e7v$cU6Q5KAmD<1*1E{n-k`(F z{T8?m)m<<a$Z3uM89K2L|MjOInd13_^?8<~9_tj&eFQqpe_S$x52V;MtN=C4eKtp$ z<s*3r*zkNt<J8AH0;wpZmw;?k=6FbjciNBjvhP&iGLNcIY5=MTRAo0R?PkB)b<9)G zc{tL(FL^{a2+rp*ZzSosvYm}HId7i?77_be)8`Hn#Zkugna^3!F~8*h@r=|YGM;j5 z*64ZFcawBjB_Tw_bLpKohrUJJ_}2S3#T~aqB8OodPex;>Il`64G(=usk~i`E*e%1a z0fc5@&>;JEi#P8cF(KOZ+lB`e=Tx=8+Nze@kKYr_r9p!y$tFmsu_h#S%gOtF1axoN zSwj(q|EiCisDl#kp#$QjiB1{~9A4HB_<rca9*BMk%UVDAxl{WqpF+*`GDW>z*Vw$R z5zqCklXOV`Ob5L~;XnU&H;sb&gh33!;4>@|%o8eDx*s{h{@{#`wNy}rIc|I(kLQ(_ zvhgRn^7Fa<*m&M12d3$i5IjEAn-TJ{O<R*hCWYhoZw`!o>Uj`iJIxPmAuHY8pFhJu z-b%90=QWR6FG;1gxtLE+lt#jaYD?UiekzQ!b#`DzuYy>2qTxtWa;~7_7vX7*LpR5I zs_6u0&n{mAii<#2(H_r-9$A4cO7;E~{dXG>`-QGM<A^o-1B%}76^}qdg+~72v#1bX z!Xk|{&U|A%1BPb7ri#)0-Y&KgO-(felXQ>M*jGLz9Fqu(w!;Xrp|OGl`$W)|6>u-E zs-B*{lEqb|N$SoBq#}O(n*yWLJ4Hx==iI3Rf5>cE`LJ)Y^A}nog}&YmR%H{P+0eo7 zKk382kQuhVGBt^ZS@>iSuQ)#mdJ!i<IROg4B$|7DL-4w5?dE}usI}KX1pan`T#{j5 z_O_p@z$Z$3#Zz*gd+{#B4Xxqa<`BCmYXhm1R|ej|JeY#(t9}^;WISvXXu&?0r|c^{ zZXf%v$OXIIxol-0;KTfvxb^0^D=dn9`vKg4Kl*99l_m$8lP2Q+d*FT)<J<vgdO|lM zbHUI!)eWRwsIz8?bjAtGsa-|*5!=QRud{%)ewGZz_V-w-<|qLYAoqH$bCg&E{4Ob6 zPMHb;K^=6$>>Yp(t@dgE2vEFWxKelk+>_YkoY_MC+iS%26`ilju}UOG<b;Fx=;>G9 z<H|i2$PiB34f&@B*;7~YJ6lVLwTyMicZMvXux5oLvN09NSg9HRi7eP8GEGE553Xtd z_}?_$om2QVa=F7F0tp@*dRH}ZrZm}l%`+dPLXCYa$9-D;<{dY0Zltef&zAO-B_v<R zV#|HfL+2Nw{B1+;q1<M>|0XU;h)n|9BaSr+KqTB~PT4Ad<_oI2=i66e5TzbCBbuAM ziYH==*nfxXA=tj7J1V;d$JP)XJKdY6t3S<pb>12!<HDhXYvD6<kdfN;1OJtgp1$5Y z-l~p~tD*Z%rcNg3FmAGVNi@(WSu%AmjlaZ5`(1Drc2=w6d+YWysyxG&g2Q205l-9* zu9fJUZ3v&IWO!Kzl~__d$9ULuzR4`@IgP<yfnZkoBhdpq*Nrge9l1Ti!v5=1j(f*U zp6}{17i<6TRHyt#V`i-WLIixzJjpJ}t!~)mqV})x#~r_}Wf7|z{X>eHh|m07L3c(j z*5sL(xuj#B5&gi{P0Z&@OIfqRmF|~fQrsHq5Eb<(Sm`0B4(fhjbetcQ1JuOX?w0dz zJ-KtzeOC5VTdjW}KvhSbp%s)GAzsnQ5fr@>Hf>`4y^P~|3Ma)rC-`F|aPOwY1C|z^ zkmzB-d+YjqnzeI<e-O<5JT!n-dg$?E-rDb%Ys_)g$<LzGl&T%xT6WOLL%%1oB8YN) zM8p#Xq5ENl(wJdIa`;eB&iAvs)%4^U&^RZ(0hZlLl`p}fXYsBw38YkGFw#QsOVStb z^y&U97Sz3(c>A}UA$}GKDkLC9F`qsAcYk>*hrGx|Q`9ZCK?71Jrgr2_nwlZi<gIX- z<0_uFM(W_eeb>b5xN8Fkp?#kuu$I+(?A&?75lZU%yh6V6dVN+I*!X19_ufZ}HL*1z z8?N9QQK$kVdr}Xmq=SK&L=1y%5@}$lO2_o4`WE5k8;RdzHb+<E+svt6`UkQl@}XGl z%X))L1{5xoW@T=Tm3s3^IQpR9uSp4`@6!!Jx36|zvz+zGj!`fqQ!rqlJ;_ZS!=1~b zWI<26pHl(v9{|t8y4rqo6PB>3riyqlN?V5Xlw5L*Q|&&d?z8g?{dWDa_3x1|*R=c( zDQJy1e{82xim4mhA;<D&HiX#z893EI?TH_AcnNWaB%M{#o}ZudU$^$jxcRv!3u=d% z-+aDIM{$Co@8&JmJ7mcx26rT1vGIOY?sITbcTqgu!<(RUtGL;hlcMj4auqXWk?!7; zd&^5PAff6<rlK5Z*Re_neXVvo>Og3uU_{M01@G4XO8yk4`Y|Do`Z&)?nL#B|Ig(|S ztyA-Jre%K+zXxVjhWVGmrQo}!y0_SQpAmMrz83*f*Wsso1s{LX|0fJz<Hg4Wis^D! zhFsFZGzyQeIkBa9*jf_~+;R&mZUlqczWT*x&gozsuZ9+u?wZ=UQ=3L*4-Wk)nraJ_ z*i_jgJ1ok~Xf%`Z?q@&VHAUrbQn1dX-L#>e6U2|Waf~%mWK%Vkc5W}F$Rs39Bo)HK zpRJ9+lGK)7ud(R=FbOg87P!s`rPbJs*+}4v&T%&8Q+3KSq#W!1N?LwtvI4)m<Itrl z64iDhJt3>kJqQ3rczy0tbyM(SPVMmNU`|M2d28A8j3X8FjpJUKwdfs$jH|ZUJ02J| z3Xe|ua9FV*%rdLnw@4X}A28>P?cTlocA_7uY@1lI32r;o{9jZK^snj6FjQ8Fu9_*l z537XThl*?##Qm*R7E6||g##s-Vh*<qCrulQdwEl|X8QNEX7Z1p*q)1GamPL)cFT$3 z!DIf!>|eeXNBri_em6hV^=h}>&g!GGCd3X~ie{X*?kDb(CTCbx+^LF=ankW0@S8oJ zUY*@H!_?fon6(hE;^8xIw2PolY-KyGkwK7N#CCQ@@L3a?@d_kP{_s<Mr>DRjy29>j zcgt5_%?=N@raloM^CPT%R`E_X^#|!SQ`bl^%KC=PnUU_7g^{NoN-e1bncA_Q<Cq>i z%^q;EqCWDoNr$?^lW*-9WOK)uE8euwr~V~&G|YYoFsx%^7}VPuFFOB4hAw6$2!F{p zqEq$1z(&-nh&ZX|&d8#%?DWaPPzv8}v|`tV{*cEJhrr=E*1`u)f=!ubWIh+Gt!l$k zyDB?vB8&ps{lVgRn+E91R}3DQSl>IW{>;H&t5t|gDJUL`q^sMFEByR6UIS_!u-=nS zi0T`J>06Dixcl^b9LL;Lt5}d(@!`L<IHAC|duNm}5L%*AQ4t(X3*_|Mf50=1Nn^-* z(W3UITlV*isch$$)389_tq`tHFVk0YXJ4s<Cw`o(CP}vLs`!+9NX)sD3#2oa#;EJP z>RRJ_$dGgTUhb3-K&|$U0hatH@R&^I48LOgW!|5_T>*R&;<#O7NBv>_j@7qnT7RA6 z;shx;kjs?qwmjTlETC_!fZ*9DuGVzt(H=TJbqtN)+a{6!w@_sYSjZ_zLWG3<iV>Uf zhE!>wxFeuhSmILHngPilA`~tOr0R7`Af)A2@nGrHTlAt(D%Tz)SIuHjx$1*MU|bvf z<4-AMBZm}BN)Eg4>C}&YOXP?0_=(%k_icuC_*}Mx@QEVas<7BU>4)TtYJ|4qLr*f$ z$qPS7*<HydX+BS22bAdQbue@QBR(0?q$`)<wdX9{B_+7$_G@bI)N2#Yl-=A!@MGNm zvB{W|j)^iW53>~yTs|Q+fzC9#UuS`l5ok6+8k$ECl)UpX<<w8R;#{eN@00H7O9rVj zT)u5F#y3!Unc6U?0G1$l%4fscIXszKE-ySc>!ShR1iM==mEq2($9XsFtlMUij}=^T z81O=V<${9Rhg<aq!zx$)Ef}4saiLjgI3adMMDfBwId&A7ij=zKo4>c=N2T{H@#^M3 zA8zDciW52G%<Ya(cOE|xYiJlK{UG!^-=dy&{X_$qHME5ze2E?6zM)xFv1jQ+`OM@x z>U(8?r1bY(E8E$NNMOaK6D{C#IkHf|T94>6)K@-VUDpP**U*Ub$vAMr>b?7uvp!`Y zo`%zL*u$@qoI-XieaatU&)&+S2R(lMEvOSlv~|S|TLSyrTmmhM3>Oy`w1a=;%mw7; zt1X0*J@?K+q}}(uj*$fJY%#)U#6gr4Q5_rODdV0v2{%gKaV;tRgyKX!zc!*fv6sA$ zO@u9GU%c2*FH+-d?Jp`if7eMwG$j3H^gc6#I57jhYhyS_W{xzVFYJ-QfYJ8pv~hHI z9K4dS?OKL!()vBjb|Tt*@li{|yQUG2l8f211!7O=%29coFyBv--O;ebO?EPn7cW`s zX@T9(J@EZUnbliq$L|WX${e^amhmayhPD6OVKpH1`|zNdEd;*|)@qcLpd~K$&sk4; zYfZN_B}ar$weAC(oj2d=w_V#9X&b8|i1B+a$?w)dTFLTP4*9#@$IbI*(^_)PT_TM! znBosofa#lfXoyN>w3PV@tNvA}>t%UOq8&uAm__P`vsB`GS6FpCTutxoa)5tv%Qc=S zPSJaJH|kU%yi#vQcUATkwZ+QD@#N@gUp}BlmnRKU$r!^9mZvn7V~!}4%VS91vlH>N z5nthpgL<&eaMDH(0kUPQR!FT{{k*cee`8s`)ioaG<{Rk#r<&EeXMLMp$pU)$omF+O zm||&H9*TSns{a{9c~#zPWyE5jop?UZo`7S58AUigfb>NB#M`m1kqTRUgm@+IZvN>z zP6v$d&Fy_``4<d~xH{eylMI%9*rj&L#u%GoCXtX6w#CWD(zzQZL4K`3<R8aZPL<P5 zFtLJ1ee}D;!p?iIuf8NYvMfky#O8w=Y;p*$&kKZJ@cXgr3sK#&vVl!}<)??NKJj=x zX<scvCv*+(<5AkjcIIfvY@_f@!t?+enO?pwwx%c1hc&aw3@@HM*{l40NO1Z8fo&e{ zJe63&!sM{+ru)^icIPb;-P1wru~j9R25v5%(fF^gjCB9`kQVXETH=LX{Mk6cHkwbH zu;4_0xG>1==ahZ&*XUWV`pT-i77Hw4%05<*PdPom9XCn0ZeO&n!i6Kc6UgQ~#J+8x zfTmA+OVpBx5#jXI(k3AOGPZUv*4T^I#YyvJ;2upssh3|IA`5)7fI;<TETNl5&-={j zD;?KS)2?slY_&*vzM+=ar{}?v8E4s&CXg4Q`+%L)qzG|cs6zI2=Uk;xp0;@?;6f>B zXDz?`WbG&<_V8L_sQ+A33z!LZ*(}0b^(Cjmqn2>V+i_35qGdg~=qS6+5n^Yz@$pBv zKlzHn6}o7@NT_HR`wAiW82cWI=~VkZ2J_!rdQQh(j<q5UG4*+p!Q!FS(h|yWHO6J} z`YG#LF6zbG*=Fypfz(@_CRh#gy^t|PwO+$qB=r`l`02itlV4wVA{Swc5lc?2I2*59 zd}HHMn)FVqlDHgS(`jd*7gKi_o0gx6WVm5}h|KoObPi*P2vz8}sq9+A;eNBqrn8AL zpn>qkhJXEU^lYuMaFnTqw?rykMrIoL{A0GTAg(UG4oc+^`bF_VZer~^&~>Lha$?9T z@+SUV9Lmjk`?cgpkO!3{kfO!gVc1r%C?mDhcSnWS;AU0Qw&wYqiK=$jkh14Y8xsvw zxj;>VfSKPybaEmMJB9Ohx*L2WmR=FE^xJXciBKDR$3KDE7dcPV{QQgv>XYJoy3;+q zQ$;-!!X=~)q9Y{wXD3A<t31K?2Ty;UdDT=lH8sLNodGAy3{biD`98N;`6mF?vnF|R z@mHayJ$WJ5V31~K@q0w-9>xetF}!3pdgw*pTy8YGD?lN@Xi_DefKD`h8t-d1w+GXm z+ZbI9=`XvvR4nsHK$EaDU#rDR?rD*K%*hg~a~#5stv`+c&U>GZKxsLZ0l`cIQZyxW zpXlqPKoQBCA7?47xFafezTBQ*I6?Izy_CZwET>*zL$xXwmz|Qs=9}{q%;xTd7JSi4 zbK;E#Zlb!siOJH)S~v9eRGQRxmuPHE4iM~VgX5q*-$}QFbK|0SMS%O9XwQ+G%y=No zbZM%N_#)wu)4}PDV1j&xd?-&Nu60AB&*g6Zq5si-I`GE6rm{Y7iTZv3r#QX92@$E^ z@@*LQPMm-Qd^OV6v+fs1fW%!{k>4bgreVZ02JDkWtjho4Vh(*cJVrB0ZvH8qciakh zV*MtV`Yx|*F?Z8#rs7ufF;LTZ&gR3!6v;Ekp1ZlZSTGRare{m}8@e8g&Uf3tHDpWd z)<$Kq4hT2CX7%#Ft8TGqFVU+qIc9>>M^HOHxk=E`q5oM?eYnQH0j^i?Y3#HEZ1&jM zh28+8yEY#z65i)|^gqz4gZ$v;`7Cv-h}(%r#98{MfAl?0TY(qV=`;ZI=F^?n6E1uB z_2^!4wccj4@IUe%F*-ll*sU{U+1vrlw&u#h+GS(EYqX}hxD+UPC?r-?MNuX9AY?>@ z6v+2<EF{=7Qr4`hwqAN0dQfy>nkF7^SG4f!aNmBO15s?yStjoqMTb<coI&?YZ=c@o z^!j#p%l;r~X>7ccTkzXh&q`rcvs*6EY1BmF{$U3AV{eN-#gFI(o096^4OL!t?(R3T zxoVux7T!H3iG^gp07-zs{vOW9Elu?hr@(?Wtu5ka|K5dtfbFos8xxr3)(iGu9uIHZ z%fdgnX_Xxwlo}Rkf>O5c&a)C8v#{j45U>}JENE~jBTky00=u2c(RfeM2@4usB`V4W z(M}K&=P3SkFIUq-bwjvrVX>iupwkH3Wm@kByG2*mIe?B%%!8EvwW(trE3c+w!qu!L zfPBTsl9{zbZ8b^U8kCklQHs#CEfV@Qv0;05Ptu~=*Y#gTm3-c!Rpnn<pAmYz3bHi+ z@_LihQ1e3SuehOm;kAc7z%YN<UU08rV_{=(B7dqj)xoC$R&(AYYkna*z(-CkkRYGF zM%){FA#mRT97S>T=aJBZhiC|x&{<~a1aEpQ+x_f3da%4jn<U|z(P^A90t-*D7uxe> zAIB9=X@tOpH{0{j1+}q~e#p)C7oZ8$2T<?b*YNG@dR)Wo>QvJofWt3G2Uv|}n3J{O zKu83uqj=>^Jm38CTj(RqT^eM~)4JrC6)_q{flT|{&^gs#{|SKN<!cNr0UrBI=PpBj zallER>&_|ERNj0;<KHOdyDS2xLc1yEPFlTxE~ZthX%AP`tv^C!Mo&=NZXo&*npMmL ze<PMt#{c*#*o7(|62CA$&+Z0T(CN+XZwL)lN`cv{|F+ZW=;DclGa3D!<xLbNffi@A zf1fLHEIoIy`*!eh7mM*CIK)Z3>aRO|jI>Emu3ZR5v^1=li!YtraK|J)THrq{t>{?T z<wMWXkf?Cb-EAx*iXv+Mwf-klz-<M87~!hhuFn)`8mMK}I@!Q8boTxAK*374&-aHe zHA;jr@8a60D5EwT_RJmWcFsf*$Ok;veE+S2G5(O?Y$nO|9u%YFhG~+U2`Lhqk>R-1 z*VO)}ptip^ba|9&<%m<DRw9TUAYl2nU#NLxe%6E2%3a8JXiFmqNdiOy{*bBvFz^t& zFA_<!ZTNz-Vw9$Xrw?kppj@O=iYV5!ZJ-n6SV#(aFuet-5C#Wb)N^ji6&N#<0KUF7 zr4gzi)sz7Mh}x&m!^Ek7^>L-^`dT(=hNv&iw3H<}C5IsQctb`;;tPFqa|Ny?B(*4i z&4u$RZ$6D%P@P{4SpC@J)_|1*D%wWRo_jUH8}5&Gyz>C2nmF0Oh54J}usZnA?g1YD z4!_QK4r6KC#*WDL4CJJZUQu+{xh!5xIyM}w*$}Pp3Gf?o{Nbj2pmFUZX+(T@!;;nG zchjhJooyUhpDI2|;2tt1;P}U&=;hbBy=YnMrkU9QQ`!II!0m6T|5P8Pa$^3J-H6W# zi47Wh?}^WG*quNlT>mblbX!?VEB-g-)QP?57_Gzin=UML-LhLv^!*k{QXGb~%r_@= z*AEZWfR<!+jwXM?2F@S(SF*#6?=>+%8%{j{(w+rV)(86#ec!E7MI*l(#36dm#?^8V z<`G0OxYK*N7CVpGHxhG2A3^B=8Dg8B=^ftnKW~YGSj80dV{eEg6Yb!z&a!p--z8w! z(N>_Ibf9ikqu)ta`eBv?CR0*J-)k!*W@8Grj6yyLiI@o@z^X!mNYMih`+CBcd54!T z?r-Vd`b#EU^DN)PS^5djAP5)Ux8eq$)!YMo+7HgmhPdn2jQ&{-DN1cVDWLu%fgwQk zD<DN*cy}NlWE}MdT`c-z3jAF#*%$te+TSF$Jq;(TicjRX@??}wha2}9ViGN=pMB^U zQ2Q8R{H1Lwsr$(wVqzmdwb^y!_{6`m-tYE9BQAS&_-E;RG3h%YAvah@Lc|*MYNEH0 zBG$`Lb$hvG*hiRB`!L~x@)v;Wz%r^Vs`DhACuFx|8VY1}?k!g?GMwQw^4#h=c87c1 zYzkq1F0_UWZ@>EQ11=wh)Xc2lo$Nc@jvB2XQVsnxi~`mc*ZzLx#&~RcK3&5HpS+{J za)rpEDm4<rrd!)y_P6Feaj*y6_Box3NU`%amcGwnpbh_ZOKX<M^vPLK>P~iJGxwKP z>L19q4CRI!MC$D+0E4V4L$8$}Ci?X`TRI~mj%HY(z6TB%(hCOvW7CkfY1YMlfMt3m zyBZoLMM&P4<Hw@ThER(<`-vzN)jUnt_i1kX%|npD8(a45mD|#u>u0PI?&eQF5YyoA zbGu4<+obyZOJ_tq!GZsQP?q0u*-cRWjH%pQCdh9?W{<ivMJ}h%gpYim5IytsZH57B zRg~NS)2+TqMl)5~l-;;u{*=*8J7(u}2ZIzl)3uJKBSgN<IEuKzx~7jX$Nu0?+ZF65 zGb2vIUHlPC_i&x^My|U?PI09lO@%p`ICoH~e0IJRUvYgo9y7%gqrQGUV~CB%`VCi2 z%^uf-lIZS8AtSU)w)*->q6_=s^(AHyyUlj}MZuo?^0i~9sNd9J-_xhv2c{pd_EaqF zt+?WgwIP(ORMfVj70EQe(<IvFn19Hy`y$hh#LM(bO1LwdkYO0~e!l<7Qdp!A6Bewg zjp^9Ee(i^;NQ4fqcQMX!+nw;%CwgIzVUI%%2hhw7drW1R@<RLbnkNldLl!UsE91ky zWRgEpUPztzUbCv#KPGG~HTUudWPQcP5U%{45D<lj-;Xhb#qVMwiud)1BT<KokNreF zAGr`Y<g>EQRSdmr{MC`pg|I%_lycJFjYJLjCs`leY%soh*qQ?7K2=t$`%tj34T^*5 z(P&2bd!XR4em}HnG7dk@!P6xna+h|#%1McERw`ps6<o^s&}T`#<eT5U(l7y%sFoC} zsQW{f<Di@GpBfB=1$$7rojdrFJsVR~KxpBF+hk|?ve~$p-)RKY_jE-CGl)mP=uy02 zZ|S`d6CQCLaunTmO=HjZrtUHRX<t|m%Qa;>vTDYJ&&9@#wZNJ^(i*zsx{}uW_=jbz zM0LH><)95Vkr=a{bkdKLa&o@CQSn&;WC|Z0K_51Lteiu%_|SC=iU`%6jU?jo4=Pjg zwm;@>XQvut>(1GziV7gp>NRf~JJRktiR|3DQFS<k82J{AU{CUpW#;V_7QiLCR|9%Y zH#Wu&IB?6D*-jf<>vHae<&$a}3_$l)-leM6*3{(0k^%3ZBfp;DHVcb_y|&G)FIIQF zOkMKl?2e4~`%yETKt18RZkfutUL<ce`QzF$OR!CWZi6?qW5(B8mO9Jc#hMPt<|NU- zFLor=&?EW&;woF>V7Yp2+u}@9ui;W-oBjJq$KOM^jm$U&3?GRooIaE*nO8G{ti_%q zjkFI*v}k-_&$@E*=ddYBhEnulhM4p6Eva&p5@7xM!Sa+rmn_>wrZ5`WE$7@h!?+i! zMerFwMH_^jWt*xEJq4wbNe-s=<k7p>^7Bxg60NDFBinN>Y58X+%{(4I{svsf+T1Q@ zOfL?N>JF{3qfMUn#10H*dO+MZQMpK;wVdeVe7?e{K2y`zpFrM=R4`}B55yTfoce5b zA<$!?{W=~7OY4FMQHm%#Q3sRNVR%s3A_ju3(}oD}k&RD<METvfTUxub`pv7>IC72> zoE7PQ5#WqOGNYH9)AX;>M0qK$()1~5Q~Q#6B1+71dg_cJ^ckT3EjG3v7RnOh5-!IT zj_;)czYBweFv|q&Y%$_#y{DB;jEn*%kT*Vt@&>!_m3?|dDQ$`#w<~iYKfl!uZk~u) z55b(aE!|snt8Ven`R+u$C??Rly}c50IddVI@lck%O^x<H<B0ox)NAs)I9S{~6}aek zv3|+X5ar*pPWT><q#TlqGGMDB>aZeo%A%;m&JEt!^T&SaV^Opn`kMdbXb;CK{gf8Z zxm4h7PSoc}Ic*LFeu@lY_79Aw?p`M6j!Z)QoOx*Kyf2p(I~A*}$^$`;<o5&>Tftpd zB>RObZA(!?@;-TG?@-;VYP8JfLaB7=X<x-1rQ}86&_QY<3YSYMCtYqcB)x_GVhW!% z4&>$y1l(v8^wcgo;j1FET?CYM6Bv_TafH`hHM5!)x7wxz!|K}@IF<MJTpQpIOgf}r z{NM&jw4JG2o~RsYfZq&lkVk^=7QeEHTqu(~&a2c;`$kJU<DMpTcLri?mM84~6cD9c zq^FSXRPBYjCEKeCp5)}9_A`beB?E??!u1cZ?`e}|w-8KdcQQr3_>cqH_24@8(hvlE zDg7@fWsMid;hi{EtyQ1SIcWvc&et_P&@2C&d(u#$#g8OnH!5{D%_TGsCT41`o*T8) zYZ{p6YlgUXtb>A<sJ_SDSNb_(DGrOxZ|b{u*4~Wv_ET+%sC{%)=C%yPIYTCrHxPzg zkvy48%Aehq=KJOVIA15iB784(B!~TZ`hqHsuoRxAmMtynN7ZRvY3bUoUt>$CvU}x) zu4c*W8i(pwD)doLkT*V|E9MqV9zCcR+QnO!!frk$4jnN8AcZChxTYPzK&nI4{*<#a z<jF{<N#4d?v;B8nLv4z3df!?AQ9~ZDdDqNQO>qO@j@i4kTJh_)@kJGau9P`r=XO9a z;hBc(&lbMK-evEB#Xs<cwtv)3_&th3?A_hd9n%~|QyJJ)6q#uA&o;yM|E9B-%gCvY zJvTReU?VfemhKMaCmR`%{0gj?P4t}>5;%yOa_Ki3#(|JN7f?uAF;k!fJAuA%_AkR} zmgu`wl;Eu;Z}U_t5|1;SpJ`mSG0(ld_kltnYeu$Q>n)pUgvsU$g)cyJ4=sAN51;R3 z`F)>j%~+44U&hyaMlqbmUwX=S&7tOY_rPH~qn=gM-$o@;cDwMBNNfYR^HuI)+L2T5 zXYnsB*9@A{ZyH~?C#lSE7~Gw*^&^{CiISKo^dLN%SSReuTYMVD^MHvHR4^5?xZVAb zglK)4AFFuF)zQ7vbWG+-a;0D-aL*wuWmN7YQ5*eIFTz@m3H%j080HUzIMfNaVOOJ0 zvE_P(UO&y!lm*|<pRQ4@VyhGU_3zQSLPL`ldlYCC`-F!wJ@sNn-6b(|5kBzegME3) zAKtxi&tiSUa^K^;KF41{i7XZQozH_F;?LcfDO~JqfoM{{n_2KOtvRb}@lUG`fJ_o+ zR%Psv-}!@HJ2S&>j{_Ac>KMoeayQiZ+VRET4rsP)^r=w3s(l#yOPjb{#%R#!`!$7; z4Ux>{leAklK8c8KMULo4Ugqr~_kI$n7Mza95)rENVu^RX%&HZIBz?;jNA>u&*|jD; zp2YKCytcXc`#@5ApO61uf?CZD_xgMT`#ldkCL^~F(`%QzR1-0QUHr?mi)pxnZjh^; z!+LB*dL+e=)cLb^7Xr(F7og5}dF$QsCB)=Yl&5E`K}ktv>f}&mt$S&usBPspz_OOZ zM|J7aN3W4VoF$JSP~D)u^I-it`CW?fiQuu1aeg{>X5uUduiz$%5tr#lG9-FFI-~Mq zq!OTN6)H)E0i)@;lg=t@@*N_&G5&*yX>OKkjUsI$sU!tS36t6ITiM{r8x!a7vJ^bM ziaN4+kj#+6*i8BKp6}ZLR8B0n?mGeS86P46{gagH*Iv->nBBj;h;D;BhMBWFpJv+7 z#6^Nnif3#ZWd0e{Jnx3w%}_3Ar*`a$WZ~vO?R)uV`uZb?y<N8Wi%xCOx5Cai-QQ@^ ziA66Jj`M$lHYu_Bxv7y?MEO~3QZH;!Iq3gUbyaauwO?02N?PegB&16^L`piPyOBn^ zI|W3#yGy!;?#=<}9Ad};hK_Ia^?&hQ&dvPJIs18buD#YSF5+^n1Ce1=$PrCP!s6C- zG!KekWAo1eCVytEJg9WSkV3W9(~LUq8f{7om!B1@cT1<}Pm$wt=IUTS>CeAYYItQR z^q31oA8S6wFQf3iHA`cy;gJScM~XVD6m6jx$V>is1kj8<yrrOf&plGAaN{820mL+} z5wj#Wv#n7j^d;sNS^1>Q*XR0=s-+pN3+okt9g-X3q0X{!vlXrL2jK9Bk8u4$OE}vM z{Rw8aUmDz#H5VX~iWLk3hcmjqgF)pPsdy`Dv@p3Jrb5#A=?-uVSrSspw<u}fcPSB< zWoUo!$;&OWL0WWS=(ONbaVFweY7mlOhXg?st8EUwm)7fzni|5ZM(@u|bpDO%erR!> zC8#>H6uB)n9(?<ZWhnCv?xd>%RdgsV9}EI1ni63mwT~#}R5JFuaA7E9v9^X$(JC~j zVY|qd!q_48x6K>eHUmC1p>lWhA|ypv<7T^T1c5K?qJ(>5M+>u8V02~V{{~TEvmn1a zBO6!GpW~v7?=`gYr=2zaK+(gt>EPE;)-Q5QIV;kvew9P<o}i`WKr{7&`Cdkcq4D$E zU=&8Dx9?tMi!YhJT&7EZzkFYu-K<zMjr;{A=#m=so5+{+AGo6l*0!AF?=1<UB3gxi zKd^N$(bkaq*M305j$&?nWkhm8@a~S}O8VM70wl)ds$M`=)9)@w3tYSm&lTIcC(>Rv zF5`XuKA9Uy+vbysjTWzX7Sd#Zj&kxb_K%syqBmE~crJ|e$x%!IyPMA<Es0aykWDAB z$?x|$Rkup8m;5)}4hu@I+y;GsaSB%an5=PX80lmHv9$cPt0Mdp-%Ha+e;5+C;SqCr z-=>bS!OXR$b|?u<QZa3N-cRy`rnVw27l@8@yF=V(|ASY(uS4ml@o{PO+Xu==GA>qo zl2!6Pf<t|8H!&r<S&Sc2@i_OQcfloBFIs-2bXKl+eSF#=X&jD?CUWrjgem>Ax^GE} zD#}|r!S~*DKmJ??w2^Kqg1dDXz6AdYdm!}LiX!@H$+=8XWv~fVs8E;-|I@Oh5S6wd zlIVqWWIOUdNcBM%vc!hR(Nus>#q4p7OvAvb$VOH3f3Nf!0FNu;@dt&wTU(K2RolPI z-=@?uT&0%$Tm4&DL#yqtAvQ&CNsM!8vpOR2fo0xQnRKN91$nNPOprCri;>sgUi*D7 zgi*%6|LsJddZ|cX+R+sFomG||sKj9;do2I@UK|EC8o@Ar>eIhPkoHK(SQ1lyf<Lg1 z3K-&*Q8XTA{PYt_PstuG7brz_-SFGmpT)7F8I$WBQqT5hqBv`8p;*VLA>s4S<_a)v z+!1?13T58+uCImXb5w<C@kJJk#j}O}p-f_m2b~;#dV_x(saMV4C<bi9PaHq6{dvtW z6Q$NI&XOOawcb>N4EoWT<!go(uB>$=(H~%ERFi=G1{sN62>8p#w{XP4nC4aX228LR ziK;%TBK`q}I^?7@A1fdwt;Ooy*&oGrtnq6UUK*g}uE9rdjdc|mofh?Wr$S%Sm{rWP zd2>nJM{BiCQ+g-Nf8YFKe}Ts?&@GTc`(lQNWf2p;A;c3bto+?I&j3CsT0oq}RS+4< zX`*TT^--n;)l=l3y*4)v99al{Q6pdd+4r(;fDjZ0&-|H9#ALs2_V3NX4J0L@AT!cg z<q*(o9a>vy8B*6yuZTZ5W3=C2C^qeuCdhUt;#gAW2nrB}M?ULyHCAAPx1)>fvyrW5 zq!ef3l$sG<+)^d_xn#iPKW=aMS*|X-QG)l~8r?70uG?vzWeyn>PrR`;>?;lhNHP4u zWllK9N6IFi(lOt?Z@r8Fn=J2unICZo^xMkGe>Bm);7g+nL0<n4{@hrAnA(wV3O9f` z4~J}0-bDNHC3okq)DvU}FBM+Y8osyOP4ZE;`}M-dIR8L%Y&R_dQCzp)S>p<dH87gR zL+3W|Yv;e2l5g6^9<Fal*}^d-8!H>ueJ?y=@oIMtXm52%s^sEHJ@sN5g+J`;f8eU~ zX@$nq_`WsX+j%KBcPsuA|HY$OT=22GDGSw;G(@h)9mibfbriBhJX}zp)K4eNvl~N+ zEmbZ*I}$wb8_*1A8Gg;e1LBOqHLYubgI|eC#Z!;^wPI%z2CJoo7|UlGuoxNZr-F|Z zxlvYy8Hdizg}JkULQEMZx<IEbS=9Si`r@(dKes4VCT%TsIm2j*7*xV^z93^9quF>o zi|aMvA+kG<Aa}dt9t5EXd_m7#8VNi*UQ0IkXYX!Ub)7Vd^auR=^lbyy!mXG^Wfl3` z9N1nB21GbgC0n$7>XK>a@G`lF_i}t>Zk%5;CR#TM*y|OK@D1%xmfA6mRLHpL8=+5Q zg2M|l+>H|5(!S^keS0qpGS|8N$=k@CcZ+(3OA)s$Jmk(m8}VjfuGZ1`wOKg<OO%n| zX;C}VN5OBO=QK)S7H9n^pmq5?y9t9kOAO4~&`%Bc4t?76rH_}uj-reFDXT;qg)OZn zto5?7c}Az7lAp5*sb&*#8FvZ4@s+Yh2Otr%0eGZ(K2oE6l_X3rp1z#UAClyu_z(9H z)E$yeiSoPW2>scxbRMj``=6K`#12s;4;CIDyDXTJjS9zD1lqsFwKsf=ux*sdIjW)D z?tO=f?wI#dBHc!Y$cDaAu|rfCV|oBTYIH0^Y$tj+q?0IiA)<k~g9t16gL``4%vP#x zV5Hd)-V6aZL-BW*QhUB7jBOatC8ECYN?T_M&EUk|5K8BpCZZ-U_dG>DkZ@B(b!_a2 zO)U1?GH1nq*}<y>)kkF|g;ca<DqXy$=5<~_Hh)6l0Qt+WgWI7vW;V<*M4Y0<(5ON5 za&0o4V@>kD`lz=~I*Iw!6g7o}?AL++q1y!r9}dlglg-dBW*-LnpysNN60?8rvK#fe z$*a!!bPVrZM56h#G@F`+feDT3x=~<y#oQu@ljs4}(c?J8R@-!Bi<`d2gV->e$?Sz< zj2$wwY=!BT*6Rymc3amXCU$iZ_w4R;`)x}{GrvAp`hwU?3Z$(lbU^i-;?3GCCo1OB zXO-k;zmhj!UM1(oZWb@T)}!Zn3yrePv55vW5{gk7Yi&>Yrue*#66y87S{eK<#eV*k zPvxG=@PX=I<VOzDnExJ)yZF?i<?9Dim8IeOlcG8R?z=^}Z?Yy|-I5+63N->(jTT5o zk5rD4+O!PJKz50fmS?ZX`1nr3tV}X>OSK3nouy#}qO{y?qTVq14>nQKclJLq@L6rQ zQ2EpCiF=pQ-$7lJ?(X6rS7ocjeX<?pOk=kvLHGvazSTAT#u2D2f;7x*^nANq7sSW) zh)ftup`I#!CceP|-gi4dHfKT+_Cf4_$4m@W(N*XV@7u09?c&H?(H&#apCX?WHtD!P z_X}Xyv$%b<=l4y12G8Aszqpoq2HDojR7_i+FUHy4N;aHvD&Y#V7xbTVwr?auJn!71 zphKVOyPv<vDaV3xI0A_{v#1js`63GYd*SH?g2ag+O;?NXH;x*t+oiuWl`*#Lmkq=h zUp0%s0IW^SDNi%pyRrOe(mo9!*%8EIO?Es|FNdx!5y8zK&3Y6rI<c@E{bd3~zFLgT z53~uI$T%>LC3slomKOy&atlF&e3%~85dZv3ikUTMFR6&ke$d2HI2@>GBcXSD#$8_! zjYy<(XF1iFi{^8A9dGnMqrJHi?%Xo}Bk-U@^U$?XjQgL_7P=5gnF1(&84FLgiYDt> zGu3Fw*uzqpbekqsBeHo=wo4X(Ae_Di6(8G&*tl{z;P=2e#=FsAMxM*~_$FzaFE8xq zz$no8cf$#!54Sr?12kqS?!^1neP9Y!U3!0`=>fzQPu>V|vZg|agLTdky74`Ig`CcK z_HXN_;31Jnf>D~KI9qYKKOLpOdFtkbY<q~U<^pz&sjrT3M3Gp_SriorpDec9MTuHt z#E^L=L}HkpUaB2&mSWg+XIhj}K2;1q1ZS|q+E*p!4;Nq!JGU*f<<;k(u|F8SzFOST zFYEU-$UOcpp$p`pV!=JL=%Twd9$%7-sJ>|XD|X}nNQTYE7AZ$*B?mQ?E`JLojvh%B zavnK7(pq;R`1y?R6!AAIiX?2hPy;2+>VS4?V(%xXZMjJj?TUfmO&1<sNFI#7lM4eB z$8C=M<o!u{J0eg1Gn`J$JECNg8a2%B90<0co~7GTgSM@OYB+DZKC<Np{&odMlT?MW z4kb$iq@(zsXkOoJU^TcEYZT@C<j}J(Pr+08SNz*`=K0!S=OuX-c>Yz_^68SJ%hu?k zy-k9#DQ)*5O-aFsvB6{XPc3V*<XTH_C=!)NB$S;Zayd7zW+Zcru?-F=`iFjT17gy~ zoupBCR~6cTUxAF7uEjXyoExzEN0`1R3D!sQt+(C3ao@xzDa!mB<!gj-ToWw6s$fUc z6O)|6GUuLS)nIMrZha6O`9CCD*vx_J;>|vaPD;8FR5A((#>oAfUTwEyv8<gLC|<&I zf8g%+yd`f_>zvSE;_sdKQdMhS)PJs@<l*iUo+39q{Dl{F)L~t{yxXoy*VDGRwk4dQ zVELfFkujaezDm!BX7*T(GmDjrpCK!NwpTinemA(fn$>VL*Oa4(zKG2D;sfe-_w!p! z7Ozd$Vn8FH+4Cf9<@1yc&~*Vu3)0fw?!-c}QvtzdA%MJ-Ze%Z@fJpTC(*D>md3}NG z1zjQRC}NJmF{rmvU)(xBTrUSUsfR>v8mqU|I@!8FkD_2ol{*?)KT;xmc$}OHvgO0x z4aeb<O|DOB;D0=1O%7YY>c2v8hV>%PJXaQ59L;>Tj~GAoS~ZRoMvvFAYJkg=A1GO2 zl=3XG%;(?k<`NCkGN*U>uo<Mr8b2;#g)bqGAr8W=1(gFC+>&_wF2~K=0MTG0m=ygj zTiShW=7S9_&lOC~K!6nGnm`-oVciv{ZJHKyA1{t-kQLb{FMcn|F5GAouiUr%ab_o6 zXLT5UAtP9V^Py6u4ZYmNH1ptwMa`<A+Ek`7D+hSc#eL^343$S271Pd1U~n@tYA^E4 z%H5dE>O5@F3t`;`-kscar1r+j#f(jWYHyi#H+Vkb$FqMYu*=<8pOYs_K;P+|-2CN_ z+1M&qk0Ek0+SEvz_fe2jeV-r}Z^V)0K#d6?EIsEV5_KWk*ysToOSkBR*t6>TKt?m| zoXt?DtQ!s!b(IJ+(_vtq8eaB5)i2~&Ui2pCfqP`q_Y!EoQ|@UaS$Z`apJp5FOzNU` zTJ`8>mkH5gn0&`>d}Ca6#+O>6)^D!uGw(-E6Uz^I4m5^0epoGlm#t@22Vsglsp%7U zx0K%rVq%#fj;~>$Kqk|N4JuG`V#sqXF@A0_2Oh#5t4l6Z?H7(Xfuc9(a<u-&1E}|5 z+gsf?6_uUP^N>-4M;=+mYVY!8+j4`xeYj&+7oKdg>?~3tcSS0Z53i8z2&1m$ah3Nb zDMV<cYksHNg5T6}de`3oSgt02)%EW}N;CVBw{Oonw!O6GZBA_T^q;^K27p`8bHnt~ zS{F6qAk9Cata^bz+xeJyBet58YjrTSY!iz6%Tv<<eBZ;KMC+BI%>6&J1TW+VM$__D z^GU%cl>6K4TNE8u+d7I4*HBQc!xngL^6&H?xkqGmgR=_lTb@GkXsc4~DpUHfe63Fl zANLZo8o;i4<~R@01nBAUcn1z4Fz~&<^+Q}vCLUkH4E<qBsmY>2*mk<Vo$ax+69z+v ztPj&k)|y=KE`!ZCg4A>UszM{{Czs^BU6BF{h;*=uzQ3AfS+UY9B8CVDGwAp!zcLx* zXg5bgDsn!CvBvqH6<%og-he7IL9#vKI5#alD`Pcbrvi}8$#t)tgY3+d-+rV;r4n-x zk`3%J0c2?<o5Lnr>UUQ{yM{yt(jq$L)VpK9Fb}y#6QlbRft(_|-%c1iJ3Aa9P}gE* zG}})cM3bXtQnWE-Pa75|ZF?3^;IYeLDYV;~MHujB-1&e#{>Mn*)dPahBRYcc#CtdO z&E3%0dE97nGA}d#896Ki0Uez^gHESyooC1{Y>Hj2rcsTC5OTT~RR@~|33%==W{Y^A zr7FhYUz1I;b^1r~ZxYf`ew$W+w4UXjzndDkOnx7tTXs8NU#Qc^Thw5Ie+W1Z(5llf ztzOk!^#rvM*!$jIH@UKAok00*=icg9xeF4edK2rv`wvRQz6t!v_UXTkkhSHFg@QA1 zTK3~U@^3nkb6hXbn3n6ol6(@zSvBg(<I0~L#f@ciPdC;Nzfpj!#Qe9rc`%-Kx1_bj zb*8q*eWkY9-oWm}QbQrMyf~SsI<x4SfqmE_Y8!bsMx>R^>v9vabqPmdp2McRt;%W3 zk$we{p>s7X`G9PQ?X^k^9?NMtOT+#J1Klhi9_lQtX{`dBJez7ARZC26U;<OZ{IK!O zLn&P`9p-BM=q{ZSxdC-}N13Fk@)pw<4$D2%T-l}gIR7C$*<q{_^j@#}qa=;0DwzJY ziOJ!4db>VMOPvH4w&!u`=VT7P3F_~;{4}t=jz#Qk|MQLmrRdG2zJLOb@te`OA8HX1 z<dU?4=4I)OI?KruHi;~mRXj4*pU8TzYj3BgAEoxpPyCF%k2Zul3<$$spc1(>$JOHA z$M0H!kw!idPGv`x#w_%+&sLozSVw8dfTHY^Mv~WdJpZNLZKQxDbC@uhf$hbm306(D z&$Wd5(jq8|?{5yY!tAae%DS<!XWTZ;qS45`zM|i9`>+d!?lo~I>D$hg9ro0-24s(0 z1nEv+JTS>k7+*BJ+h_WUeV>ibw%#l4j%ELA8K$r1j%JxFgSY~q93rUm?LZNTDpwIZ zF0#ttK72U%PQjuWeErL+p{#8a?`=>38Xg-rbrylCk>*{M>MDLHky3mv5+VG>UfY6o zBg3-8SUpwON1Tlx5CmTRGlmRNAKYH8=L8f2MHr_?C9w2M&e!9He+#o2=H>k{<hq6; ze}uRHfTUP`F1&79Mmq2RkblDPQ7^McyY?u2RS`ufMg<BBVSt9yWc4aPE0fzhH*F|b zrVUtDpeOq0tTmDRE5!MrlJP>1`v^xC*^iW?<_K2}r+}eI#CyGmKMn^5B<i|FUwen& z$qj=mXcYo<U~H)nf>9Vc)S?gy(ny2enO85^(&#D2b)!7kl@Xc_mA_n*c;`auhS}s^ zw`xRCbN1@hr6O_LHNVsP3&P~?Yn&Cp)cpi0iMRX)el=~+b|@NhAXY@!Q;_~5bPZvU z_A%vO0+*~>xv*#<{DkgxA{JX0J%f4QJzA{Q{THJh*4w@J!P^djb3na#VQpz?g@IY` z_WZ8lqSHXzz_Vu2G9jc?l3j#bNQDqa*Fxu9UyZQ1Cv7=pj|AP$tf9ST#Oxeqax0mW zDUUXHX%q9sqsMq4p6dJkfCDgMpHL0?EpzvDMN(<{b6|;9@iZue?Q_wpotiat#<N_n ziJXEvGNklYkd#NC7KKtNfj{?6tNZCT4g!2w8x>{l2R>1##3^n7W3zR;vNlF1%ZK0W z2&}n1`$G>@lcT$iX8ETb+IK&|0au1ytKxb_5kP|U*zc*>SQ<r3nc9VGD{KCh(Eoh| zf}m`_8@;E_tJG{GML{PD0XGnmfZr|gv&3I`GcPHXw=Y5=+8j7K6NVL&)fwgKXm4-^ ziJaI}0H$Eje@mVZ!Z3~dZHk)*p)m5>o138{oLFce%fnz0rDl};T1kMyLQ0^7tGMt+ z1KJho-Q$rZ{X<VZvomYZaPA}<`S`%e{1#Y%HLLx+S42-+<k`u+|6|4{J7;j$gOB2x z-(+1UfX!#pglK)#td%WmiPeq>CECg`CZdnnva2TUx96Ks!lT1&Ubw;Sg4vL`_tggN zFgCtwz2@^{5xWMGFJ6~&=1$(v5vqgP_lZIGYuB5`j-Ddlt6A-PtXJu%>Q9z_-7`i; zeE8nL`C=q7NLXP8F$V9cVDq_h_hk2c2}Xh0e%sD!XKNrFU+=Fvq&RV$?z59>5+;0w z79W2txZ}~zboh~>1v_mn`<<NEH@XO6@+IEg6499yRTAX|IgcQNgux&;f#^Gh<K2+{ zXo`nhDDd>@J-OIMN#4JbGOF8Pijd@e?fT8b<oW#y!1>O$5hlju?dJD)!okb6PYM&f z{7{|<*7mS|Jf0beK21of_WNL28yyQct$Xe-rH&QhVdr=2y8yiHG>ZB3973<1oWilJ zw*COj9(pGov){s}YZ&*fK+sB`V5Ga~OZ91$UMpmzN#ARa^$7&(U+BQm$HP%(`aYQ@ zc-KAI@f<Mua23#^ie=XRz;)4@g`e$iIpM#?eJ5K~Rg~FB9Q#bL&NHjN)W7plw`kzy zSt}c)%I1{C!1v;a;2Eex@U&$xM*`!KqCu$^Uh;cDh<)6BK9~xi6Xw#+;Cs;%XrYy= z(qb%~Yu`8l$4;^G$#k5QxW*t3zJk4lnR2`^I)VCzSQ$f^#&*qM-fCVOMvaxE@BOsW z&-yqDYFOwnBj*fxn0tWqQapq16}+#|W>v3+H#}}5<YGN?6WI#MwaElZPE~FEe%Z!L zq?hEqggE|mcw<JFV=G1g4eJXIuxcU!IUO%8Uhq5}VX-hhEuL<D;r%2q*AorhllcG4 z$F^BZ|1E8JAv~--1^Cn*4NIL^_-@ohY1p5WaI{`K{_QCqZCDhXBKitvXVb?hkTS^0 zt;SQ3iG1Mk*@p}&2wvR!s7jp--{0c=LhqWtR)c(AP1yD^=&@DvUN<R{8#3W&6O1f9 zY|a>r*)jLsPn%ETsE<b+pwbzNmXD4ZBR5QC(OCuDskdvfMCA6=oMSQz-i+O!J}<5V zu7{9C5=Zfi40{OKUQ<_y>F&p}L=l+pOuBO~PYvLU4R^7QD-0VER61Gf)M1<@|B!se zc|Rbv8(U?s$FEmuTj|_3tvI~*&14p9^?I@MajG=?x#wnR1!ofLl{31r#D4t)8%eUu zvTv8O$kz)We5Vx#Jx_ERDL<m1E5yOi`0w*2ZrC>uJr;GTc-Zxr#z?yiR2YtReULl( zX+jZWh$cmv&-&<21R#s+E1hRIQgz)!;ze}&ve-cc<aA}TK0$t-B(H=*&Eg&-AA0g^ zOfyHf*?~9R^WK?~Cf0KjkPVM**IEY>ks&09p`GGuyl)p_jU#*Omi02$tNQK|D*r(E z1D<R)z;Bcs$&tAKR%F@E2sjnUM0&{iT{1qTF}p$sezq<BrNoHo2=?3YU-bCFid!s2 zS9HSqU0!%7aD{8s*~mC_-7SERN$_l0?B*CV!z@I{eIt8C0+pwpSvF<RJ9w&*NnFMl z@^M9cJ|qJz?pF+!7S?h&6(?*%(j^zyDc^(*ZrtXCNnd-t^$K6pq1LzRtSch+VJ3(! z>#=ZpYe%kp6`MUTZ;2EJh&l?Gdar{^!~sLSyxl2cwnbZR7Qy{GiVEUh{v1m3J2LRe zA>4i21npj?EownVU}2KGFE45D7Ea&xVlLm{rn<NolLB!&XW`f(n=Og{T~-3bTP75n z4~R-ZLnkpAgxyl~#%YQ6?sH7KQt{%?9#F~P0z!hfop;6Z0aw%L0;}z*{$L1-0yq8l zH7^)fv&T&rXEw_YZ4tkBWmI3@;~N(ufduM$+v;x=GcmvhZgpFye1)a?o3dyWlDt7j z2#2o{)7a#Zy1hQ*7nV-oiQ1^8&{$8jKs>C!93z0ioBx}KXPm&=brkOj_%D<^c1P&K z$Z@L+e@t3DOdkyy?>(=tdA*SNN$RpTt#_R5xBWOaaa7TyUG6d?qb<!C_TwcARltUW zn?ELIj6g>(De?*#a-i7j{ooe?=tEU7mR8Wbmq=UPb~_JDg8O(i`FUszTmc4Kn6IYX zjPI0}jSUUKewK~x4~<bn$ohrqJDtJ@h)vYKJR1V0X-Q2vjEHZ-9NI@;#^zt)O4>6O z7>vGrmwJ_Q#ryml9PAr|V#J@Nm)g;N`^Y%45SJ$YHvVvUTqjHRnx$&Nk$EX%t`sF3 zZT}rf*ZhZsrZ;ez3aNDrvYQKam4d4{*IUwQBERl>)N0Eo-(dq3oEE$L&jzgKNl=FZ z8e7GuAfB6w;#u4tG_#T4R1hGd4>v!aN^ZExJ_p%JNs@?$Z^X?lH`p*!5dMs?akF2@ z10JZI21-(MJx1rlHg;JS5>7^3aw@aPlz++?lz(5uc~4TNk^a4vrJ38274LMsQgAY= zxQ^CLA$(I3`{gD&JZoq$K`{;5UOA7{ciMAAJb`45pOh$plql}m^M@`no~Yo15#?#d zsj3<BCEec&VP#>Zq}v`*KoaiI($8Y{+CHSvE9myrqS)Z{OD~&k_jRg@N%A&F|5!3T zIG+>8aC*IchXE6a8bjPMJG&ece(VK<G&`%Ez@f4@5V1Zn|IBQ>@wk;Y_+mRHh_O1b znp#}PS7RP21V|z|`hgxt(QMN!-{i|6e-Y;E1Dj70cQW6FJJHFOdkX5%r3fP$Z?MC8 z0zl|Y*4sT0e7ekwwj0QC;hkB?d9cgiRzv}TB2p4Z|5T;BV4O@zUn2+eru#SaNAIdT zrR|Z>b1khTtilE|l8OhL^OxY$({BpVkr%NK&J75Y>Fx}bGo+h~)S)Dz*uk7A0E($0 z(xX!euc%l39Fi+waZ&7-qS(7H0ruEVrRXFMGWrpXxUMs^@sqQgcgkNq<<HrG$m#YO zG1;gA6ICPxJ(Jcb6goY3K0YTkOTnmzb%REWzp9XQ%zNgEgzdOVFvzN(-clTHC8&op zAlyKVwCWmeoTxM>hDSwl-di_T*-&<hsd?C%!8Lr*fJ+`6U;``l_Y>RPpcK?^aOmpc zGacjMRd4Vw)+>3kG24i9m2f=^eyYz*pYDS8#l&;x+u^0D4H}T%cJ00NbCB9haVZz- z6o#`3@j5zM7Tol_y}u$X@$tg!0Q8?M3r?_)!t<;d$1Gn4`~XxIm$O!7(e7GKe74sA zb7b<AtLvtb%3&ptMB2#SdzNnrsIcSGBMTq@kk6Q=KwH|zC<|0e<=$<YiZ_{@=^mjf z8?;XNPD8&oheVoO(&UgMw%6s@h!7r=U3WTIDxdPJ<E(~8CEKfFKY=IGpVT>Zm2D-$ zWt2TPAF#;r0}WIs4%%z}A-ETt!`#V8!O`)Ny9~fB2fHKr0vRXS>A9*MjqV!-Et-qJ z>^4UEt<;76rLhKe+GoL8F-pSoA(g1Y-jDKfFqTe5N^<d`*7FV?Wi{cTIF#2j2ZvEV zF%KFS7;%N@`W&cH0v$sADSUqA&CT?q(Pzpi*Qn*z^2hY=D6{^#5v<5;YdQHzXRi~6 zi%Nft&0fv0c(QkfU@pX{Fze@wlOkmp?oFNUZ2m^wG>K6qArN7uu<98^KM!>Yi4oNi zmPioJut>0Zk&w$>MM@!+fR=aZsH>@uXb?uF8$+X+^iye>UW;VV0<?p=<A$<l!9OHv zypxk16a!4*DyMTOl=r@QV9q=w5oAq2v3A|E_33dr7Ye~9g*W53vTY5Bx7)16rnurk z9W66yvg>%VLK$kg`?c;`LDRy*f-^V^hDJ;g%$q?HGf8LC2wsZv29*H8_3qt*SGA>T z44#4g$v1g_&h*RN5ON`L0E&O|SxH>kEK2mu$%y`v@{;_ZwU}Tq15qzF1N60|)I?}9 z8f>|zH9rlGlN+N#*xEl0m4;$}g^?eG-lu3{2}id5cJynqU6kW_vv?xH!;O+w=8n(X zkr%U|?RupS{|7l2C9BNKCL)F&-UDUN?h0o&209rj&BmZC1*p*{C+;yM18&_|>`W-4 zs<)3(kw7vZ<$rhaWj*zDxNfThIV)-wYm)P}%AcnWP9_7GK*XdO;tDhaOR!m|YIfO| zR99uaM(-^vge9Xjg8(U+9lWi}_;>=#m}@o{;ATUaL;8A)bWC#+;6YdhMy5bVrjRQ? zDC(zu)S=Q^y;(pEbk2E9MBZalP}$Llzev$dpEI-0#L#-y{(PcvB}u>T!<dX4XVs^{ z8EqtCf@|Klm8w4QV=3nK!8`m5a~nw%{myqQTu0fL=sd>FIDfvlr3!a?Q9s(Aa)(-x zcW%j+xi{ILyA$Y8TQWh2&KuD@c(LB)&sp_!TzZnPmnh_1;G0mC<^hZa;ib*#@GYeT zG&_W0k?D5ETYpk3<|(PZ@XA&tg*jTgj3v#YW2PlROy$CRM+G93%&$xOig?@PjFfN2 zs$-Wfz+HO>Q&|Q^JC`4nO97ySoQmjJaB#W%ywR194fz|J+knGrlmrCQTkcODdOe=Z zjk-McvQ3M1kbrvp*@JnV1_GH2b_iU1l?`w9w-xnlE12`d%&n(4&tCvvh-zy#@tL<^ z!Z6l^b}(a1yqL1=yU(dEPTz%IE0?MjITgx4+&A!G7Yybo7+<V)FI@ohZTQ9XX%(bM z1}&|vkdG@*3a58bzLfUV+H@$_24Ma|_015wktc_mOJ$rem5oU%su4|l#1Zx_@SycL zwUT#txrlnBh_Eol@*<NiZ}be}c=S5uFq79RI7G~JJ5sg8d@NoPKQPC(*y=43OsC73 ztd5T-fN^|DqxB)A7k#4C@2*wQPj1;aC(8uL$mvG`ai&i5jaN-9vM<C7jjV(EkM0+E zGj>Vc=B(Mzwd1GvUXPIcKsn?`{m)S#<*XyiYu6k4J1ufm(|;*dH<ft*CnmV#bz{9x zF_?(*m|FmfMc8Cu&ST9E^w2J8tx3d>qehmxaniERKQA5N4no{F^HnVag|4=Nv~s)? z3!pAXoI75*usGBOi`H*w$-N#xJHjMj+wnOpW{Be?CWDTB!~L^<RbWJZY|kr6uMEl_ zoX($4g9q{6fOrq$%&3JE7C5$VomxwgpIz8Is9l!bMKD^Zt@qx1b~*nPJ3ijMQ0j0U zFdk%h-Z1<^L_zxF#7LmkjsW-@${d#Sk3D|yYV!C0Sx`y*jn(l8NUeOqio+o1Yr{me z*x#6^Z#L)EqHnMCc30VrR;q?;I(I<S(-X`GbA_o45ggTWpi;jp`C~W2FB=Nx?%~*5 za|4Kj-OZRtZ{~|#b@hBR-b>*m^1M#x`I&@&6f%lPTJ7coKN#a(?4;|VqtMJ0quOSq zsejrye9<8WO9g1(Ssx_OX;v+Lb4HxirUE}4w}9{NTIw-lz6Ivd<T}h~B1;k5WT3Lx zwqn5k>O-zKoSJsJUEAbB?@Po(jKj#0VneMrDVR=O$u*Qh?<n4zI38Mj@>lXuH%MP0 z#p#WPok*e==sfN;8FfxXtf(=-!aq(>)ZKP7cZ|V3ODfel4Zt*w!!M&KCn&!xD^P+x zdeH;Vw%JVPAgg9!&+Qn1$sK5<?lJDlEyqa0;HCY&!r&A;a|AV`*hn23J7f_t63ZJC z`{Oj2mEuci<e}zdDws=;tVnvBV=rZamB5N~=lF6llS@)#$K|NL8byC0yu4zE+IZRj zyTO&ST(Nx-;M+%Z9@x#XcyZ&yoT)HV+kau@Z5*kQ_}T)NoWT5w#K%2__7tNoX>-A{ zB1Y#NUw`i8#+fHD9K#RpjV=TWbux*e;7^naI5tRf>-1-;dV2V7BJfSRN6Q=VkG3CD zM7b&LK|P|=MH)DX8haY=X(=oj2d92wg(lgkv50-{kbiAOJFkcavO<8+zEqx}r9eh- zu0MzgoK<7wU|8KjE0zE*4j_#j2M=!>tkbW!50ynz@PldyJ<N%<%2_{Zt^pC>&M=o~ z<k-y)WugD)3&*=zJyL?*bDF~FXvxV*ie(T((;FA!{-&PQI7g)AU9Z%JO@F2h^UL=Q zF8bG%x29t*V5+`XF9_Z%RY(IDiRvSEidhCxfte{zzK6zALsPpTUp4XtE^Kf0Z1g1( zGW={nIg^WSR*ck4_Tdc34uHfD0f(_Z+51MOlqpR#K<O;duD?ODgD?q2-my3713wWp z?r0kJ3#(j!znQ>3)J44DmayFx#3x=TuTg}-`FdnMG@iVaGsA%Fo&(1Uf4;vqX5bef zw^D9O)RpDGe44AcJ2ah_nUFN+q>3q8ako@E{?_)-dD>L#n~+UbD1c$sN{$jOOFS~J z=C5YfM)diWMY<W4i~`^)KAJ^%mb<~EkGJ=JF3_kTk^K%m`8=VfK-U{UOMgr;o)=HT zGPr9Mr4hWn`;(v^G<aKnTu)}TU%zM66zN~30O=}lsfdr~`Kj@dXEbak&sok*kCH;G zN~ahTB$XA<NHSr8?hseo1td^F>pf5yFP=s;pL2Wt@4=BVK0fd_xp(J$-RUn?VuD2C z{|QW#8F?jcJihJ`rPr<usRiOA`GLvBkI={Zc0eZP0@f_9yo!*z#dh>#p~xJb89bRP zox>ixH|g6FE4zA-%V>=#&KIPuJa9BX^cIDcNJ{-Q>|1@WV+Ua3aL>(OSIwi2kB&e@ zsDR=oULkCwHj{%1PS3ZsgT<Fv333I1heSF&GIzu%d1_W;bN~=027w|bXmk4zQQ^Ln z2VbJylo}mmudI#=+5MEmy)E)|9|MB$&rLTRNtmtFF73g)Eq{HPg4-M#+{H4JL9M?e z9j#@Vl3H|ksQb#_So9uKQGaEMoHx}pt<{MrO-61e=^TGadr@YPWUz#kvD}THKYO3@ zP{ApO+Ab!4?QWBoRB9l^WpVq!VW+p2Y_y@4)?p0={x&+pfHlm453W4`+h|{@9)!I4 z5Zd^loasOpn|KY2CyUKWX|WMl**x1tA+xLQ@%R-{OBX?J?AdPx5=rJUv|E9Gbi)48 z8p|Ksd(S^>q&IqM>3UF;^hL1Oc62ysQNiz#(i|r7WU>sk)Ux8R|9SWfIK#q7vnYb8 z>0F%lJY4<0|Ln!x6&^I9@5V1Bw5rF2Pf<u9Lt>TxN-TOC_u4oioaSM|crM*n-EoKl zGx8T{%oi2Ybsz4Rmwce$h_X5Z2l1>DPsxMWIg$Vah0jvO51HT(WN`%3eJ=dZ4n#j@ zYr&_^AOR~f7q>jI7CCY47m1-4N0x@+LnK<A*tQE*Vr1~pjL?s%vj?vVQgsz{P22hR zz4);II$0}B-;hzW*?PmZ7Z}msA=RW?wtw@1Vv7B1Ap45e@s0`+7(6l+%%i}Xq+ehW zH8}&z;bdsv*mMP8NiQ#x+rFSj4f&V>e{17lHM?NRD%MXZ*vUHFy22rMwvBFk7r@9v z;vu1#HL5{{J{V#qHrTa`br?Q^#Vfq)(Tq=O6mBvjI>v1K-C<MkiS7Lx3rJ!LR}u&X zIURolO>@2=EMjIAX-l9m0MqlatykK<On{nPb)j2SYSTBO39oy>6v;eks$MTW+!JA* zAaS>^A(4m*i--h1*ffq@iu5ElUi`0<E@n>|MPgJ%zk;gJCgz#YN!}0$)GYr!Y*sPg zeWSoFH3m_AZprO6dfWH*Me?9%u1|C&rJjMB!h%)&9V-W}{87r8!zH{MgH)ZspvpUq zYK_SLnH`j365?^~N^M3waKqPOy~kH_<?DurUq@@4E3y;61-+G7i~VL=oM<g(FnVy& ztGlgS$j_&4KgU3;(l88eaH0_jkQYp1<HM+srI1QOvl<FE)S8IO#D^oJC3CC;+M4xd z!=1VO=EBQ^mT4C7-I{=XZRce}oLrpd#Mv7p3)M>Hq8Grxw<KPqtCTtG(|adkNM^US z3cdvU7O4)}pR=F`deMybSIeeMIIYwmrU$ZU9&6x(I80kB{Wl-g-^_iM@PQ#&n$Bty z0QcmG%qU~kJ6>On^*5<daGc`lYa>I$f(2ZC4h5)lV$3Z2lJcskS6Q1?1)t2gd(dn4 zSb;F32SW9tpmi;*K|c4gF{BS^sv(=(Qc|uW_Iasa+jR+3c>&)5?#A{#vW*RV@KQ0p zow|~;oAzvOpXZ09hPB{pX~n@Gs3`Z2?qQxOX@WvEJ4`B3CfC=-{l2bnB-nngjHfKo z+wo>-YG`6_&O*6=Z@}Zb0)fcd`#1Id<=7Qbe4hZQMw&f4AVb4dPo5w6bJa?aie*ym zhX)0Hv>iviv~kaGc@8&S`+ZsCv=OE1Xz}^+Z9Iu1)W`t$kv=5I<nn8VUZEI%`%Js9 zl~)MRYz2a+<^wn_pZS1u^C`S4lKIf6!4j=fMfI>EZXvBo0$TZ*45jrmS3%Y|eZbe% z;~KSVGisCVR`?mzKcOGg<;@-RDCFE9a%eUEAnNIRp#TLWSv3Cj-BxGx8O>6#+GnKZ zHHgH6f$No;?Yvr=RH<g9kb|?-v`G*a36}dZzg_=g&a6!afnteI?7%?m$*T9pv_R8| z-@|gE_IvxX+`H0o$^6BVJ(bnRpw-cd;euADBar`tF1It{Xj3j;F*u^~C)PkyU<{`d z_r$_!=zcBs+2qKLqxm6u)470C5ffvq^-=$8waPCtUa`WDQ&DZ5_ln!9QrBE*(6kl~ z`6HgR2Jk}%aL+=u{ZU^q@z<U4jm=R9syYvHXH~BIx9@&-k1Jd})zRttP17b@2(=1b zosGP2RxUQZB=!6^hkce^DO#Unf(Enij4Jh6z=u5=MQa6;)ak^!Q_Bs`W*l*&j{5WK zWwOQmO=MDYj1E5Xt=0DYdJG!|UfN3QHZD|}K91;CYMzG8{JeKJJ_0c-x3T>rXUc~z zZ!Ug5LQKt5TR%ZPTYixxzk(=>Hy*{8I!~JMbVB26P9!K6Tiis@r0G7wg8W>*Zt2Y3 z2gdz&`}Po|JJ0<IFY;Vd6&}OCDJAd4$4+#;I+@Bc{$LlG4>MeZ6a^t`Z^04J5AE9C zWs8<-?llaTlySw=!cE~PRIStO?x$Rb4cd+XUT@RoZaTka$LmJ}VUF5EKI)D5GnG_4 zw297>^KWbCxecRL%~bK=)atK^He9!R`5#YbSEZ~<@cnt>BnG86=O%G1kNFQGiCpOO z%$&U`$NBs@RbduYAMJ;jY_~Pq{)SXe9*JD7wBrG(c;0@$v)MXOQ+%e`18ft_vv%Gd z`?SkWN_#Al7j~m9Al#s-hA;q2S*X~fBb}?wa4Rpb_%${AMnsup=rlABr-s?(f(q=K zJRLdw_BT#?vDR7+r+f@3GFM2>n&G5bXB$kP@R~B(wi>aRGW~8{-dB6+3+@)WtDLYg zj0~J}Gi{L`u1@TI(9<6vy`OePrbvy7k7W%iA6(^eP-|Cyzc45nO551+>+y`|d2{G@ z-Sr3JFMjTNf{A*WLr}fSD#Jn!VdvrzyasimHy)w?Wt-6MC`_@!DuAU>`?alo&NiLo zLFpb(xrO^rHd<Iy>rac1;3T{B84rk6p;neqM9O@HKNpW^@8;octk|MLJ_ulxL4RKK ze{+QA#Hx6D*JoAB=5*N=F&=v?(s4Ttd6@Ezp9&>Ve0Sf5U!~pj0B&L?(sZ-phy#D= z@B0!9JROj{v_SYR+-BQYKb#)!-{Ws{iS>mOhMJ!qpq;=^Bv@!sABmMGU#dCXue&BE zTf9s78s>6jN(WGL1?4fWH#>LtFI?~9SIYFMEDmsGp3^rAb7l_89h8aB=f~o1PI_I{ zuL}@=88puo^u9ccz`!CW@qpBPvbqVE{z^@*Sa8>xRISr-mc}!FD0DrOkbI!w5)`S9 zml<fzFNDq8lv;JhBpfhgU3eZ+O}fJmR2&^B(H>R&zUyYs&v7^QNUbWs?NA@|Uu_6a z3?|zvy_$~J(33g!7#+XtyGXZM@1{=p+|{6(wfH9wao{$@;01cZmV1rclUT{gMVg<> z=`c?^OpI+Tzg228zYlP?3B|L`k#G@Dmw_oGDA9UK8WKeIZ|QTyO{9h=hn46%7M!HM zI+|-&zmeut=MRktU)>a`gCn5DQMA~Ch^ydn%S$Mb@qgj)4xudGniHC}QMc|dJwVqw zE<ww$l75>t!a!5k#-d&}EA=50e<xM%Ju89ksAs-*6%PaWo*??)tAL?ME^cNA<2?HE z_MVSlocDyVRC6^w-!o#o`uiTlK@`pmP;KgLR`tQq7#l+2`g_LwuxlRy5#h$s@UhQb z_eKf;C!qlaJh0jt<ARh(s`WQ+=K{s2EOr44w#@2rU34A}KA47WkCjZN`ZlnDMY}Wf z&a2I8`%15@8~;`l)`^2T4yG4+;;iJcW-7ztjcsoFZqE;lP6!v(!@Euw#0?`5rxsq{ z^H3sDY<&e&Cu7)Yt@Hm>BbTh#9JA&-3Z0vc&p#D8ds(O|9nbJL(^!l=h858+4JyL~ zMYNdTG01!%eceKCh2;^w`po)v=LL-5*t@Vzg|fll6>3qcA?JM&-c~jx+SOymno3Mb zT>zR@G!4_AdXFi~h(U(*T-!E>hORy`jP`{BSLOzAE44>1r3;K86|=7uO5`LAUuYj` zx{48c2b~T&Zd=B>deq)72jz-_%K(?Esgk|2>UOx|hp0ZT;H{F$7Ufa`+Nfq0P|X`c zVpEl3DtuYb16>W*&Dw-k3xGRA5N{&3-jS^Ed#U~k=hO?qTc<>rAlZBgE+cTbM#aUZ zL?xY+(+bYCB;iltj=4qyatc{<SWUd#C8^G<iFoh%&?5i$&SSp}*jyul&Gj{LO0`&$ zBI8Y{(^WxzmVP!lOHw}LxP>0M2*6*45T{C|v1GcinCO$m=F^)ZshHT)^}rUrANaKK zM_`?)rt`orXsj(pM$aQ?vk_HKrf(CAQo=BW+`RI=ayhRV1+Mh>K9<*=pi^nY)g8x@ z@ToOw*{hWm%J>=!`gyO%Z89s85qds#%T%%v302E7%`Y^#L(dVD*M2z|u9~eb-j1q3 z<TSn~BWWy1fZR*>2zZgD7DpXdmz-a|vep|l=Pa`1W^C}zRU#JfHTJ#_rKV;T<cJdi zl%G^&?EI95j;AlQoy<re5E$@G)tv*>^2%WYo}WsEBN4)tEg866FYCoOilp{WG*_4o zaq`{ee1;ryOB1YBP2&4|+rntMg*<GwZl%6Lo!~Sk!Xy6<h2)BJiM8BWIxpmTrd*N@ z<kH<v3NyX1lw|%UxPg?x8yy+1prK$gjkG!Wb}m-#Y^3cApf8rk_{(K&hUl+vgeD+8 zQ(4T&S<Q#H?bklgsk5u%UZhuqw(2Z^{ZLtr&VwLp0s}`?w?=zuPDyFjBymxhPuKFR z!nJEy(D%{)jL4}QHKE%}ulXl!4hKz`?ZbWn=1IzudlGvaN<SPnIC*^C>HD39F?swn zFLKI%-sd)&_`s_YodT})ia0rXC``_}h%w-GTa30pJ=Ax!V~9HmxW<?_Z_@5{`6#ZF z(ZiBSu7FO;k8CG+#n;5w^y5|N_9xV<sn{zw?S-N0<h;cauJQ&+t6F!<`zmTIUyFrY zuTDo}<H67~p?C$?YgPk?@$^Z(r=)CM4);aqf%s%kbMof_<1Cgu7b2gBlB;)kdl?$M zLR-ApAo81gvP(n`hOruo)g-&ilG$n_#M_ZR$QxCi>?Ow?9Rpt8yT0qM(4Y2zIKIEl zQ-`lmeit{;eq_`{K4Q>gy$?+7vMVkk0`X6#94-#UWA|Y1C*cC76u^Wi@L=8HNt+)F zm-I!S-X?{6Kuq)K1pK-`F61Rb%_|*EO&5@uLTu}E3<wQ4eqEg}WZpN%>ibTl`<4mJ z@|5r&WRa^EJe79Pp_8G|&#t<~^8NP9b%z$qCv9u<&54LNj4tLp?fYD3li0&kNIj^c z-cgw1>NAl~zH4hk@=B^anwT(fF?C+%Bz!w(Id9FB^O>g2b5h6mBG$ldTFTeL_cYQ4 zl{NLtt1az#@+9-o9Vc6*XC-~gnEdY*69>hM?&%9p-?pLZwl-<2oCh7`B=%1Sa$hH< z7xsO~*4f}3A)0Tq<gRw`nNP-9^z};d&U@dq8O*KG5U+5e-LnGj@_?teZZPHH1EEw? ztR%RFMidsbt5=oTE@@rR8b{acSm3}>ot%#6eNFW!De`rI@a{#OmG7UQ)y!mjdB?1d zGVZCS_Vxyz{Uf@bPm#G11lc8Xbdtc^^D^6SsoRp;H?S~JOcgB|f9Kg+Vu1MFV3Ob! zZfsP5-ruZYqRWJbJW7=%Ggq8ek{YsI-_RP-2;`on$54(QkttFro0S*RyGW|mbLy8L z-L33gGKKlLw+&yrLwG9mocqV$vu0Mz$q*9e-Bp*>y^19VvZS(<h>-FRN|5-j@CN_N zz?iOO;B`Uk6Bx839V{2*@917A)UQ@)SC*~PcE9~lPSAcbZ`0}*(83hl;^UP1gh){7 zu{`Nwc6Ses_C!DT*8Ak?^GLRZZT`l78#`}XXCZw1@xm&3?=jpu*l>Hr-3R><yu@X# zR*qLn*W?b0MATSq&ar<4?bfpCGbQQ^pSsv<uec2ZQO{q0aGB&97c!~Ff-S*`z$SMM zA*mu>A}QZg{B{diQ`X4mvJXz(6jZO}^5M&6?S{J&7nsPJPa4(oir00M{#OEGa{=%t zC=9F9OFzX$(m)zvV-f6^M&?tceOMp$$MSU<WJ@cg#3D>Coo`W>G<~y*woDkJ>8CGC z1Qt6ThP##+<<w~thg>n7S@q*(p-h$Y48e<Dm343%)5M<1R`*)NL!lP|4*Fe=RTZc; zwC01hgRv%jE`7E94BwMn>NT}UNS&?9U;`E!04_6`;Im7M^QmBFSygiK$ki@>73mPO z5KMBDE-gi1$oNtch@kz*;p1%OJD%ZO+{mo9RKK^s)AaH(<sq&W&-am(><1L|Mev02 zXouq>8SAQ|MU&2QBVum7VGAJFYA;=>3~DZ^<(+ts@Y}P+4ADv8-1b(i_2Y(M??DyI zQQLv?;HyqMyH+BW!f8}}rsMHL;p-W3!R5m3z0mq|*lkx3J9EldUssF}4;-K?9vl5T z=z3}7`U_4fgiz1{)-E}jm~sH~3hDSpas%~qYHrwQ;`QGq?~kN0$$dA5XflPyiIuS~ zwmfdS>LFz6AZrZt$1eEj7scC<$YcquQa$hor%cmNBcU5$xW}2A;9eJ#E8jy3l1KVB zXZi*sf9OvYEflyhRL{2D1cO&YWll>-{LHmF6<&giuYd<$S;?PM327x6MpWHYNqh6P ziSkCkY8q^M#GGPJFYMX{*sS$916(~-S2-c3{P?!^8UGqr<{OK#jWZA3zB2CQ@}Q`H zeW0G<08A!+Kn<_i%=<_)5@$i*l*T#knUmcKH9pl7u_hg~d&;mypqIC)^DTex;MX?; zv1p^lBzer8acBu9XNS0Nb?LBakokcaT<rL?FRv#(!m#q8W%VU@@JVj7a-JV!Bd%S7 zQL+peEfO$;OZY!Y$#y1n85qnLIkvu;G*o6!H#UTWO7$a|VZ^X>apdw2j8i1q`J*qa z)4ZGH@YKk?(!E7#Nve4J$xW7)lIUfX9bH8I<sUO~o-tyDe#W@GK7ZH09q%EunDe)b z-6Q*A;_caPbg_w=oWjg!^ZIHILchmaXtHmGy~CziR`L)RF;u2*x}-lH!xsOe#$2#f zYlU#f_w;J9wMJg*!#$Uj#v`RHqEROhOtp-4!3a{0wEK2f=xO;U*1^~EAnDjL5=$Z# zZSi?6oKl2VYUdY8O;$Ju!VHz;l*VVHeJC~bMCAgwZ=qCcM|ZzSjZMfdZc=;<q%_y~ z%#l;V0dTrLv-|KRIyontLzDPc2WYUKqIs7l=kImd)fT425xg`8TsECfX}tf6SH7dE zLvd2op@H{VcILAecPzRtYoN~Btw2U!>$S)ar-vsLf+C5Z%}Q~sjk8kO>a60%e&4#C zZD$B(j)aeigvD^|VGX;@5b1?s)^KK?%9*8I4z+G520wL$lhO&vAn%tfbHrmN3NKre zO^BHAaUQtLiq+b>ydo`sJ?FS{tNE!_0QdoYG~~Pk_rD2T8eH#qPq*+$LA)A6a;a|V z&)<JL?V|22h6pitSO^MkEXgMZ&HF2bhb#|6BT@R-I<k}PXX`Xbtt=HDW+zb3eU(uD zLdztFFfBxGrxYI%dQHhwq%$GPj4u8k`}yOq19+w8$I+Hd@wi!-D3TBY9wdvkAT81U zOl;@2kQX2=A7SlCP~3ddiQ&xhr8XJa`TaTf>X1XK=R$ElCf;6g%K=Vpol&b3S9jWC zYvT+a*+>jOYmDO#wOP?Dtc6I-@ugKL&<6QSo#cP5L!4GBU;zw^bMe3(VjS_cA??2| zb>LZT?;FAkaeyW>y?j)16~GD7Lh$g(%=hSy8X^`^`kVKIu?w)Y?+g!!FM2wM6tc{Z z>h90$fczUv8~I&+0UrzH>5g0Y*y%{CC{7aeBFvQU+2&U*&N*B=Qm0^4JbAdruL>Eo zh5iMj3;tUKemUa9DRxo0w4~YBaAe%$*oD-(JlIpYC_9|zwvN64X~!)>Is-~plu-tF z=&M344+9Og*8U^p5p*J3rYbp2knX>RFVZeDY)miw#o8rpjKFB{ud5ez@BcrpzA`MT z_WN3-L{d>{5D`$iW9Sf+?(XjH?hcWb?q;OBW9aUNA!cY8I{)+N@5}pM*L<2!=RW7& zwbt5ucczyzZG7IcA2OM$QlKGQo?Q_mIvAfKUlNZt%7D+z!{pLm!9TnQnRSfRVdiZw zONPZD5|h!GYN$sJvL;u1rB{DSrCQ}oar%_7rjiUj4+y)chaCq=9GD$)6GXM!rDj}+ z69meHsL%Rh8CSKd4~QHWXz~2R%uPPOCB?+JkZ;l`5H9&lEAf|oKP`O$#uOfslxIlJ zk*NQ!Nk{}O8KQ9d?Bn-496)J^7Qs1sT7pGx^&;$WMuR&(G?4s1uyse-Y`W~#wyW{c ze>^2ECwlJC3;%QftPe-Y@01zQhk2mZgi?gMk|emj`HK%9AZQ2m|3!}J**In>>(E!V z{yyT+;Y(&f9I1OuXI!Xj3Zv<HNL91inDoiV16&zS5JGCapvL`w=?B_rc^9Kjpf?}e z#Ii_%L23kz+gb7*&3_pPl28ht3s!nUaz31JN@PV|T3Yzd$dOr)cNVC0T?$v-D4Qy} za`MzEJ-9j9D8nb+y~2vS?K!6s9Sj*hGp@p%Oj;kfHTDnlO6qKeasZd=x<L7LPIU^1 zJE<3fKAh6Qemcm*pV~zT4PiuFv1_v_7j{08y5gZ6BqVmmxkE@ktvpCSy2NdoasYnt zukev<#_H7pYx5^#gkeh&xf_pKs0Z3VhN(8^$E8?C5}k%%iBUkCHI1^A6kV*te<#4v zA=<c2`|h!AY{-^LoWoZe?ZU=6eYT))(QA3=k88Ovq_lGT4Zf}^1Mp0TPRyND*R?Us zZRew^f;?tBr4jU?sHI*5oK$$2k3GQHi_Vn>&RV4~V5U4+pS{*LO?*3r@ZgcA=Ztj0 zWiH?UwquP0Kj7Eo$mbqtjEoqGV=6<TRVB8#=*ITsd@r%n$81_UB7ljvNtXTeXgkmr zMceV)|GvVFGdisVy>9DIvM06Itva>?5eold1Rq;Xvb|r{NKL`MWPUEqmtafhlJGR+ zIkK_Ji@QO~6%`qDD+OEf;yS5h2@(SuscM}Q-ftRixK6BQf6g=VCRP{leU-63`I5Wl zDC`IN42iu=reNDg)4*_tO^?M5Cfe1`d~v9W@GUt(WtMd848p2P|3L6ro_3R*8SV52 zh{ygzzVpytH%no<AXWo$9T{BZvoo|6>subvUH!T!Vc??a(?9qfi5FJoF%v<F?(Rc` zZ?mAR{`UfHvZM4gwWWv;iUxd{%`e%;Cpo{WLLG}+@cA7Pt4Ohy?G`nk{o2I})9OVE zat5F;4lp`LNrNRtYdI{h8Pj7g>fHkXWW)ml!)cnn70nQUMT{E;%P!2FN46g5GPdZy zyBg<iFN2+=K=<9z*uz0F%TBISXeJZ0fEWOJ@Q;(99t!`XAQ7;itpL))9~iSs4B{eo zs%8FNaJT5LSjih9H1apF#?fB`{bmb1Vl4)m=DuF2C&^pL7Nwb7M7AqAe2#~Q)#>a0 zHg6KwV;$j{h>Rw$5yepWXFAguQ|+WrID3%D8UN<g)jz$pC=^W8t3tU>FM3^vaK9xS zMj30Y+_`e8lEoh%yc!-)5O}$M!4=3bQ!&jwiu})Wpk%)Z3iYvd#lyV1oZ8-gmpGiV zzPsc0{y)40eg(YP&Sag{aP4C~s<q$Aazevg;k&ys_sErS&)!({60Y1DgQdglFkF44 zH)5*LGBkvU$&#Xf#*Ww;J+`6@xX>{ArLA|3Tf*~{G@19d<Lv4EAP&X=I8%{d2SuTY zKEN}OX;uy^CG+zqCq5w+-_h4vCD#A^##9gk1h9widf?>yc#x*45#(F~j%oIDT!9iY z{Y2lhPC5GVPc=3Df@7r@%m(a;^=NTqOJ!83Q^{*A|3di}F8ca9iW6TrF^swx4<%hI z5X+;*Tm+1^M6fKHXp}jn6VY0j`P`36Vu0J7v2Hhv3TjU$b3)}SP22_%sKX^2<uSJ+ z4jHeu+1<Hpk=n<?oaVs!;<Mpk=~uX8wnDAI;ruFc>7$V0l;d<BXckt(icB*FSXwLF zCkA7lFC7HhX1TpB&MTkm=^|#WY^^y-J}3+|n`RgP7v>2&J2c!$D|Bmw+i-ugB{C|s z>EOlw)ji<IxSt}v`=Io__t&9+{9(joTra;z>D4RiYYqkOMAH*ud^`99*C$~`u|SYS z#!$W$eUKL%3zErz2&PjU>>~d>fT$Z7`DM)`u(T7SR`kW9`uxW7Y4ty_eL2kaw$&7V z07(4;n^kId5O6ua0ctn3>=df^KBkon<H&iM*~ja9CiGpAVEbI1y<P0APqvmSf5P~@ zseN=*XFl@&!CQX*|7nE?v-xZcY7L;DuIjs3Hkfw*-I;X$;{M3}i+(U^!4z6<B_T<~ zNsjcWskyBc_4~H3)}8XtjgD44y%uFWTU}U=#rKD<e;#Fc0zT21Zo0u;p8yaZcIfd+ z=H|`AhK6rvsSGw^7zAF@178)~pMA`3$>^-Jf3?>D*Vg5pBhoI*Wyu$Dl$MoAGd}$} z)|1%2l(YZ&`n!xG_0vHi&%KJ+uyf}?jg%-igIDw@KWpHF)jw&BxlsJn;AeVmwk$Ca zRk2Fh=xNBmIL`Hc@&h*GvHYh^dAiknVUGYT_ZD+%>s*nlHl_1(8oo+E*%2w1{=+WL zHu0hz>(}bVcgIFVIGl!0--GQ!Y)bj-6^JV(i+w)mM#DuF%_2ToP^UnGb1}m2bl+=) zCRGHeNfhz=PS=G<77{lQgAVXYRNo|7QV`>D&5>$MZzZt?S}mK8<fk#a>jadw{v-PB zH>`10qm$d$Y&6(>e};(l7f0wTQ2njckv5$WkBFQ+;&pz#9psvwq9l|iDGFR;Si)Nt z5~=D@f(>o=>2*%7&dFG3$&kSQc!3^FhzjXDzEW4-ttVQTSFe?;I%A9#$phi6s7Ibo zc>FxZ#iVk(j4{)jOY8w2=#ht#R4D8ktzcZIfr^HoMJB^BzO+E2jmtPUMJ!LHWHv%^ z-y<=vHA=%tX6Gig68F{c$R$@)n$6WCOVQx6&N|m@+KzDiZ))~$RsTB;VX1!n_s?ce zf&y^q5er8bY&pnh<eyLEIx=HZ5~wH0Q~LC6FiO1O;@!A!&HS=NDA?1SmtVL}?VGdK zCbxbob+-_+b=g3i^$zx~+3-45>;QhBA?YmP&QkcGx90Hd1CoJIn|#H#WF9C4j?bI* zr?IDed}s}+e=F@#)J!38@M?27?cs$z$4$zE{GIyT{OYf;DTLgu)w|7Rwu8|-qqE+) zs_w1~fQn)XULlTZc@zoE04-76T$rCTXg?cFJY%m!V#SL)hC4+tfWEXX(hL^@$!AFl z>Kq-g%<|>M(9FV@qyI5=tk9t`^Kbgc6Dy{h<o$q$qg~94vwJ<3tiAVyOFI02{p_ov zue@1V`x8a+=0isDN&`|847RLCVIAK=@JT>nWmmE4!dmwm#ce5f2T1qWZ#hl{@|zrF zHsE>u_^^2<#fd(<>@1yS5_YW3a=WctPhjxS!p{<Z_TQIFO6E5MS8%K^PmWZebgb}0 zETx8VO7`>DHXj12HI&}vjr`kcs_5sYGa0~B)9ssbpS1PD1}KxcJOC$mi_h6QY%6;3 ze4;APkSL3vxe12st;|;E(d6cI(Fc-|I&>?XEZ$}Yy{V)=VC|YWy+GX(+1b=JN_Qki z*ENi%Rw(*WWB-7?Y}Z^;!)R*!a52&T>)PPVBu}0(Gi9mua$_N0pme6Ff7Cb?x3SyW zP3Kda+idf)Vaf5ZSbx8ASN`in2Kf8wwiIfc%znzW@mQtYo7_T%K~nJ=O1Lnxe(hEN zElExB59@I9;K`y9jZojsI}#vCPDwu!Wh>IomUcq1C*~}3Wm%yd{ah5M!8;ft#;ap{ zTAkp+HPzLldbaDv_rPr~+15C@9rhA=!pwz+lTB;g8(mLXURT`$mGo@@(f+8#PVe?p z1ys~#Q_u!lEtN}+n<vUTXBFZEQYMkZ##JIXW;R+e<ZMesA-Uu2X5kPmsDn~D)6cTk z-mPRG5JW_lRFLtuMN?Y@pWiIhQwTilCyBWF>X+M@B{zNMzdb*V^Jr5TF4(1q4$`aV zpK}=6Lj*H!U>HbqmP0Vam<&MBv{jpzdJ7rAW|}X$oF8k}R>i#yrSI*fM~wphknMWw z=7hi_&@i5nSHV_kc=wmwh~yP0KGk@?5I8>^d_+St6dM|DbxExV%^bGzIiNONjpVO( zJn{LP1hj_CSg>o<7<~0UUA4`zq7qs6Jw>~eQjrdC<dXi!7wrb<&{2J@<UCNKOZ=iD zJt64$hrffvx0YF9U5DmFNSj-3<ey(|BS*_254eOT%l^%aVmS#0N>VjigR!J(3vKqG zDp0$plNHF3{n$^uBI{iwC2s1<Qt*8HWqPn`n|Ze7V6z)thGqZ0487DNz-5|5*g31R z(y{w1d>Mo`m8g`WI9KA#!CAl3?Z8@_i0s4Z1Oy#hHZhj0*GoXGm;3{4Yw$wvx)e4~ z*SL8_38xK`!(1_o%g{|}l_Q>RUiN)U<m)jtM+*zS404ikj389ibJ@u&kV#zX9hjJ@ zH^q+Pzk9^JB^hV`Jsa`EbgSfWU$pYX!h(Y)@hpc&S%{>Lhtn1PU&;hfvSe?zTP3`M z$hHPzkrL#Za#|~n@1*>%s<rFy!CiA0C!KEQC{d~4v?#a}bvJSVha>WI@OnH<P|R9z z11a6TA_k#MhT~oyN`s{k54iqiN3!mLE95C9KPDenyA5ij3Kx4AgP9q-cEghsljpFu zhgvb%yWu>+P@e?5fP4jBkzIzA!e^$neB4#<LD5PcQpv)^kmTFupcJ9|bo49{6leO< zSr7eEg>l)LS$395{(qFQNN13D=HBFNvW}p@W9BlXi<)yHE=S*;0gjWv2~HJ%6YRSY zCO@|QON|mG(ky)LD$kqKHL@5|9=q!q$Z6!PgmHI$%*ROY7UwGO6B+uF;#MZPlvVCr z4J)%+f}T++<MANPqWRx*$lOhqfm!7C+IeF|)9z!t57x%r4)X4%iuT)8?xr*XT31fj ze`!R}e_GYAQWZKyna9N1ZpVZG*HH%#8yJ?3yhP^UU;mgM-D|k7y8`=FV#KgK+d?<L z+yR)L^_2OPm^r>1CuW_iQkE2T^R=7yP}yP0!9^Dj4srk2(~+Z8G7-^-4y|a=5?9r7 zWAMH_zE=vQq#8H+TcC|uOuU1Wvq8><GzAWZ77kA1HxrW}su(gKE&-M+gX*LaP#R6! zV$gix;ClnA8U)S;gDR66ow6CpTLWW<TBQu)omzr05bmH=wdu!<!(-Y0Y4rkH4ny~v zTt}h_<r9g~rUh=JVou9M1!rOH<ZykuaGPA7Tz*zYsIkMM(es1Rr}>_qWfQ%n{Z_j9 zT2^X94PnVutazGvDlsOdq0h)abN(yEOkWi^1T&~L{9dy^I55}oW%S-#6aShaF~s_} z)CsB~y(qcF)?nJeQI_1X&^LIHGq!RNVOZx|nT1$Wr9tu84QWWGep)P|6`mv<)T`iT z*v$eNl=@}UQviP+2NtgO`d^D*DG?<a)GUTU%s>X((01g&RoZ#ReQnPlzBW)od|M{E zfmb6~c};B*8Owh4ESmu@6VrpqKPi0PlA1NPp4;E)Ry&(m1LN{=MD1Q%_q>Hhn^ahc zzRZ8yl$kk_`ySRj-el%;y%gyP?Fwd=_$*y5t8^RZyl=-4x3?^m1WhritV<&$KM+q1 zFx)RxnlDf)$08%5JzjSC)Bz42JdbO;6f4Nj_qP9Mf(UT(Hbg?(cc<^-O0%*EHxGPq z6C#};U9_D__csgG6I8`7vo_d7aa-uL+DKHW&9C~EH1T?9rp0~J@|d|yp!J*L&@oSK zjI`$P0NZ|Izml<m(=(($lx+FdmP~-R{s^wSN|+b^twu*G>%Mp#nY?<Zm|W5NNP+G- zubcE^w^?5;AQ3TWxW<X))9vJw3@RVhCkg2mEF6ay4p@JPz9U+{c>(yXRFZ5dqS&I- zsj$HlyZStOwl&#CBl0m6PqrZWLfdKeR&wnsrw-l5!&KGf>6aQ^jzTR~@_=Q|*2~E; z{|=(x^r2wH)OR-R=2IHY=?5g=IW;2zSfcENO13J5xBCNUJ%+ODHD?1I-VTj_z)c=` zTa2g-j(=5@<k@cmZms8l>ObzWNebf5en_}wdQcG|{Jr-<HN>k7-E4oPk6S##@s)AE z0n`>ns0l&EZ_4C<vm{s*7V7}zE7TRMo#B&x5HzXnS~1~rI=j4q!e+-vkGTpGh=#{t z`z9VKoeFh`a+8lQADp`YYPuaQulo$z`gqBoEWuh+lBb$25VZYSq&i<O#hp<F9V``s zCQm@A6PX>Gp!;)~=I9zIe4>eN`rEUvl~T&UruTcvmWsjP_~k5RbN|_b4;Sg4x9`h* z_YITF-NwbI1~W4O{DC3O47)XUi2HBD9EW0JERnV}&bk^;?KQbyag51|JWBB?dmq{B ztrH(OR%tHi&G5xT4l?JRkDJ<3jqym*-S)-nJnSV_ORTa}hlx2I9p~Tv2h^|=MpGG2 zneQJR8*pyKouNrk^_u-vaRyAF;oA~kqEOCsxO+d&95PHFZ<}~@d8S{vYnJ@_qCk^0 zL&^oA0>{1{Fb#}W^woG)qHbR+ma9{jD#vfVsdh#O`bfHZ=)J)k>NRMBcc{--c#Sif zDy**7i75}JVewuxKc}-iIE)G~Oh<DH&3}8w>|OTWBiph%-N6AW-U6fd*sMgJaX@Dr z3vRehEcLJ0OJ@p;X>05j_uc1LYV%LJEfarYC%sTTv(=u16IxuAvywE}C_n=3tE|aA zkow~;Su#mXU@O{FM={p}`fzatX8MOD*C!#o;Z0psZe6k>@WTb4$f%gfkMZ}(mB%em zlCQubU9?exf0mXzL*z^dIgrmu9-1YT-bFur`Om;Ujs%!Q{n81TT0}~8RIC-K%isWI z6(X+5lu`~Qgt@=7^`Hy=ppu=qa{=E-%JKW1r5qi2XG-#Jtc4}*kVNUL6g;|lu%ai8 zpQziDvTvasDfvfrLK>O@`cupM-Cy9Kb4|H4dcnPil!iEo&F}c*`95jIu2{~_KRbP` zqN*mF5l<^aFe$cp38%}8J(cqD!n-6kLgiPePPbkD2ZmSPQBh>$Ao{Os=m*Tpf?nTI z1S=_*rv|ysy`sB=oLZXdIC1*k>M-!6XuFzE4ZEb~|BuO2Owg$43L$b^Nf<INoiie^ z`)4qVFUMb{NVPVCdWwFh5=!rgndv$ZSx558g5pt2lIY4Vxb%@}j{TPP%xvAEy;{|# zOmAchZw24Px`#Wl%!Azrty<MpgSjP$GxWXTU>*8!$kZFW3H_-hIFQ8ZPLH4-zdlvi zlP|uHl{dysFl+>uWa!}b^coJn+kHAS2#>mQnhc?nG)fH-<RbwP$mQ-6m?JsZ52GJM ze?e{jbg;88!~|L>2CD%kr-8>}QirUj|4@dZsr;@d9XKS-#;m;2ANn_24q)<}@R&kL z=ki?ttYBYig3gxC_x=8tCREP>HJUO;akQ-SCO3bnWx!vi!#t)hpdM9Pv9HvLlq2uS z5wtqc62$X(6rtfHk*3_L=#t=-e<rdCKaM8gQ!TPlAawuBhn~7r6anT^8P-`xKzb`3 z+1&e_7DH`ekpIEF(1+#`Y5$Dk788|!=-9jbNi#W`#C&8J%9li`3CK;*$UpsbfZY_E zH+H%ejWkp%pl~YB=}TMWRZ+ua)wa*?bFmTvV0_V2p9r7TDgtLVStT|58M8T!r&eFX zIZ9paD-gI*dM;r?UOXFxUX7n+bkb?6Ss5!oI8YJ-5_8UfYFMUQis|uqv3D4iwYwc1 zQG?|4Ez$HdAfqGpM^>c`A*H@i&-KXv0ROMAFgW>|=;-kwJ)cn6_?i1~-~G*%;GL70 zbT8gm_LtCR6u^1%JSe!9r!L%unsd_boJqOu?RA5GYq)+pu2aJ*6JnQ)?||MWB-~=r zUWbU-Yf;W44J-ab36XDlYf^G<iy=2cl<+t4!0$?_G38{jTmm{EF=!MWsMo&I4iF<^ z{}VmIGW;j{Mp1*ppKFCE#(&8ia!DD=H(A%1<`xGf;QUuzy7Q@xzX{W;?qNg>u9S4H z<RLj0yu7$W{iPJQU-gt(dEwhkar0&bwipYR2gNPLqDlH9eoNpAJ{5ALgKBfC3|Lwx zK3_%@Y5TF92dzNBWRA<D8~T>C27V0qVZnTJNNguE2uM*$edQe1%;1yCAXcxOwB&e> zvX2wvxQ$;ITPsM~-`iOIx)SWvc;~ffrcE7r@e=N1WrQ~D1N9Z4O24RzUMqb``uZVW z{I8rB{-|h-D;S6}bVAyx4Ey`i({jfjt-tes=TR7k+0l$gD(0ptk=&@5@~)&_V`sQ! zF86kwtRQ|)#R+SGqgW(f>hWVjZzeYLk)uiIxz>ibMWMD(EDMJnFK<Rvf0p;;Z9Yxp zpT?<$#|o5f6*W-ZJNP#*ChW7vYzVJbgZp>G{`Yu<qg3>otv@k2PwV~3#l`+{C?8ve z^<KWk$WeH1o+6NN^<+!n6Vz0Yos8LrvBmLrp%4R8(-rqxDsBtUtE)PRn{Pt={hlB> zDsiL2y{P9JwOBGWT{s14m&MXd^pLOMQ0|TW$d%X$0(bu6$i+)$2l-|kys!qYdjtYK zSm<`%1?w2I1>VFZ%Rh8e5r_8>598_#{iE)eGv5DtrQpAA+9(T8edJQNl{`@zu{x`` z5QqCkx0>Z;(cl?;O5Sq5zIdFp%I4`DY@CS80t!LGWRhrGHv3lt0P{EiybChd2{nZQ zxF{oAn?OWloz1L?M?E%9_Uj;@mSqi@#l#h0;yRXdH>z}n@jnYiTw`yt`i<h@S)x=j zWz_x=_E+`~2Ztr}F26d}R`E6_pN37b(`<`Dzq?=`{jkmLDOpwe@eX&?jkVd|1oK5< z&)Oi<)==X|{?h3a5VuqjkA!a;mbfeRqm5U>h}4aH_V64v@w>|OXhi=TIn1RfW_|6C zbkiZfVra%G^ATCvwL$@Yek+oK9xvhNFTyeVGPBSATVO)AjZYh1kDAlyCcOXG-G-xM zT#i8fMpl6)Bip22xF=Plmh<sb^mQ!V@W??MV0pD+4)&IS5}heB{J6Nx%jST-niB69 z8dxU63au9(QAnJm+?SAqszWm2iD^0sFRmz%kgA-PMquKM+?-+=>cz!RgLQL8L-iT) zC1vn*2G~#Q-J51vlz*YpK&cE<gUk14HIyxp_B|H!-+$p>td)u_4c-MIX3p4mRAb-} zB@tNXxL2WjJy~GMc=P?_p>MvRMmw?%o@rVZS9*lT@Lk>FL&*tr#|jDZqRDLK&6x~> zFp1l-1O%|y;C&6z&XAOkRHLKoRL~)=d;fEi?j6x2bg6d1<~-~(AC1PS3Ff@5+@aS4 zE(55It#%&0_J7*P;wXreW1IeWt6uT0Pjad8`pO+~mdMe_SEx*f|L<y9zFaa><9$gh zSFrUJo(xGas@LD`E8}UymMs}tu6*gVYL2N}?oj6xTCt|1k2_&=PEQ#)i{T9pZ~nB7 zo@^XcnbSy>5s`}uHpG)o<ZZ<Xl=mct({aA0_VttFy>M<Nh0iG<uB_>c6;G!i;tu~) z#v=jjn?zRA6<tgIUv;g(_Vu{We73r;72_s6&YmW*Oi9)H1ri&+-hw%Dy!8LL6J<CT zZjoF<MRa-PvX@k@;Rzm+1l|R%q0c=$nT=Ojv1-Rsei7nDmI<vVBtraY5-3E3Hlxca zjm&{jykQ8g!qhh|Vy$IT3FUts;D%dB!D5Sa7Lqp%Z=$Hiz{Q)eg?)i{cI(8%PJs3d zt_UpE6mQ&DyvRw?*ZYH~@MBm*vf)lS?|cN|-<OvtPX7LBb8<;}7@D3a3C+E<g#3by z=e(E1n-tW=Hdgp51DYuD$P-GmNR%jGc`r%1mPD&ussfiM&AR^rC*Q>UI~5L`YgEb8 z$qTYbzI1V>tbwrvdRC{k=zJG=%kz6tB-%*1fD*3NW+R07H43(pPyO6{D`7jWe<5yu zZTQJabhbe8P-}D0SGe&vVnNV&Ry19X$CuRlgCN7+1B&QybR2$_kFv!<-vPt53MP4` zm2M_Pov^pizOuPhQb}iB4i=6|S>at(__MevcTT&&+gad37I;<+w>0tL5A@l}l6W=D zd+CY8ZY?&m4jOG<XmEe&x3h<Np{Og12bcDJ$&il@QcL&64Dbg%u_zgiX8>&NF<jUG z?8We&{FV9P?1oqf^lg=%C4TQSGzJP9It3J(2~)CtB^j2lPGvy}bSXo)Zm0rNn~z5e zMvmmy^${&l^d2_YU2yd+HTt#Y34FKXdUL|lto7%$Y88Ol%gF#%6AI$wx5)jP3fWg@ zb$dL5wW#X)nfoaXPv;|T0)pdb?3ewh#QSB@b`F$eD+Kb#$ysz0Z17Zz;`-teMIOOt zqF_-U&|F}=?5bj=Y?MQ5@?k7B>#$OxN1N6{Wo|d+{r~*n%W;h$TnfY5gHH0Ls=XIS z3$8z1P6VVvW3VPCaeLT!0Ycz-#RSH8B?=XBc(IBM$@+n#db-&3I!v)i3|fMcc%!QN z2=uzuKa&`BI#DwF&{52v^aL)65M?>ybDU_Po@X1$6r@SWhOxN67pnb1trkaft-rS4 zlmGSli&#qvt#7|b;f50?w({<Pag`#Z?L9)Ox7p*HNsO0eWK>scOK*S$qd)ae3xuH+ zD<<RlsCD&WQ`qWBdu$ogqhxc&JNk`ZMe%JEVm3pBLx^;f6=Sa&%@7j`j)+I9fS@f< zsKUyFg}_fh^s$P!RLm>&q#kdf@c!`bK_Z)%&efm)fAFw_37#Bp&iaP}2srV1y_rv> zX;PKQg-VouO<4%UeU}4d<X2jW1((ODk|z(!y>*bF>aqXod?>FlD1yyvfBHStgQLHb zDX)HkF_E^F*uA2V&rz>aNSmgP2D@j=qsy@<XR6#EHIs)1Xj5#LIE#W(9OfDd!0P*3 z;eSlG@7=<mt6Ww((+F@#<R>g=$axwP9-8(1vL?0fqPF}oSFP;&*a=MGc|pU%vbG=g z9YZuV@H+`Hbf#~EG<3SvEkf)yYQ2Exsb!Y8#dGpgY<S`EML>bA)^%DIm+d6|iLwH7 zy5mP6AdD{bnTuYW;@wYYEDiSnB(UZk9P)Rc1>xrR*y93<;({0ZBMZtjWmlX*;86Zc zPu!ir7928JV^wMgZ`HDXw||`*@7Qyr!mR`%H~XVhd+`RnG$0nev&q==n?{w$GkWU2 zkY0bFa*43%p3&uNAchAd3}$`MIp}2r%s++-h6DRZLL4h*51zOUZ)ACW&ZjMfVlPp; z2;BEQp<gph0axu^ti4#aQ}cp>{Ro+qjrGJc{1_bE9Q#IJ;wOhyEktBL(2~n><i+SO z{3uf6$dD*LfSR8Wc{UVdW@^uBXpd*)@k{b;OOTXtSygFqPswF9mn0|p=YW6>ua~|D z-OI0IYsEYPpHdW#RQ|fFO}3Eb^L^iFOfL2aRfQQ<bwL<h<ygcKI~7gbM?~6?_`7{M zY^c+^z-%JsHE!5epo(Ov^onQ@_|ec;`~dRB)GoG7EkY~;{s~+m2hXS5?Tk-N;T$1p z&o|+)4{PT-5tIgInjx2dg6Z6Pd0}g4ouT@a`&`6*NLzt-4>xvVdt3@sAIU7AwbBi* z8vHj+ZYpj0eNGjho#DL+j3mo%x^Ht~;H-wb&rYEwiTr7n20U~(8+teP(QG$#)_al0 z?>MyGth@GdJ4o*wp+QMKAFg{3kJ015F~{3{hltNwUAT02puV5*_dJ{p8dkb)UjjS& zPxk3F#0!6&B&FEpO<;iVE^pHAYpEWx6Wtu@Z%>UA5Q8<&;OH@47%C(2`(J2nz<Tdh zZL1mRkTJJY*$cR(rxp6Iky>y3pkDMub;sGq<TI72)7YWswbvW@syDT55I!8FU-a4# zyS{YuZ3?gYY}&Ja*(Z&4S`rXhbCS|Vi=K-=zz+MLGnHYVxDtk=i%R7QgS5tGI>yZO z<v@5~RGo&cLy|hIVP+2$)POJg8xPrS#=U26QeVoC38~3)m6?|^+Ys{FgcMy_x$mCN z^TS5`fe&@zg_Sd{eYU*UhQ4h+n`vu%eQ(3XYR1m=+rnP;rvhsGXuIv<sMK;2n!JSR zmrU%Q>Ng-CrH>WL;=Z`wLxU_>K~uA%)a|#k)L7nk*VIFyE)+T#oYZK5H#fof83{X) zc;^nSf!=NV%?F!^_t<24-k~v5y-Jw^7_!b@g)IyayVLVF2}YmGeqP)Z$6Q@!AEp%q zV`-^fsNa+)WC3R<(s&HD4d}9`F|ongV~6V`=h^J&AF6<_Hfql(^*%zW-(j>A7SSZO zWk2%XAc%OveJo$Gl|@cgRmHhjTKJVwaE`G8lr$|RH@EpZ8@pL{*VC+x(a+M$tDq|5 z1g=k;KG1bVll>EEdAbo#WOnV}qa;sq-{i5@*<(2QfY7{^ds%C<!_v;taz&Cap1C-% zlYu#2l8k<Ts~5?~ukyS&5xAEGxWeS8VK~;$-F_#Vl-`$w$@O(#<@&t!NoW6P^4eL~ zmXpY{wn$dPx+XztziQ<Q)-R#<4c~dl_;R)66jrBJT5PH(@16D9OA83yV<rk-7%+_D z+NbE>i<12<V7mrNdcGH&5o<jAm#_gTZzju>7!`%;Jf~(EG-lMkNz#;+w6GN~@i1HT zpZ0tpWT9`=2IBxQL~lrGur?nUGN!cn=-&Qv#J=>2`gJDixW0gn%~$md^KCPP`15dS z#9dTt19czKeVw3NuHK)MQyc!w6{oxtkInm2SGJGyo-D>OhMol6Q>IApa-KYWoEvMO zy;<0ORRm|RBpA1#2-|lTOcd*TX$zap5g}#_No(@QM$5o`5cYaZ#GAgi?MSR_JN%^4 zZiIl%+!-8-U}9zzrL$6>*8bRo3Vou^%mer2tqjJpRBzxJLwY}FH)uI>w_PS3Kyn@D zCvx2bABNchn-Kg&CDWZ=2)^}7edMv{q5APm_s_twS5Z9OW$1wTy$baoWOr4|5R!(q zY=drHo@@bIw>MHdkxn-^XdYL6))%LW<I}q&o(n$_fk;QjQ@L_<lLdI?dDtD-))$3D zl~bHLpHKTO6sqJ3N$#;GVo7~|le%rG13V0Z$S!KwU9x>rP<K{so5F3H?^xPHvzBW! zo-W78swck|UbOyNw^(_0v*|R06?Ht)*4kV;@b9hPW@Y7`tiYI}rDdw-`?Wgj+IFka zq4WIbJ|25%HrbPBXwCOeAgJr}^}4)>^ZAjT*k(bF?dZm1NuCsI_xhH=^W<p(h|D_Q zKL=He*zI_m#k@^<T*>W1@2xSuJI;LGOR69Jtk^xZr`+9t%%j=eGP{3<52l=v&?ihT zOb%!DYy^6{!PMMcI%cVJCP;Oy4&}Q%*oVA7{mm^b(Uv~ViY1mN0w`(KHI#II43{2! z(LUO7VSB10R6ow_=6==7`liPPqh@N84D#kvl3&!P^rVYwrBZ1rYu<+pUw5nZj)(EV z^Rqy}`(6Xfz4g;dOZYHr!!lH0N8Qqwl6swJ){sjL6JtFDd4QCtXX_jkzG|tsIIPhx zeQ7?l&?kp2auye!vd>*ufM>l!ef}JDc%O>u--l@AX>GGHuZ&<yb%v9_Y*=-|d<@0z zkacEKh1+!u&zt)AsDqd>1^^}~L<|xd%lmEpX6><7ALjBTcX%menxjynpexI%4HC=d zoVrxi8UdYdcl|+X07u85P`wOZ3om&|^rHPX5LMaq@hhQxhQjt69X>t$#)kmseSSBA z$C;Kj;v3TXJifOZd_Pr5Kt1B25PvvhmT}E1HQv^k(V>0QdX(%!qr2g`Iq!3fcyY|R z$`yE=#Qa8w({=qB|8Y4(VCx<e)-<wv|H>BGDe1Z6`PA{k-*sgu6Z4wyiSF?#%lj8k zcRk|0ggz$cyskUi<KoE!i?+uTAamua;c44e=hx=$z9eJ*`a^J5KAG<Uy_11cdPiu- zwJ-nZx}jIY*tY3xiQw?Z+)WDVG3h?)90BYV%L+ptDRi;lqAOre!psm48F<L);^ozD zit<3&Z*uo&9;H!(zFX&X`D9{U>~Ambxz{NezNvP))WxSllRV3+PEvOA_E>;7tE%r0 zgSO_LkGwP3!@zRu(eUtJ^3^)BA<lI1bw82HJs5+&q#`G{?tMbVWid*f#Wf6D&VG7# ziw<E49EgI~FDhyjJ78<hxw2qb8=+y|>=Qh63Q01&_JQ5zxjs#Ao=L}Y{$^*Z_hK1b z>vG&%KQ~Nf@IGOzgtS~Nx$(ZYEUqUqW7J8^{<I8M)-p2s&ha@9yG{oEBxD=^{rra` zu@vvMplC^J0&uCf21C}D!<G8Y1w4T&%ZoLj%0ciCudQ^NkhDd(p*wxtz=U=9T&qG^ zX3arzFPy5ciFt)Rv4}TOo&&mk0IstRIwp7-F@fSS)5-0Rh<6uw$8s5gysi@nfF;R< zk>xczzP6Ji+kDBnERn#+w)7BvcGOsm$+OKjnfD0pA26^cekV%a;+Z-Ds(Mcfk31n` zWPDQ3R~ckg$=CquDRVdHiI6l$DCd9oWcs8jnk+Y1Av`7vf5)>gKo&7$>}kzr{{SkV zg&pEMb5r9DDZzsbyFP`%8`jmI3f2kt7wjD2gjZGU6Vl^?b;BQh#H^F29&v8q(U+G} zpFPJSjAxcJzz^avS=o%fd!%<OswZ2NxszQPXdEj>tQX>B_sDmtWS+FHDjm-gxEEE= zPpYlH)gnNXNcI&i*S@|B>W)Xr|2poQSRb?W8k?@)I0N@?3CDuHazs_NJ@_AY$Dcnx z-Yl<mN}Bi{9p6Jb9(Uj{v*T-nXx@cv`P^sJb+en=jflut%zja?kVa1Z0e>OXb#h{G z69zUZzLi2a647#%#fK0}{jd+%n?w1FYT<7AHBrBewa=0!iD`|x8Us&AF!p9GGNMzN z&O2X4o}h-9cB$F!fxE8Jbbj4r=2m)GBFZ2!V{ID#gXO;{1tL^X;4>3C&(3|JE^c9o zZI(prbK-ZdRVgN}OfKtl`xK`VUEroU-fpP6j$`G)td+Tzfvc}<cF>8fU+uL8i3^vO zJtFfw&e`l<qfhkESCFg~jQpBRsMXqd-Cd@7rRxrRSmEBI#BD;T%`4Zb#8tI%p}^?A z5z82ej~qQt@1cgW3`h1`ubb4!n{R{qCGTBHe|sHQ^~8_!sg*`!s^?+i^o$Y<<`FyE zdY!H|Op-nHi{B<|;j6VjZ^U2pgl6Sy-(yu_>^5_o?kJFMIV|4pO?BmgAn5B42;PsL z*EQ6L02Iipi%X|T&vg%UZ#m~X{TF`oWBL1k1a2QbTqP}3?R_L6BiP|(!tW{$B>$|c z<3-wb{0p`y7^EA(d9nf`{gBlGwjssR<H>J~y}>hqxl>@7TNU&rYxjZ0giKK-kwZi6 z$$?3;Fcq_lA>NcU<XaPTC!tsd#r4fU^;9!;e@H$%IWdvb2r66gZorrjod5I?$O#;O zPIas$X*eAc8UR&4{Incg+7zXB95?ua66M<QR6~}HT~(DQtm%4EH0}%bv~u&8sc0w} z`f=J;^OT;*yEimc5ZMTRWjN9n%P-=49n1rP;?<vuRt^N}E6;1&zag@*i|th0%c0KN z%aJ@S-2~L^QV|{eM`#MTERTBmc7iv;G1Jtjd8H=EGmanZR&&Ti9-mGPpJPHzH`}}a z<gVX<V{1@f9;;UfW#IBZW8K+hoN@QWBh(?L5U0S>4srxcqd?z&w^0{yu0)-4m$gbT zju8m1x%`>6A)>ZyH1`&elPRNHp#@(2WY)hrg>~A@n)W^a0e-p!m7XZxmv4+SZB~)v zj%&1N0W!fUs-b)?Qz^;fq3?#j5?nq8_@iE<d!7{YHfGsVK=$4{9e8Z4foj^y+XWWR zKacEZ$N|j_u|3a<+3rWGVZUePeU*rp5*P~NT>q?JX^XTj{%ud$JVZJoto1Ivq>-1d ztCQ3z;h$X5B_{Q8*j~sHm$)qnG-F|FVrQ0gQvCeO{1@QuSYSl4k6@cp20jTR$)aX? zOa{C>s6ey&)ak{^2Mr!pR!cf%S)~FDU?fILW%i*tzf1kL*3>C2IICR29(gP5e6wJ* zvw+~X1ey6@(3py7W(S1F44-FCpUhC57f$uh=QYn_0&WmA((a%WF=6)8v*F_dU~7<# z+bU)4^@RLYapwaS6U_^@{q?7i1E?zhg&{8x6$29_6LtQl2<ZFFzf^6=7#$^TXPCwF zi3S^hp0WbVz1*8<S@*(i+vzVeA3ZNvLF@GT>ihKEp1pted0o=%5bP*uib#TI=4bq& zgD?;A^~vjlj6mJ6vtedHO{a_C1fL)^WtmY$G7g}INp3@H^6R8n`k0E0(^OM@Ip74p z-w!K}y)>JF$!CMuUfZqxH6^MQ37r=MjkNX6LpJWMe8;g?j5DHB3R5WZekcrSt~f9T zKMME8O3oG^WuhrG`5l8pQH&RLcL))&z|9QG-KD?-Eg>n<wE&`@CE9ojd|1&G{k+at z)_TES#m<lDSYk4hytORv{VeyFD%&D$T0NL!d$g{rBF~SuPjP%6c5T^2*j9cypWs$< zQWX1ev#d;j?q*<xe-7Vx(ms;q-*%GgM~;$3TRHlCZ7Cp5=5cN91@zTjmF##d^6i;_ zcPr0W5CNoiYW^rdq?^DXB^ue3ddl|#Qr>Neam_oWDe@wbKM_QDVaKoEgBc>>eIJTF zc{7uc3Huzsd4doD@>ZlvTBLZnU}=zAwi$Aeb8L>!EblvV8+d{>6u^mmOsj>y5;}+f z5k7p;Fbo-F#nn59FKN~3jV$u9-tB`vSqOX&1@kplX7ZAvIAdsxDM4o5s|C>GmOVdT zZDcghJ}Ih|lhV#+=C{trqG*n#)2I`oV|w1mxR86CYl_UO#_L1ZN@ZU&W#2!_-!^W$ z8}jb*I2~;N6Pk4|zF5LHV^y+96jOHILpP+*lp$X9T@MeuKlv&XZC#NNAyV3=&AQcX zJ_0ZD<G}C!pYbuJH6Dc=gp>SYaK1I*_HfZpIsZkgVf%F_nD+<Mv&3*l8yDx;r2AT} zA-45eleqIXb)yjWguiwze9!M~(Yhq3jyHkp>yQv}Xec({H{aVu--05Yg^>)=hh|%z z7tOeSX!f+VjweD(Z6`Rc_$qYj-(e_s#SOHe9y?O^U1XYKELs54DMYQ!3eD3kyS*3> z(6a~B{KnaStUwxp*wf=MJ1M}zHljn?EJ6y_&DwnL(6le8>w5c*caYYISqfwRMJ74K zNRX`6euED;ghy<jZ1)AgbcdyRAMVZZ?Pm+{CMfqZL@ZV4b^zy$Gy5JDTFog8DrY}~ zg%CsNoRm(PG?*r2@yfNo;Z^GPWQsNNe{Xr{c7!Hb0<+<akW|K=dpWLqT#R4qsi1n! z81npPe;H!|QDt*NWz&VQMvDdaI5iR<d>CwCzU}JbYDe+4!6mm&Sta(akw3ZldJcut zd|Pbkc=o_G25JG>HP%q)X#-xvk%E0MZK(dseH-TrcppXxJrATa&aj+l{sXj82d`Xn z6qM$AXxt;0^C~alN=ex7X>-!PJ&CI!7>1f46<2?_Bp%CO6E_^9g}*Jrdra=;mC<5? zyeD8ftMG(n7@&%eZGW=C$}O(F{0)ZM<QS&!F@VioP8W3ii7GC*h@iELNfom`MUNnh z_E_1ATCZ5W+-ZZ<PX^ze31g^|FxavE@)8Ip5Bk}m>D_=;dh%fmYT=CCjsMzkgmSM! zIqULmCJ5;|m83FYe4O9+^j6Q9W8{61W!SwwY^=@c#Blt^S-jKK-_UEGiTLc3Gqz6N zeyAtunsp<!{+~YY;1lt0t1yTaqGpnvg@J$}=LUaG|9gD1T99-ActNh{ysJ3i9!<=` zO~}9}A3ih-vM~v+^?ZKwAAW4T+?LgolyN`fYR$N=$<%1L!-5gZ2VfHxp~&;{1@lDS zI>_;32;T5-to21W1tPW`N^=7{#<96bAqNFMmtOn(3f2202#D;N!!GA0ZZEsyu|wpp zQhHg1psK;etP}ktj}MdAu1p*IwSsMM0v0}1>9LbXyUy+ll+rNO36OSltQmKZ=K8I< z?1Xrh<9kWH>-#*r-_eCjF2@k`B7SDZMKW2Fq!QUS9Y(zRvSPW&%5O%)$A{;QC6gYr zO^@-<7m^qCnw8*2%rw^tU9T(2i$~O~jWLQ=3@cOwOrv9|(lNhF6hUgjOad}^^E}km z_p--njhnVfBwRW7=|V9p4{lxEAu+`<^~fHu+fUlLfWGIa9swCLuWQYld7Y7_b4%aT z<U?mx4(1<a$&5K!D&}O5;jZUzXIvjP5IpSfZ8DK=LueUyxK-t{j!JRQPo9@`Cu-8_ z?Wx@+0}z_eN{8JF@(+NGVQ|T{B2@;PF)sG(Vkv+|z+?OC-Bm1U?okW2-5x>+6*>UY zXuOMkHEGSMD|zAt##}+@A5w=jZV+#L3oxGU@O%dUH$r8SeqKxH#0M5Vvp(M=;td}M z@C-aVE}77@X%6w(L_Ep21UCM3Ipq7E_1Iur6L*LwaAR}an@5545gWVcWbOWo_tmiL zxrFe%u00yjvR<u__}bWQ!1yj?f{E{D2Id61CYumryi`|{%}DLsgLtfL+zDK4{}*uX zXbmU|o3Oh(C6O}Nx9=CP+cKibnSMTiRXaqU_gHne?u(TIK+&1tevcKe%SumZtbjhR zjhuKM;XEN={W(SxdhPp|=OwF;cI10|w|Wuo`$VIAa5};K0*r`3E%11}d;>6my5m#3 zIkP3AigA0*m8KO%bPMDLf<hKxdycv-kwCIz%kqgDgTYT8;7ed$L&qkd`5Zo04ZH|i zlY1e_akAu^a_qCg{NJRKT8~A8yCdBP^UCQ4pBtRV(Y^L=F&TV*?N}nO56?Tk&m_Jf z4K%9_?N2ls)n=r=$1jG3PI#Q6NWBaYy|3HFq0nf}%e|uGZ!%elAWUBC-w%)6wnq{k zC)N${m)#oDmNcOr()I3|7qF@p@+|Kh>vhy}eddas#YtpH!Ed;E_+lN`GJAJZV?PBv z!v~)>XZd6((2ruvTc+nWXdt{pmn10*`=ic#t>@PePv3)s-jwg5qtV0H9?Udx>M6Q< z;D+6)iHfkUio{DRk;u{koZy`%1uT_C9}Hdorgck7)&5(5$f(z<axLvi{~m}{?T;mC zcXfNN1jb;Kc(-bNA&KSW>mavdp%37G!ys5ksl=17ZmTj3mocuGaqNdNm&BdQ+SoHf z`xKz?Def0(6eJF9TYDD~IU1Iu9u;eH^M&fOJwn0*awXh)e8xU!)a&0mV8a4E_GTCY zr@in_sE|EOKr;jbJU?;jyn(`}aS`!+ANm}(cGf>%(|{56HS2cX*1l5?$7|ChAk?|| zG?Q~(^!YYfKol>lA&Ku@`%MMeM3(n?mib8z1@FlqqxUHvuRFt(o?aJHJ^C)D9ra?h zxbwO1uE0~={*8@c-Y6WoxQ7(2-I{PbyjbCY;Aiuu<GHH5Pg&oKE8?7bzQ)Tc%(%y@ z?n2DaPp2?arPmbgxI`!04);8ZymHzg%#}G%q2Jroi{)>L<G(rZ9SBMB${7hsUcZ5$ zLi)=X3UW4?bxH}>zWj`4ap<}^8`phi@O+!YiiMp8J(k3O$A8JFTLknz;XkGu-6iE$ z@4>7zZI{blUU%bryc>T+YCCJDUEJ`qytVYbNN#oFZ7n?9?wzxP1@pAaK0h)(#bA+; zkvmsiaw<RrCao?bj4$>&?#nJh4s<~%+-`{v@H;vr#yhh7Mj0Dlhh<+&ps?})=mP<9 zuS@C4kZR38UqZ)W*9ZtYG9CA{0zD$n8<?|bQY#p?%=no$ZJRV#SblG|W1n})Zl1c{ zj?dXS-Xb5kXMV(=)(h)y<61R6@1E1XxYm8*@O~n4g|YjenQ(*<S+)kqpSb$&^c)%+ zc3lbq+GFR`kT#6Zl6{|n7pthG1>u9dMBWz-8aRchV(;et0=#*LZ&4H)IFId**z<J8 zN+%O9wq}+Q11*yHmNv-4=%XUkNJ&EM+zzYas3XZW%`eR+1m40U$ThB*IKJu`hJVq@ zwvzufGu<?y2hIhn&ide0O9(xx>-r4tzmi%Jx0bq9G+<~JAT1Lm^C5(aqfo3>+PlDA z@l1mSK2BN*M$wFnZt1t&VsOx@MbuL0jw{GcRvPW_bTbo!37@>f&!J4f|I#q{NA%|% z=S!?zmCT0P>n%%9*2wv80S)$?1PhxCGxAV%<>^;-Mpg4U+S61-LgKJ+Di$Cv8aSbu zp|519%3CD3VjSar1D~#~k_6SFI0mQV3rs7gU(9s7woj*=(3M%*g^&JXjJ)ERUOu>w zkhmh~q^VB6h<Gf_Suk|`Nn@zPi-rV-dIu$Yez<n~f=0Nc)=nUjPwIY!yg#_3=E9LZ z>780S4D`8ayI>W#;;1A`dIgdY9JgK@gRQIeU~1}EvL6R^M?a@VYr0d?^+w0YPO7%U zC|sb=;~fvI7yirZ10=>HO@Ex{`L9eCnk@xfUGy6R&X63h>2#Q~_DH+z(x1;eo>ekn zXv(xl#<d=|26s)^t?@o*MQfuO7+R4ep4bzH<L%!yU5<BT5JS+k+$Y`Pw-IP`f-XDw zdFC>xYIn0J6J8(8J;PxmgH%3y{=zYEp(Vo}Ow<%9lht+g`O7$K5EfgjIg>6<2y_Fh z7Y7x?z4P>?R@q*|VLocsN@vd$lhkGfr?%vOGqrexZ!k86E<$}TuaU4nLo%WK{~3{A z4vORZF2mQbscb}7L2m|uM<U;Wd9)1LbT}-u@!MvpU32!CTUllhGP~~Pw7?{VaZL%Z zhQB8vII7_JUq*O(%6Z`b7Uh~^+n&t845zXOUJR97l<!z#Pz<kP^N-E{<cWWcf3RVE zb>qnBkTIeEP_urk?6FKgf8K_`v~th|%F4s5KiVaigJ|hE4<hp_S+5B)9t3v1BJ3zX zZV|Zc-7}ki5-A_PY!sq?OMAV+gOm|#yCBMFvtBS(B8t9;IZ>CaJ>U#tVs!#=mY(xJ z_VGZ__g8YzVf$JYV`cH1C_bWGK+e*8?5xd8Rh{0f`%OdYg;)1ccMO}3LDxOV2P%`x zwoNf(nhn4A$QFzD&l<9xQGk$;lR>MtS|tCDy8RYYd)?iqhNXwDYvSAr+ZG#xP5g1G z)>yaV<k!51lHRI%ZXwrL7yx`7WN`h})?`o3DeqiQ@7u%2Fd#>g_<SbM5`Lt9hFgF4 zf(0fYQwYVFwlVrR&P*Tw0nP=ZH%)f)KI4TZ&fk3u-DQD3WT4_oK=!3Z#nhKx+SOq9 z(SliLwvP6w-?R9$GXgp+z3$)AOv0#)2>(plpcJX&qW!9H;+r!oElmi0&BI~Kd$r1V zNbGaiatojK7*DJxKklxoQ+sMnronl#>$*J!+wD`9l`r~YO)?~^{ql#r1I-v8{RcG0 zS(0w$>B4Hm+&O|q{>_nne0k<8(bCz7#7*!$HL35$Z4S`Kp|#bv#d6^nx6SU0vDYM4 zZnN1GO$Jbd%*Yocd;GJ|J}uH@ZMVw({7ew6Gh08BT+-~cIyvHQ=Cn)y2@69vz*V?J zYe!$`n)i;4NM_<i7CpqvfJMrUcg5+__@N}3*7!<?+wF!6yD0#Ku&XCzNQjajt?4?o z?tPZl%6p3_Yn5%vVPhEBIdJoN_3n-qy0`X>MT&)z*UJ~nE8_botDDnu;+YVQ=7~kR zdrSN=HiUPVUp*f%0TJ!7Lk6PZzuvftb(iqjq+ain%tdtb(Sz?AFN=Z2kK67VkLb!d zcQujmbM!h+=&8LQBg=S+;eWe}O}gzUTJ%x}j|)2?d|Y4HnTr3hfX6M|8Q)!Jp+1ts zYDvfwn{;y%<&;C1nwZ3G2D)4t_~=@i_vk%KzFxfl+`UV(aw}Fu=2&@A49F`-6px** z+5au-E)^`qhZnlrxabS{0_+bu=)oSw0x&UR0Hon%+-N^725kUj{<uA>O+)WbH+z-i zil8j8ltLxCyOo&<U)!atiI{=gmSi0fQcS|f+}#t~?)q%V3$2<X(njqC`veIY<~5U^ zYN)q(1k>1Jx=v(z>9anb$oghxdf4D%iv(1i+|u*7HNHy{mHEuq{D=vh$Nj{p(b><u z;^}*R%j1^FI$*dKi&uZR{Xi|&?`}*#l3`?du~olnbx5duO~&u(8begs@cNn;zJW7O zKim=D*6z8>?P3O9^Z%H7({L!?_-{Cr5raxHwviOFWR%?ui6}(&eM=(ynqlnA*r{Zx z7$N(f?1mYG5oPRKwz2QVzVl4K|9$_T`#2n4d2?OP>pVZ__p=?zQYrEyzY?2pjkoz7 z{O%Bxp96hX#PD(GvdN2m$sfe4$|Gn%JjqoY2nfCIIUJ00#Dr+k2qM!f-LJA|twGfw z0bm&!vAoR^*LR@^u7iEY(2VD>=`H{8Woi+4W6a33cCT6@?q!ti#K_!DL>2aZJa;6> zIJ(YzdNk?;K3koBY8L2*cMf2%-Vplz$IA~M3v-98-M}?HTsgXI{a_)*xUgwTaL}7+ zN1F(s3rp%s=@HoL#(4t?Fa2t^I9n60!>6p~6$Yk!Z&d)^A8WjdAx1?ivUT5&4V?Us zeQi`ajQEziQpq<{U|9cA;7vOd&*%GWgx5DdtH;+re6DIc@Ku&6q3x0RZyoLrTjc)P z?8!w|5sqt&tjSI(SU3E)?R#iXZx`R*7S!%Xy+P#)G1HNns_VvP_6i5}Y9bcfv+{x1 zteUgeF7`xP5!70|N1aUTOw@aGb}nf3axlD#e!!s3M>PY%!EnBZX=2y)dz@Uxv#)n1 z74~{;t_qd<@kMK5oo7}}vt-pP9|QNv&e`xknuBa@jrPJ7!EeY$kw{{D8jH*l^k^>1 zN}}^yVnUt5bbEZepv?HHzDV}YQ0a_?bZ?zfD2QHf@TLJhQQ^1;;cV?AR^8kCbEin@ z&(prE@TZpW-ta=5=%c5PwY*T9{%b~Kl^2kU&gkcsR)&{SnTQwU?{;?`0e(XTh}Ys> zxx~{#2%I)sn-8|I<C-e}EO$}WuoS@vRpw#RSxGBu6p}_}0O{$A;<xVZ?eCXoM#u5A z-SPG${`v84@S(Z*GX1dmujUSCz4ZBu6Y{4H00+j?(=AOaa&@+iKWI4Mn%M~=(jg&Y z8&)(cuWN&CyL1RHx$+l*7Fp>hjN3lbkFc-nA(t@E!n<WWXCC1i6)cX27)SFjiEwnx z$Y2F&+d0)c8ytK63iI84y1(*Cy5g;KPY&;~I_u)E*jO~4bJQ<v)4{opn~o<CJ~wnv zXXvRS9BL~BA8vI@XkdKmaSbE~85tEwJJEN^$5872jRAI)7_(QpsF6ghLI)#(AD%z` z1*=HQR6J9OQ<co8+wcMw;b1{0fJFPit@zENoj_goj6)W`GwBQvXSO0<!<Ey@uLaH6 z^Lg!cEd{%TQ(oZdcKU88AY<;AxyeC%J)@oqQ)0-h9KNchT+x&cq-WKE^JY5E0!kik zOv_aW`eAWErpSv>fmK0ozl8n!ocvVOVt&c9OiZ4KJ)+g!7KNpZyzkr4QSqX@!R_<w zyGC>^YQfDXywj+*Yt5D~57Iq0iKDOL?$!pX<<L%@z@4|lW>*@J2+k=k=w>{JJa$Kt zQ_3%Gzu=(7d2b^Kz=6EHp-nIV@okxgV)sG3ruqc<QjmF&?G2P7WPAFEKAX3Z%c=+4 zx(MgGGYwK6QrLsFm8&;C^7vfr^0U2xa$2M*gJYnw{lOo?&Mu}0r%h|hR4Mo$RlPfH z#vW5plb<(P5_MyKcJ`BIthThd?p9$!@5{4XWZqQWWrF7+QR(uY95ReOZ*nGh*44Ft zkKDa0^tm&adQqHhaQm6tMR!4G4>$9l+fHYvlBb70bW_{s*tO^?`ogxaFNA<0jmKR3 z{%BJ^&QmyF{H)apO<M(UX7B@h+4^0XLwAWk?Oz+6(~=D?YSFJekv1G=R_G3vm^QR0 z^zUH0X)XNwPust*=R2Bwbr`>Xi6Q3t-}z8^?JpczaY@lZ?quGj-?nM@#qpOFSKQ+u zYEjc(f~+m`1bJXSvO32%=_ZH>8e#kp=&zgpn#0;?<@<_VwnyA-U5MX1e&AHg_()sI zi{Zf#Bvhu3QT~jQlMAeMWO=E_V++%7S>7CB?!D!+mP4g@wGrYP53#qDqSa4%QeLz+ z=gx|XxzbMk$z$ud3hK?!=$kB*MriKHGAE5=?2SNo!Yx92rB(R2a2DlHN0*@Ated<J z<RtF=zHE9xbfXZt{fQnX@hy}xlq%MKpT!JrXZg^^^H@{~;4bA2kGl=#WHGJ$RLBmb zC5Nf$^KJS3X7k%$F($HQ?u2LM3NmGI>Hj$DG&|^%4<vI@wBaNXj*T~r*WqQ;$1R7{ zBB|b1S+;`;EsN5e`6{Yrj6#VF*^C=(VMDM!<8#n3!-3F-EZo>C2lD%RC}O_CR&uLc z8YJLmp)eHC4S6<m9;yYTZW;~pXn%N2>S0SyokQg0=!gg=Xe>}^Lc5A;C_tQ|lGkFT zzxD66qA4_`$EQ+-SViu`KVzrs;6$i|xz!=-h7WM7<(A+ZPHDLo_l{;=FQtmHn+w-| zq-!X^g{L=*eQ%8&Fv*(?98eLc{9M)!uH&*t-WOpW5!foW(%TReIC0U6BZ)ns$yz5C z0s^_YtEdShOg(MfX(H3D&`+cYM)_Zpu8^=6{&P}4Vdq-s;$S7~WXho%)#mlzdf^93 zPhgtUA3_(Yfij01nA?HGItO^XM6qLp)fdPc>%Eqp;nG*1naL_Dh&t%aNqxf+!T~mZ z=#SrouJ>9~b<?{&v$ZCO5%m8X^|AMCJ^?+24lZgrg_tJh)+3kg2pTdY=<s-(gO}XW z$`$ZXUBahVZ<bybNfxBe7m2;+qt*N1o2~lG@ZqCWle%{b!))s|md|`gORtzYh^(uL z7!KMEeUbvQ_hN1hlKWnCUF0Vd=+bQsEdXcfJ$uWpSJdS+)?YFJbzj)S>*hj&+ss(Z z6L;MoX+B{K1~~)mII=}!8AO3Jpm)1b1plP-<Os@%vIu*14L2NXTyKW&@Ym7E{;7UN zuOvY8v~?|W!1bqjsRm5T?Jv{2C2ejVQf7rlTS&jSEQ!IlXPS5or6Z{8MZZ&lAAoQX zNzXw^fE_;}5XYQ_Qg1C_>3h@WzRB`b;4a@1nS`2re0U&#LUBwwnNk=w4al4_3c}L@ z^;7e`0s^^&Q-=wAp%rtYgQ+!wBvKiUfuB9y6^MH!a{Hbn6X|<UFO9{kIhCVJMaD!F zUO*SJkw2ry)1-j^B-E&EdD|_x_cDt2P-vQy@|%Du-hk3m0&-m(C<v`9DHM`<x%7<4 z(b9Ym*Hh!R>U`WF5)gVmv)Qb~b+Ojmhrb|BEtQ=sI1Qd(oc;~8;<*Dg>@liS@(O|+ zi7!NB{rBD98GoZwW`f6CNqczS=vDaJWGhb}7hiF`BY^i7xjxDd(uZBO$vwW!3^q5s z<FD&4x0FBX^G=ALC51fJv4&zLHrzm7kTfdAX-mr$T_8~Wu-obxPgCF}&X$^SPw}%p zLQ_V-ylns!J~ex|DED~NH%0=PY3eBINJ|Jw**T_d5xmm$<j{GhA#9PmDTQXJ!<xPX z&WlU@7*{I5iM$3Mv3yWL{NN_>&YFh1DMJ%l6Gi_+-tX{!{pzHOkKqdE6e7q#G;H`T z(m7xer2?OC`zM@JG#2${L*4_!7&iahM@iDoR}5=dhzO(P6ZD15Th-3X%&O7?X)p;~ zhDYnrDwsiAdZpi0#M>5{pPpNO=h#ci+{N(`b^eZLqaY^~CtUe5B~X@oHl9oBKZ9GE z(b7TM3ZO0V)AO8y4<$X%hPh=%D#IDxx#aZzwi4i@Ewmte^8ZM&yIRIZioKUQEb;7k z!S46`X`=R)qozb}nb|sh6kOozmM>s->vhWh&nV1_PA!`g2TiN2r`WzyD>*W!bGQGR zZRnkAE^Y_RPDh-s`F*d9$^tW4)PCyU{6d8_-!uZs_=B<&s5AG+^LvvgPL>3x$V}qy zdB0{rd<s8O;S&9m;!ou3e(86*;WA>pbh0G!10^*_Z4}NjB$KTgE5&{rK!tlaXxWw~ zcFAVlAl(qCRxnt_7fXkv%$&sJlHxLVf%zKzP`>v7ull)Dug1n*z|`KY<6quQ_pgyh zPK7#>W?rnT7$3{-TT3l-sSsW(DaI8V1AkD=2oJX*C)cN6I4|A2Z-(|?AIq|h|H<6h zaqF}E8RYEu#>&Ujv@?kfv22N=8Q>aJg5L}F^}J;{-twLj^q%BnrNIU&Jp|LFv(3=9 z-Qm=K7!eQb#b*1$sgPV&59mOO=jT&RFTDLO6p|!b4|tJDR^-xm6(0}zk|mDFw(sq! z!&jB*ObtK+e7U)Y&=%@jbU=s0Qp?)**n>LN2+<ep+=J+GY-)Rkl@TKmC$i3OqS^UH zd@u3=;D84y`fA1=ehW);nFq)#+73%VK>Y|j=X}o1dW?%Yixk#hc<Y@*TzP{w$)za+ z-j@kC_NPUu!Hthd44za?MUat%IL&RPDYAm|Rp>+L;)c)M+xi_;gwM03#pWZ}aYWg8 z0m@`*Mp(b-WIJ6x%jIH;8^uJg$S*2CL>6WIc@%nxpr8G{!mPFw;$g63YLQ|Af54tE zY5;=HPnU#Rb%H+DsiF<6MuN5Q-Pr#ABpVoH;8i3`02I4(V=>Ye>F-BmZByoy&$nid zfOGy#`{(FNizhXxqyK&sja7Q4gD!f8_kGvjjj~;KJ<#v8RnFh|%vD`i;&485mKP$v zFk;Pa+beBcizkXbJ-j9|2MX{d>vP>ZUArpEyYmlS)1(=0E_IZH(SIMvvY#n`S^b5G zj`X`_!F%c9ZMcB6@hjd|*X-$bb{Q;0H#M2Pk#X0Q=efktxEFzE_k`;L2y6Drv&SSG zQ77h^|8y2#WCf>xv$YuSZWg0F^^Mf~0#E(8a?KdsAI$yi(Cfxd%(n{Ko)4{^`b%pw zmClcJr?VOT_x<uaLsg=|O*v@Y>GYlPn7_KPn!d`f0}=wR#}cTBxnJ}q@JV)11Vmm< z&#PWbj_vrfy6Ob9@cUa0y5^Pbmz=Yd@|;qDv!ztdS~uC}J9|M*qeX~c)58v)uH@^k zFe3ot6~b~oAiRD2x}lHI>1bwrErF8r-r85|aoHsy*!j4!415kWrMQ%efecI}^`->e zI!NmB>^sb1qZaXFxdc93{(hWhogQ(@4Q_AOE!+wF_23xw%pIlS6`|qDZ{^skj}953 ziP*$@PVsz7Sk-&rAe{z4dRl%y>ON>x)iEiSxKfvAG19s7h<nqqTjg3ewdHA#GPz%p zj=%?Rp7v>Nzfr}AV}$yV0x&f<r(hsEi0Q4wFH;wXk9N}$T*T+yqMHMJ7xSxYW|6=8 zF4kNwKA&%skA;k*z8a~sh69*#0<7VKgwxd1h(QD$A^HlHzh`%Jj_0rAD$iNHlwK2; zdgSDJ`|2`T;riI6VcyqwC(fXsJa<zVHVeq~4J@@GfKP)$h)w=5n5m{L2i@k=_4LrX zcR#NK2tf88Ue^Q@t7F^z|5hI@NmdO_PHVsEWm`G0Cfq-XVtH%5sp$FLR#vaiXRvz^ zB{^o2i~h6Po~9mSIEYz05*sC1W)HqoMk^1c;M{c6sE!l0+QAP*gkq#BH?3bA9}j|O z(i)w7f{OkwRdK)Hzah0sF9|7}9wyVx4M8a%+sj-)AH%5G9xu{!c9=fs66~?;{`#T! zss?VZBK7BWkK$>%ZJY|~HGu|x)w1I%FH69IiSsLw(9g)~Z;2Kz5=#pX5Ate?l=<1d zc7$3;Zu;-CcCygjj0kp4#?S#0f5oe-yZXDL<l%=`k4LyJ#LspEPkD}yE>3NCcbfab za>p4LpX82Z168?>G%rE}))~)34ETZ%sCd6T#q2$f01NV2?FsJJM_o$%({l29u<xla zsFM{abLpr6S_a%B>w{mp2wmc#S%^waO`F+VH3jP2GIj9`BXw0MznxJF_*k#IC`jx1 zyXP}jsXrA#y%_fVizvlg4HzkVaX>*O7mEXR8&$;aX#)C)byWfMyoVd#b=a}f_bcH< zzYRMD2J`1@Ub!1J8uMiOk?8fxF^!K~d68~X?P7g4Ba@NLF!U47_cN5ncLG;j0{3e! z0B3!hXClWllFgci+Z@d!bRiH~68fhCyDxOME%6PGq3I;G5#*sy<jjiWKdz$^(fEBY z;_9aiA2-2?gOSR$w=@aq&1WHC)#JR3W83|Jvy8w4ku{1F+dy&_`Pc;KR6_>X*PhC0 zv@RmPXpv>on`-5==d#c0(y`!!OcRShX7tVw`x2jXAd|@Lprhr0wd$|S)n7|9O-k!R zN}F~m>s`;Jf4Z~s_H7c0r6g#GBzNp6Jka`%H#{>7#k?oidO|-RMlY8>Mfx{aA+3Z4 zu#MqJnB}g$m&FaL2!v$cLQ}*jRbH|{;m@0G>>_P<ErIu(Q>mOUXb|UGhMHlM8q{AT z(rWq70_rjwn;b#+Sf0fQ^k-(Hq}}z|oqMF)<{~#6_x5)2&3iEdr?T~X$HNtwxrPGn zJbxIv?(26#GyZhmi>alc?Rl?g%@kMbDDmR&yY)qjn?z-Xgpj?(;_nwE;=z{txX~b} z6)N08MW6s_m$!*Rt*66-koS1yn#e@xI4L}Hj;z`PJ5Biq(TkG&Qt8Jl^ehI*atBnI zZQ;w8^z(PwZ%)68w}6QLy1Vd+m5nuLR={$`qJj1oahA{SwO<Imyp-fpsDk}p)LAiC zbM>pkUsp&%TKHOxA^vcr5W*?nS}c`dQ8RXtwBwmGl&_<e&V+<o9co}Nul*%LB~ATV z&$a<mio>SwxV;TYpPfe<6E}QzS<fHT07V!CD3obU<>AqoL^YQ^e@f0#^=R{pdbPpD z>PUIO@4W93!3Bi2{Lc&>)8?%&0dRS%`MW@#5N7bV4G3Ec4_(GYMW&U6MwZ5enRGp| zP;Kc4-SF1ICHIZRSdY!l`Px|zoL-9isXAts+M^pIc$MYSVk`^oW4^09ynFAwcizMN z7%!DxNlsPqIsMjp#!2C6eNXIne=zfJc>X6D3-z_wd#8*Ai1SDp`QmT5gEJBhVU@zD zxHR;HbBfi}+l+^t(jjnIKO?(J4NWwrC^}o_esRb!dvuxV5hGE1lcCr(9M6Dy?wG1K zrQ>HI3K)v{>)orUDX%$&z7Rd$_TI=0JYMl$+H7(KoJ|Fu(h^wqB{NPQ`X9%5_s9p# z%R;wKhMT>)V7qfW(B6kltMGXGUC*6y8PJz-BEbcHWGu1UxJoXLNI=iOnGD>aH`sZ^ zK={5xF#Cg&C)GYRxkNw&+47(WaN8N9t0H=iy#e_Ji+p43j!RZ=|6R!7Nm?S`zNfrq z9I)3!?H@R1{h3JU#g+=|5_I`<&f9)!#xmB_Zp~<8#k+sEzw9p<rcLh^_6Z%_43Vl_ zwSG;xr6DITSFG0iYq~$TX!%PL(3!Pkc4Y?YJB;V3^zI+eZE~6|HfP{S9}+L5*hl?! z&id<IpNuw57BRvIc9yeO(Jr0N|9HD0b+L<Z&i*^)3KLF~$Iz?8r!7O2h04BY<Q3$y z*)5$~fx7yh(v9$kUDX>dA(xB|hyuZOX|HZri9HkL!ha0kshy>p*la$FgEny~zWxUA zptOu<0!6$8%T$xhv8q~zrEK_A1AzOIV?Dif5b}Y(-oMbcg8JPZh>)0=RS>4<0q9as zxl$fSoaR!y{cRWYym9^Z%+ArUrkD%`@Jg!fWx??2G*S%j?!2A~D|PO#C&4zBrXgx4 zh)H)Q|0VonXFF%@P<HHcG8Nuc3<QMOQkKTS0EkWN2cb1n?wkaNpq+rjf<>S3o5g-} zzRF~)(4L|#r{L#l5YyVLk1xcECsvuR0PQ#2rw_#s!|bQ6nFW{HTG6DtKRiY)Tc*9y z%gV<cC(e0fEq+veH`?)M%e8_)-E<nDN2Q1GwDGI^4h<YqE7d2M>nK6W#qqpS`Gr)h zSDP(`OUeQHz3evCpg-^>BZ2ynbtg@D_*-vyG%;Z1@=9?0b^WN8?d?<m<w5I?$vcv& z+Tp!AzLeRcd#)}&6gvDS^LbW8dxpE3KjKzbYU}w#Pbp+9X^e9>mjAl=!w4*)4o>ob zG|fD6pYA$Y6J;J!L6af7!95;vSZZ~ZbWq?Cuxa8#JfWKEU0*@$FN;iI)e2{K46ES^ zbMDi%COrx*(zwS_2v%yX0Va3yghaq%moFBHrlB@a4~dRv-C#9+1bT<@JcuF(TW}rb zj@nkzpO)$pUU2Su_XhCQnSDRUTnn+KyufJpD*E~q>}p44=#jv!4I3jQnv2_R*SfN~ z<T?e1t)4bJtw^Ka;?2#m&a0(oKM_;hV~8ahME#7<Bj6@%Z|!k#sw-Gfq<hnV5U@Ad z?m<KNO!gM<_`QR_!#da=&4iz-w}t&i!{Cc8p(+Rvu`cR>YtrgalzMNm8fgUPByjDI z6Im>}Lh-1Ye-NfocNd}Wl=z~Mcktw)sIresEL#+H4!e=+K%(R8a+gdEm)os^FODBu z9n6R(L|1JQc@n>7z@#d+w3uGpFDtTLpWdq>5K5XZX&>9<c|1+Ry6r!;d(06L2^U_q z)5epF*MG4`dhb?wQV7p?$+$cDWYKiw?*s3#;d0hZ7}a53nsstm&iFbZK)}D_=CNwt zjlyiXgl>z5FS4HuKTvbNf#-d*j*LI@GB8(nX*iPcJz+1k<)IpH?kzvTDr)vjFhbkG z6iYv63=~g)Bp~mMeWp9pI1jQP5nhO57SZN3^>nxTR=3d^vsC@HET?ADkN%>s=H0w| zbx2llRL;*WI&QX4kg;!D(Hd)xK*?KvT$a1oA4OeyJWS2kT9$sgkKRFDVlDE<lv7&& z{zsL1T*lCB-Ks**w0QWW-h|%l!B#ilX@Lhjgh$;@5&A-iGXUxI1i>!S^gQ=+So&nQ z)aIRPNL8T<L4i@aG8!s4`q#Zjco+o^$V=URN-JsZb$^0P-mQ2vgvgT{CO)deyP(ZB zeEwvU0Nng8{1b+s8b+3)HW}v2#`-}fGrJA<*_5N$&Asmjf)Dptx=gI|DPnyXq30a_ z>xhG$vbI#0tewwxBRv(bDbn*izj2tFs2kH$f#pO@0tYzLSxq&I$z>zIUcuyBE#<wR zSk{^rHt|Ku2Cl2tFZ_sEns90QAnzb_FJbfY1Ho<&865peD1vpWZcs4U-4?KHXhuDJ zMUk$;eduUazapYXZZPV2+e|)dbK*j3itdmBbB)QS7P}bZlj6$2Pvx5#XdYNrc<`k3 zBsz!gs3Go`hDh_0Dfr9bhU8Q$_2}v+4G@=i!D`S+FS_hszj6g(!_|(}`**Z4YLXKA zXylo;L%ADZ69V!of5Odcfj_l|{KlQ!oJ5i^q29~qJb1f{%<M+hp{7ukqX`?Tg=oc~ zMS<;^2^0S0(Q6Ev${<_PBo0ACFosKK2?ue#O)flOnZ&`*w@wUUCcVl*!5s2))1M;- zn@9Lvx+&T@BsTIfbkyZoJjmyEP|1Ykbp5}<`4he#^L7Mp^2^Q7O5vTqpz}=Dy7A0| zC*KvWs%m9@*4_k(ZJ4;E?$@Y6s8v>k$46cJUC8axM%!PDlA2%Cs4AQ4`mqbGK105i zx_8IoHFWhyD*Cah*qVQ6iCk<xRjGQG+Y_?c6VQD%9V*tO+YkYJZV3u@yM#+4H-jmA zbr5ojM5Hs!y_b)EJ`?{z61>g!j+`>-W`2Wt^3r&)1pPCyZ;;DW9^v1ZXcU3%zq6@g zE#@JTKp^eX5{_v`AcsXQJL>~L(iLv+w;7CIF7lpG(}Xp*4aYcDna@&#x6O)V>I|Kk z={q)IhnFRlxI--o^l=8i%R<`k%bXiZ+Y+ZQiIf0cE~|e>tk1L9D`LrDB}n0_4F+_D zrxQHr8qPvB@Crm1tGzUrP2Qz$z(X+aLwB&+Gd*rQRR*r1Hx>2Y18l72(s=M1q`s9g zSDjf0ifoX~ur-qp>hAv5qQp}+XV<gIy#@BViWo7FGnp4oM2n9BB`3^0V^-eJp7z+` zUsoDdzay)DKn6V+Wj^qc+d9!FBohXyUoJ=1KsYcq;9*MYtLm*$$7ILE!OnYWPwHu> z*Il7objp?gWcGUsk{i;dfa0u>s|6E54$(X9p)?+i;}>KMzj862%Q-Inx%+Q>OGf%} zL_B3<musMP46`w$n65pqXb?uDSwN=Ix5|ElK3>L!leH9_<sa#~zsC8cShOBlwmvx~ zS}S^b+J!B8JxQ<L7*k`EJK~t~J`{56CfVU&!K){`?ZQwXCAs&EV9_<a{Y6d0G8DwS ziwwSU(9w+sER~)>F3+eyo9R7?O<0jJh%51UR<2ECQQlXHeZlgs;-aIcUv!)u-C~i3 zmJ1{Mq$Nklhvm)~f;G=|piQ+pNMcKR{pEoWFd5Ek8Hpt4yzuQCmBGAs5jU}t8?_2; z6pbRJ*cR1Dxc3Y7d7mp!fqd<>!SDl|H2{}+{T-LoZ+X<u7A=WG4o<c=E}WpUOsaJt zG{q9G>|d_U14T5{|2R#1y0p5y;Qce8X5S6Nc#F*DHhTNk*Tds)ueXIpUHs`ZTH$al zwZl(KNA3hkYIel{HnnRw^Cvlvo5|;l>#b1lk1Gc{>f%0vQBdZOv$~O*+OT+Lo7qp_ z?)nJSQl||yC~jVvyr&ulb1t04spQ@PN>U9^$u)PeIp<>iZSMP7@ioC1VBn|xBH1%{ z=zw^@_LrM{53~U^DXeb4aV>4G9^2DtJ+;9Gv@#AylnY;;d*ofG2ZPul&$-!@?+q%1 zakLKx{?kVaPN7pI97nM!x0Y`abY%3#E10r>ntAc}1}Q4i9{1c<3hmT6C`>QDo~{+d za9_WgJXZ+p;M9XB=F{G2Kemp!lzo{EPSOpouyu5g4y12f?9KC`iFC?8&Nmx~3*>~p z3!#4=bysd1RAw4RO|)zVcZXXXlli1;mWDlMD;!)tZ+Il3y-SL-x0Ek=uJvZNds&Il zEouAs9DbrTjG{|lSd?(e7717dh<zsLl-WDJdj3|--l_*99+XK%eK(B`IWsNeG}4%E zz*T{S1j(`>AlEQ2gI2GI#6)BSDEPlY<Qoovg_C{Jza}3WnEpi3UxGaTW*wNZ)nV75 z%uSLePx>vhFCm{0hX*<^%_9qM;hwR4nDCUVKs$@3RdD@9l&ue?gQ*V75_0%g_+sgT zg;6E|Hw2&Qa(%fdp4o}no2)vxjQ|o+h|@ZjBLjnjG}%l-(g++-b{_@OHDd?WTVk-{ zZHqDm8=T|A<f=HLPduq^W40R~d3<R)DYuy_)dl}f$n_#N_C?=68JD*_Ns1jmRA!D{ z4BPC>UYW$6Ma5s?Wkm+xn2*;`Cv}P%&VZGL2LOt+mX})(GQV$V0rkepZTK`bj;l5& z@y)*3i6J||c|$WtJLKWwaQOiUC<J*YcQ{AwU&hbs*+)7eOHxtKA*dk|T4#RtB=pBi z-q@U4-0e^X5U&z?bITSUX<0=}_}2Xo!P(y0p9tDSOKez{axxD*imeeSr|9UQfc9_A zQs^hPR?-lDlSL?%*8$3waD=lKfe*?g%Ebt^+X`);42|%StIJ;TN2tR#$zSR9FI@%{ zifLP+j3@(m+018$40LKOCp9O`R2omsiN0HJev6YJ3kom4D}$N<&0HaS{j#(I{ZXd= z0eoXY60{dOC-9Aik)3~zrtZfBJQiqH{`rCcwI2#sTtaeh@aSsH>8bp9z9Rg@ToJAK z#d#`w2Z7}h5U0bvFr?!GSSWm9osH#{OL=du(w)G#Ovi{0d5uWR6_$JQpfD|k90VXG zqV_Opqi$`XCg9-^dWlE&V8b@^(NS9*k`~#4iS&4Y+%$bhVdl9ZU5JxTpcjgaprAqm z)IUZ`KOqUS0fBbE-4yvQ&se5mM!Y=Vi;x91nvS);ZLiMvfE)cFxp1PY9Vm;6T%x*+ z*UkqWW05?A1;|XwxY`d<&-ZUXj$p^7LVi+HU-K*v+$HsoTfJj{{UDz%U|kW<iM#<{ z!$3p>zgY}&DVDniFhK)pc@2@h<a7Z=fjo1quCp~a;m*Nmd&s-~xUz;%2D8Rw_s9ih z<ngo&y4;I}OdRO^v=CP>tDmDJUz7I2^pvLG1S}?iU*Qa&ntk1K(02_mr2>kE_EL9= z&ial#T(4>?OQ@NE(+BeMlXbZkmQ+l!Ql-~J>2DTp`A*EUR0M}bsIJ2vlO;Q1tL|}* zTGMht3YUgiChu`-)%Vy%h%#niOVJTaq%CfV?ong_=(|-aL3|~Rxb;w2RbHR<Zy-&^ zFS)V0i`(oxo+^|mGi7ILS7xg<jDOhb*}~US{ev0lLaQ=)5s+|o{>l31xW9IPQT~1~ zw>XlZ@P;J(vsL_E_##FJAXt!TH;3CkV3gZ~GKygQ!}W|wbx!&jWHO+Z#Z?&c`fAti z1C)G+$4kHYQbb)gmCIN5vL^L;vo?>(X_U$$AVU!N#84Tuqi31_1<gfvZbX7tsLJjQ zuz=+b<j*+*n>PGIEov&-AacO<mL8btMX8W}aDO7$n*a7f73Sf^(rY3j?Bwcj*Cc|B zk38Ds<PXcnYD|7Rg$^E)9#rj&KfXm!1?6vb4;HyC+YF07hsH{#(llwJaYU^`m`}gs zVS9rl(aJ8#UvkNoD<B_>XwI4(PQ3tZIsunMRPLd0a7GXIr)Zw72eVwo>gg2ns((a^ zUpV^b`aCF9Fa7@SL^%#Vx6O%vzTb6Igzs(nkFexV!&=?}a&7iw#7izAq`w$2V(TV7 z%K>@J*D)-2a)=c<<6?R-QE)|V>c@hlyxVz*$>iTyAJLlh_07-e<<3e<ZB-I0>r6MM zan<T<d3JHq&QEK0uPEW%f|Z^wjR^B0gS9`EI<ua1b0&a~1~%hT7&o5y{hx~A7k`xh zC#Yu7jdr%fdu{YhZN)V8lTd2ZJv*sPw=j!BNG^xq6RcsVMM-hYwqto5zu32)$D!Ob z^;SXH@jDlL2J%lF^dHPS#8MBCjme{~R6MkD{y?WE_!Gj#6w6xz7FW!eh-;Ch=Hgn3 zsMvbMde?Op6B*Xd!RC<qi8)TruT-izq%Wf4q9@@vb4w~+Lu|LFK!X?7q+$0uYt~G_ zU=&A{?o=CUZ8ZNQS~2umx)mtlQfFHaw<k)p;E^esSYn-`&q&3iC}%O}a1~-DCI=Yk zO~N}x`#u&aWh%YiePxoPl49=(Yi(2NdvD`ULM!yvsvqeEt_F;Fg?JUMBI}7Bske5# z6hqSjh4m<!DKpj%t_?FPGx`l30!c=e{!Ad?mh=-zXxKFUg1P@3cJZ?JuZ;~M3$^!z zl#xgL-Q;m0flm46YmNJ`CEdq-p2Pq$#3+3k=&97xh)=sFwV{<k-{|t56=hw^Qt<=0 zQ9#-QS||#Q#xx!>C<P-jjdeu0yyAr-ez-CezGBV+Ala6zsqU9n$Ydm<+sUhxk8aYs z1e3sDHK@!9#goI4wxrrCKSY?=R6^fAMAgBY<_AQR#qkN8q><(B`C4@FQ>L|tYjBs9 zJPv5s*He`82{qyEW#IagY3sfCj-o|jpe#J$8<?NV%Zh%*=Pmj@eClB3!y=g&XjzU9 zh%Y)<tkh^z{lI3EaEsZX|HsVHfEma4H^LfwhUs78PogHi_PRd0NIua19aATN>*v0) ztEo~*;vdTeX@=~Xv8;5O$+(WZ*}qd(PB!_o)oadSl~Z#lMkFeVxM0)fBDEDvTg&|? z0-th8^5OX(qPwC0c#mkbTV)m%V(%VH4*`Ag4#kq&oEO8cw8U>hb%o8)kaJf46l>9k z)08Kq>$Q%4O?RPMcaq?#xAO?d1+yhh<@e-8?tC@RD^kozzannG+~aP1$JC&Rs-W_I z3VW%&EW44(gY3DU@-({IrhxOemL>UgE^iE|C4G<7-?R@qbi(gX`yDoI#pugwOk}SR zhP5_R9eFE{HJ0p`>$xYI`35Tx=(=Z~j|b#lIf0v+dSXgM<ox}G_IEzV31v`)$W2Q% zKd!2fDVL06Bi9)l(4Xc1APBw?6aaB4HQRdi>>RtkWRyI04dXH<Wzz!}q?xY)a0ic@ z!E%KWMpg_cF~q6ssur_B8BWlMkU^D=sK{S@(l3wEJya1n9ih;Cq29^Jr~@@PI@++z z7={mx*_P3hmqp8c<b~akd^ets^^1YAMvSUMejYU8i+I9{Xz{bZzC$=yj}|s(hNrB~ zlNcoXU&->H=uusz+YjzyBI1K>j7R?^299M(-#O%|Moe#3+vsXJr!`L%X7~yw@*%$( z#OG7v)!J5maz2lh$F~-w3h6Og8RHUX#|BfU3qmv1{)riS+e>6e)h?lcB1xpW;6zxn z!Hmq+G7i2IAGCJHPLa<=2U>up<#U*S?vcqw0@kP1hyapUu`EW9&44Cl-=*Gyst}WK z3Y^xZoa&K45d-)RrV`IE+gT_!XC(rLrwhQ~-&?x+N|mpcy?~3ijATdHGy8CD=~aaX z1J>E*u+k(R*1cBws<Ob#Jts2eJOt-|?;ikl-ZBo(439WWe)Z{rSN~(5`+r2rzLjo6 z?R6vBw(4&<qka;pf1+`~%!LN!w&e_06VHzx5^Rf@srmF|IXU3#hxxVDc1+~FYFXtB znRX6I$6D5-f1BqSdGj<NhaVURE7Jy`TOy*aQj1=+_qEa4mDfbDD<1ytotB0>MjDj0 zZ08)dsmam(=dM@?5#O*QsKM`K9c9*x7rqSqiEX8xu_FFb>T@KM#=-5g647QY9EpQC zH2|)-N&$eYet620C_%G)I%F9peg6Y;43n4~CmH_%fK2l(DTN^*Ldmma;0Ao+YYtZL zBdl}lvNN{@R#mkZ+&(rX1Fo<{071X;5oAv}d-6N{-qSj5`90?3KFhaPa~xnwUVDvk zd`n7ir*@I-eMt6iQ|fHqQ+OrnzQf1zBWH&%-|TeKVYIZi0@8epQfDQ!_*$mC!pFAn z`!8GqOM(Qdd~|`5dE$2JR$%rZi>97$6~kZSWD7sM3S?#a&v6L9SKiJ^7k@n`BJYdO zyI7joyQz!hQb^~T{2*z9Wi9rlAQ>LLr^3-AmQ$^aNHf1)dqU^-pw7=FXpC@lKp5mV z<|S@tCI82$W%hnWxa3311r40&oaH$76al$p<sSHZd7=APXyD@{Oo_!O+{N!E@~H}W z1UE0t6C7j{*S@%~)v2xNL$SA*qOEBoXTyFb_OL4OBvGY#|3H)De8wWxQ5g59F&R%! z)8sXl;1tHSxw*6`!BuUet##e)y+e$|b&5?+m5wQTn>pM|Q%FYNB1a5y0jMMy?YQ%V z>5T5<zxgA%poD5n;1;^*?}HZ-KlA-T8Uy->!~E)47V9!jayC~x+x|3mhQfD}6WA8g z3&2&ZWdTO+bTiDh-16A}_SmF89T8zrT&(Y-5N52%?*5agT$Xl4kul(I<(@UqdzW!h z<@@}*HHX<R|A<Ub_A7%Y6D2;A5x(@X^vHKrbPHj~u_A*y8YEX0t!mBmH$&EM(Uwd0 zuuUT2E8PMbTP!g6LvsXQ(k9PvZ`!NxiF|~#K=I@2pY){g=cUcFOO%<7PW3mn+=Bi7 zOq)vopN?^IUawD2kj*R&)RM$lV!mgA*h#gt(QRPH6+#ARC#9j6V+>FOD48?ZM5DS) zvWl$;7zF<v*7?4I>7jMbV>lJIic9d;EB6=h<$*$9{##{zMng=32CHNFxb`%e>JlrX zd;x(7wpRu!uDU__$v=K(Tv3op#8%#7Y<`7)R;8VIED&>F`ol;=;MC5=@$QDp=~J{Z ztBV+$*RX50LDGt2EyaT9-xiM5IG<ALnVXr=^cjVh&3(4<RK48_x_-AAYOlYUdCh+B zUqjr#l}L=Gin9l~{UlySiH^x4*|94lF2JIN0_VK;(fs~?`ptCUo~M@^Mth00#JaSe zi4B&M*fq4)l!+r6kHr9(1d1r(Bh1zDc`27Jap^x-QqT>6b+g2XN$XAL^jb~dPZn(S zlwl8o9B7oh`7#U<vx<Sy*QCBc!-riIzm_EOlCd6d&?0{_plm=u_rXx-Q7@5&Vbgbu zOPOK)>|I4F*RM7JH5t>@K=6MO@G>O=^UD0ExW|nFzGI7}_xygR)>eOi+}OwRAFvY; zxWnM?)Z1=1OGU94-`5o!c<?oW<ES-|8Aq<tAg{*|*LE!ZY=^$bHE#`eSyMU^2U*dY zWKKbcPc;E3r=L%PC-=Q@J&8G`r5qv&lYi5*OC5&}=7Is&>_ak*K+$>yOGy>w95U63 zIzAHnm|APJ&n`(gJ-)C!^Z8k?!X~bPCT`soVKPP*!lyZ>+M4LVcvi!oSe+hbh7uUL z#`X`Ym~s|f%t>m^%>k3_Q(QZZuSZ;|#!w{QJJ&WrPfy`0w*?qTR{RW_6Qk_bzxA;V z+!Pn@z12B6KO6qezME6@Re9rhhzBpXW$|B*`M;-1tHRjfO#CgY1-`KsRR?(7N~fE| zxMuCUI)+B$FaI(W7EIUWrq7Ps@5WZwG{hKCg%30EnkZvTVMdQW(IraE4lgQ=;}VM3 z{^$s-F#i~Nk3*sa*x&JPUonT#;c6hUbdz$1W^_K&R$;#PnH$+sN(6aBs`D}xzWmGL zfX5N>AAI@6+5RY384Jg2#&cxINbIiFRSaiTCYPFIlrVZ)xzE0Vwyd__kb*>9M+tF@ zzR+!qBF*}!tkQMJ02GV>UL5h1$9vW*pc|2R==Q5$+p{WiC&TQ@=j%*5gR>D*<g~nh z|2*=~HTs%@KU}afhRvgs`t_JgJh7rn<So+!qUHXufQ=Xr&}>mFH(*#8!(I~-N{mnX z3CVOfZu46F8H{HOEpIC{&ZmqOCEe_+;<g{y<A8#4uUKm`qhR9JyZ3R^Ity1*)=8o; zmV{E-Y2Vq563KJ7Gih>_2vJYrFXJnytznat_!ohLy9;{BHh`F-8?c-!pYn4GhKjeY z39`u1Di_R7ziy6=BFo_b=g#~*T-zB#iWST(Pui-UevNz#<+Af{T)q41y>26GQM?`_ z_^=l%e>R8<X91T;(CVb|{@-s>0shv|nx-et&3aB0dE?x6X4-}d$AGlLe#0g56#2u6 z7<Rry31ph?$61K3VBSncR<Z<XiD)>2?=*SmZeva^V;dtD3YYS|ln}HY+<PxfZYimI zh<t4|aw}FQQf2yHUmOb~f<(H%bey&EnB5zWciB|?YjG_sh3bSO*o9vIB1R9U%5svQ zR~~sx8&lBm@L7fLlbkP$2|MGxn*8C-+5Mzb+DAoFi-wy5{@kn=5DqSxH@X}ufW8o~ zR%t!<`98y~>F$zQZ-1NF4oNw)!Z=3UTD<4~&3&e6DT;OJAyT8A2dy1u4?Dz`C}PFN zBKsdMS$_Sq@;r%%P5iUOTsdN*a-~6ChCONqjM%_5v?u@BInKXG9br{0E!6wnmYt$_ z0P`FeVwh+N`yFW=`u;gyZh_|2Q@KKsZx;@_Q@7nMu3hF1ljwZ!TfLO|ZR>|`_dMWj zd2QOm@X`X~VC2f)%InHW$JRzeQ<zUkfK)Km(@#D;Le`PdL!*Cmx~`MF7r)8VP}hVQ z7Ed}#u>H|?YjoemWER+hC!_;5hx6?5j0H>e*Khpat>t#w%3<Ptk8(v+k9-g8@&vV{ z$5_5RD0eX2$IG1+t?tYFqRtcfV^nO<bCH~lkvFrOCi^TR6X3CfK}1AoynO*|bc0|Y zBIYfh-KuUZ)Q?-7!d??DWdzFD$K>>F#YoGTK`Zj3`}f4X7UWec1X@JywS438r&W+b zR7_p?>S(TkMe^=HN|M!Q6@WgH_M16+6|n7^ZC+Nmh^h*@+?&w;*@-{?@y|6NA(NHv zCI9E;R?@D}V7p4Y0N`DG@_|#4c;}VGIiCMrg;I(^FD}!&OMJux_2r)^C;6H=4a%oJ zTYD+o5Pgd>SsowOIWZwkHjU;Nsfk3zCsk4(`;JxusKHJ&oiFb!R|MyZM`)ze%R&~^ znbpYgzoR<%(!#crkwR<u<~RH_fqUh^UYA}G#^Is5t^`7mV;CxfoG5k>dTh)BpVZ>| zS`XuiIK(D70hExQ$ipKt<S<yEj5ZgYu@(B?!#J!mGTBOLbIE$0d6w}*i=2y<Wz^@W zWKktL#VT!Rg}d>(b=2+=)tOk&u%bU~f~<L)y_$@uZ^*ac#MLJ5?m|S0F?t66aZfT^ z1>aaD2?<5TJ2e@8C#T<uB$*e0%E0hrT~S8OxK%26m5}G$42|2x$kXFHA+8Hn^iuSD zP=TbbKU=*_2xW$iqxK5)UpYxRKflE5vey5#DgMu<H5O|PyxX2^eG%5<<nO#)bO{$9 z)q9~wi8Ql{=LEssKa1J)vzou414I4Mkd@tSlCb$xI`{kNkXt}#4|{@x3s^VL@PSUI z;rCYsS^I*z`gn32oxQP6_?;wC-7fg4Wj7}X_5Ql}VmHc2TrfWKb+N4P>u@qpAm`}t zGLsypt=85uH_{P>=7~56K<xHxlxf5#Y?KZc-sACA{;z@WKS+A*%@u;?EJpFiZoJE) zRcI8gaA?#R+a{>B;(&pWXRSZjQeF~<XA<)EUXDukFe)w%*Q*|AGP*ON(Fjz$ra$z< zW;D}s$b?2MizWJ=Kw(gw=yVm;tj5!IYfy^#?(H&^H(sA@PtWAaN@0TD^xfqtnwEl) zGr5_sCPhO6;im%?TSRLUcAlh?<*3OIx&=kbd+=f~ZoKKmx%sTa1|@waKVOUA6wmgN zXQWG_<Q1<-{lA9Ay~V?-dli`<`X+_>IvXTXRui*@=Kf1_|DR_vf0q>}a~i=2rz+2` zXMFeE<97`?Mr%Jc!p4fy23(kPP|-$f0-3Q(;8ZU!j&NJHGP|m(09cKwOnFhvIx8J$ zIZ~0xx1+sm&(+QWLO{ak@aK1b8{XkWK?O#9jV=3#&I!la*?&a$zsujHDU&*d=}@$P zw9nBkoM*R=`h|M6IWVIf=tGes2n&0<xng*He>W*stV5~o>1UPOd6Y3GXpKpJ@!(pF zf>16B8E20c6W4<UkX~BhbpEynl5Es<g^K=9-vSxCs9K>ddNS?Tzk=hJ%|`;L)$c(% z3>6s`{$k~z?(kIo2Z|G;LWnij`sfHEK>4=AZg85}b2`|4^E$c<-4AOYaEY>#BSARo z^e?Q@Z77)6quz%=*jPWFVepB0QP)t?MNxhBesI&rD5lHAxnMr7rq_q(;zi(lbQ1%K z7SH^1at8FisQj|mm)CrjW4-0NV<^gQ3ustiUv4#8o8{+sS>oq9Mi$kU=c69V<)Ya4 zR+Q#R!6i)If$Mcl7DvtD$0SjQ#{cKT$h$I5+(Kx+OTEdfKZLx6(lxpwD@2EqAdM5r zEpF-pZD1KgW;$F&c>=c~jUlWk#-RJ*Bn-N#5rPhYYwPA1uv@$;1i#qttN_bE#z%zp z2?9kgb(Rg;IMuRvz(=FCq5dH6m)`Qz<GVg?SF2^)=AU1vUVB5;w7BwDImtMQEeB+y zMm1nzs7xjBT@`k-jPHn>l8S+pakoSznsUlT@wPc9GG0NKBYVc{<I#qUJNZ!8faQ?0 zI9HhVX7L-+<X}Kw$i?roB;^3g<^SE2$e0@EyGpWXD3cho%c}Q=6dqFF94vbdAEN^Z zT44oM)+-hGQgWJ54?1ls2ePY4bHTj;Ww3fRkaZnP<$?;6=n-34%cPnm+ol^`7ACQ( z#(JQ4u@(4Ey;X4uxzXcSU5l8L`uMc(l5bSbMB6!IcH6=#StUvfgP6CX2X72^zE}|v z$-ScEP=K(%P7W@O7T>)*?<m$b+;*Y8ycvIHe+7ak+Wj{YRkeMFk&lgx*dph23u-c) z_2;2j&rk89ezb4@pXVvY?*%BZ(6Ud(02Cqc7;ALd;?#33iNu*-iNrQ49u0#BiaW<A zcIC|}^&Up%Y@A50H3uHeJ~+iF!yBe9cAW~tg<pw2%q7~NJKr#uMERjq$=}oM-@mLQ z9E>!1a+LP4-_#Cp<NgX#Ux}NKi=Q7E2Y<<tBHvB>S_-@dWUInvlEm1(-%tL?;P=6& z&TPuK-4>8D)+aRgBcmMDw69mBs$5kykc^w!`xBAiKhqp<z_9V;<A1HH|FaFqVA6{s zCsX28ZpZ|Th`KG5iGQ1BJjcHL_l{*DGoIFV$y+1K>&sc;p;QCp`U)SP-S1sSs6-Xb zDQp)P`|JlJ>7tieTfd;>iUQ_NM-s8*Dv4BaJ0m<!Hn+K5FyOOIUk)Q*TETQf#HL+= zcCIou8&%Nuv)1(i{aniRBv@ga12^I8t#qJBu$@N_Z>MUujj+|(p&ajhGk>?!hX4On zE5N0DI7KE-?AMXL*0(^a@a!7DVoInhyp~xXs|sKH6Pi>7F;zpX&y5rTaFq}dM#e#H z6AoM`z+>CaC&BC015P*~sq0Nrv2i-ucRM_b_8uxUVsVCO(?|CGIbu)nW$Xr;!;IG@ zPzmWJWXLkDAue%K!cSk2KAO32z`|HPW_vZ?!Ja}~5G)SyaT~9QNG)@l{=3HEd0e<^ z8?ti-dFYgNeM|HQ^6TdK7HLcK4E6uKXY;4Ep}D?ZYdP5rBRUbYyY2h6jv2JU<nTWQ zd_R-$Uu$(#+KW7Rj9#VX95&hrR6m&1RS^t8a-f1(yS`g*fbWIQ_f?^4OG8&Kuy$0| zWFQ|b$w>H<J@b==G5Ps0l9R#fyH$&g(2wHb=?bs;K>H$tqpKlsvJVXli`?Wuf?kbq zlPh3evFvFG<pj6Tb|zEb*T+Hid})#x0}Xg0qZeuX%XXZfk#AWe@Kv|Ux2Lk+(7XQ& zd9H=&u)~0KW?~L&qQTZycd?LbX!~UI=W1TZH^61FIVsALCsAQ5HTV8pD;`ocCJjBm z|5;t;&o*hSSNYC5I$JieUQ9NRL9@v;6rdRn^D2B3VslyI6qBfOMV5<ElR6ILWg9+j zG50Ngtx4JCOi=-T1#^aMsGl6zQEpRPIeE|Zee(3iim*_wdYvY_YX`{nuxU^7-_&i- zdzb!qM6f#B8H^@#<{CYY9BHHsb^f2_P5!Ncuxxe1a)0$2U_h!?e87Kh9f@&Z1OtDC zEYh>v>tY~6AkXO%Djo**ciO3N=@({ZMxBLH!1*6t-*>cEp_1|Yr9}6--_(Q>sxnUR zWe<?6<v?%+K(R(Do?iCdeJ_q-FaM)YyZUGIJ2R6x0$mfT89MM^)8~3MT2)$F2ezRf z+c>-yS+p$zSiM+oz5LPFCirrBGogv)&-y5`$wgtcDfW{d-f8s3Wr;%NG1o``5AF!7 zWbg!zj*vl;BS=ejjJ>_J!XR$a*9~@;&RiB0f5n=CSH1nm;u#t?(4RDWi7J5}a{9XR z?f#{{osGLbhPQx^K<?r0aQ<YOYOqX>YWU(<Fa=(G#nKtvv263#EB$A1$G|Y^(|Laj z$XlpSo;f#klX0(EyX<9^cAjp<S8BShx0d!-a`LD<igE^obJ3ozW#JnV7yJF}9%WZ% zfSIv=py*IyJJbIHeexuYy;u|g2KZV4oTRL-CReu3h)QgbE_afKe$B((ZBXjcDVf1d z=H|SdU}&nTbP*+ikl1>yB&;uYPkiMCI7Ck<nZN8wowlfgW^U|!9}!Kp2?i_Yo@Z+0 ze-eN4=W2golKI+boWyiKqAYW>@^!`6Te0bCJG=&!q7f@@_i{EwysvIyN~mY!?|7bg zHFE0tN!?#_d-VU`Ajx;udCK&c;4gzcNYoIA<XCM;z?}smcCG_DuIeOu!H}%Hxw)F# z<jm|_f0p#~7%^BuOIisQrP%_t+r&L03su3g&@zp>&i1s5sQX_!Sm4?=9M(3%j-tKp zIfW_DyibbjHGEN==Xp$CU!JpcKbRI)b^~UHd?<ewRUv0A;Uy=WDiiTB2fR=1(5?&F zX7k7hixcJU0&*c|)2sufUH|tkNXE!zH|u!{5!oeXr&?!9p3FuV&~w)g6=h&P=XWbP zFv^g1XZ1ToNlo)xY^EW3t~T&@;%S{@a=iy+WsV>Jx0u`=S>$MSPnf^8QI<4Ppud|O z2TO`xNlmfy(`NTIMt);M?2P#Mj^ta1h;LiQbG4`4*v#r{`5b&^I><H7S9M3L8uE;8 z+re&fz+RQPe$VfPd3xK~UOVSuz`o1Mt<p@S7G6U2e@77iScUM7@s?2PlX`$dP3(&C zkKW4-TT(8g4tSx24PO%3m%Xz_GKJnZf55r3gNY2yG$yTKm41T?ugo$wdY6+gPnths zAF3NwDW{{oXrIDYFdd=f{n-!Nb|d+@NM$C#{OLLQ&$W@<CdvuNII<(?NxScLTf6nE zc@GbNe=)S6&G4vtUZEXbzrADU>dw5UDV(izuV{mLuMR)9&hJFcHa$KT>k(u&<!Y^; z#8wndBzM04&$v%Ps_iPl$T|)hIh=V9r&zAL$b#e?&ZpXBUysV>GeC+0CZ!_(zt*lj zp2_`>*CFdLmqG~Zc97+=2{D@;DzezzG9(S@=U^@=ml3&bl2MpjCM?<JUg{+3u!SVK z%~B_dC0ee_B`56nbk6T}j`RQT`Q!QbdH(o3@Av!jd4HexXL2>t=$Fi1rarEtm@nc7 zfkd$R;U@<9l^fj8KhR08<*ux|lX9`ks&$&){@wPRU|CcRDM&NJSte%(FG3AE>^FA5 zJ^o`$oY}ON@+F+|U7pGPD^l8c$EfhFF|_Ipd))wB!=BI}TP|fsI9zmMgjQo7^7lCF z`$X%PDLLc0#s`76oi{JvW{RhpwPThJJw_tH7G@oRo-Ou|JaiA`*sXS#ai1ld1GyI5 z?kXJ=HrYVEbPrkO%1cYPXGw6%<A~vtwz1&^RXJ_Wal`;&yRYAM45f@hwO}&E_(3Bf z6a5DoYZID^mkgS8yjA>13!7I>$}OC(9A#<oZl1-w9@r8yWE^{@31YUkgZ!Qu)`G}v zN8V%e=$i;zL2`>Ajs9~X)k32$>m$13V7a)oO6Guk#u3%PZF3sII}|8abDLlM^c=Pp zAP*7D<T%nVfV<P%n|d`?d;vvhQ$(V!)Qm}yi=A07PM5s*SQ>P)RgD7H8;k>M=r97i zGN;f8NHC{gY~sVfeswP}c?g<cW#O)1hIY26+X;2`Zf~%Zd8no|d};cT>^BymBiF^R z+Kzo)I1eJLS3{S|H}Nx|>#uB0rE0;7TA99?a4Y>NA^e>jIY3Q97HkUpNErW6YoJ`; z?q%`X7*~(%d&T`S+xn0zRpy#L4waAkNPD8K9<m5M1N5Izj{;XUMg8U+-Om#Phe%U- zNmN|$aN<6;@<q>}cb$uZ_0bkYUdg&K^K-IKw29sx?<&WZ+&h3OGB$hUNz8YwE-o*4 zq(eBtH4^NN>ssx*x*1>hwn#s;*)h$H=0J>qz-xu%GH3Q2wd)!@DwA$&TSu;VG~4x) z?BdG6&u0ynA}5DileGrM`Ukta?@S&{L_!G@`q84+Xi0%XjVHsmg7d9_V18Dw|J;+G zSFLZzB7>*G!In%Jgy_+pEc2xL#2rvhn1otv;4{C--t%7(EXT^-G^l@|(l`&@l%1F9 zb*zbl40IC+v)f*l8y5Rj{-{AvA*<VCGs>LhH-B3S-l&IJkjN%jWBF1haMEqVeEE`N zf-C+e#oH&^4I|&n3Dd7G-Nt=MNHAPliFCo6c1zvzGN{7$b2LyG8ytVS!8=;o=TfzG z!?E_e-nufQNO$v~3s9WP>V8_)DbyZ$a+ptA-onP#7T-K+l663HXr3Kf9k9;z_Q6V( zp<3yagT`hJMY|lTE8p_s$^(mq4ZBUKD-L~040*UYTs=g)J?yXTt$$8aE0yBWqn<=1 zeuQmkbRYHIB!47?2y19FAl4>BYTF}3=LUK7p1Wlr#Y11}^^`$?oEYPHAy04>YR^I2 zRtX;xu|Sx9$4yL)O{(>ce7nx4&tZ$LRUn8ZY%RC@6j8}JCVF&l?ZetjRihz&;r~&J zL!1vd&9Y)y8_L=nRJJXg%B2_C_K=DnM@-MN_5zV~bPEV_!)`M-a6YAl_VoiyyQjeH zUgZWOAw<?()!9G)M5iU$e<6Ev*ms!rrqfwi;H3rxJv`%%A_`JGwmoZWO&+=*9j&76 zl^J_1yqqN4p$P^Z?He_}?@3Lskd9p<Se8J^p{IJn^l9Xa(W1s3gG(J~%coD^hl}Nw zrFcMu!TZY$gKh2Ib{L0cr{1s5!dvby4>_6$g^EBsHF-ON6?Z=KX4hQYmomYvuXURN zA?4l{Rno;iDNR$+dw1g6X!Dx}@=n#zYB*(b)aQU~o;}VHF9#qi+Y>h4x<!&JH}0I~ z(h0C{`1X%mRj-x0)Wx?S56H?bDhZ|Fd!3gO_fd2R9U7<!w#V)f@F2%hJ#}#&Udv(~ zeonARk=6)}t|2O_TJu|f81F%tRIx)+!4;j~eu4d#L=s)o^_bnyZl_6NnJnRFr($QC zj*aEYue}*@8-kqsejxX(&FElN?|w8(b5@d(PCc4%YqD{H;`d2E!*qLri|t&cE*&e1 z55=j-bCYc4!4_)Db+XnF^<+ZG6`!;o3_F7j=TDt#ZfuasIq3J2j%imVDf9xBAPhL5 z07fCQYMaljpIkrkK)RUzN3z%qlqq<ISISLnA_iVMCB8r(s0b0>^1`ANPsV(8EzhoS zmxz#eBC_FeA4Ub@Z|IpG^l~z=iCkm#Ulq)$PJ}<*MoANtSp^$AoxT)20b7xyq<CA& zoR0oLFmnsV=NE?B5)YF&{@w`9hy_)7$TQA0$`VUF9phrFHq3v0J$cN%g}n<I;p$ma z`#1__h^vv#f)JmMk<=L2APD44f?V9~{yf>4en$Apq}=ZqUkB(AhR59L|3!j_ev(e= z%y+umcZQWGqWtPG8nNPcKs=8YE!`0GXiIrs-9)^A>8?Oj8bg_8)HfVkmscm%r<!af z(_Nj_gQx5Dz+Iek&yz2sT9AkgOO(6znf3`-oQ%==Cy<ic=67`5&KuH=^3Zj{eeTLL z_g(aS3K#eH{>qTGx|9&G3vg6P;r>2BRzqj1dyd|6l|;Clwv<5Ty8h@|o6mGhcY4K( zdrk$HsG=T<XLaP)yXSDOS$o(=geC_J{^@+a_Yj)ZWuVi`xrzS)Z-f_@2&A+XiCY3i zUWg|9B3ZL}K5%ko_!=nu3kVbd<j}<~UyPa<o*EpX`2)Z(l*HnaKy6_uLwA8Srp6_P zjty!411DW!-FH-^wY*VPeC9XNgIc~^QVlv+?+*T>@ZA2ytsq6E{2=9`qM`y-bo_MT z*t&(~;rI{pE9vc=l!0EU-J6jBn169P3KinPbB&eFPf>crTKphKvWxWD2}<j;(Ez-v z4hRY<lVf-q2fPmFcK7^RqKbl>AgN0dVh)=x4VfS4Qc3^5?pGff_kPF)dMbm0OBI?B zr^5Bk-jp(^h+)&4RGa%isIO?XpEV}vr9$4U)5?y<Cb+-AX~uYfkKo^~@o}dAuE3xx z55`&zJ4eQ|lKt5AInZWBz0dvw0_2Bu{0mH@+fY&&sGISnPw&NVi~*nNwicvaUMCVs z(gK=+Hg4H)y&vFJ?VQqX9X?DmbbJB~cMF1F-)0djJVSTMq_Q}?r)6bFzd=+j9*AFF zh!;9icUB3hq{pV_Ya=;EZ@pH@zl+b_i(LRk&5l&o9PcmxpHKEDzSsR|Ws#{#s-W0? zB4jJ^4`|D&Q{dBt+2V6hmX165Rc0X$Fg=5940GfputoUZfvw)i0tTRuI<}`=9>$g` zex0aFaCfM3WIHyvm*41b@B=N+jXnrnnZ2xo1#24OGAs+x;q#v{c{=);`v-RCoVfFd ze|Gf`H1iH<G<@wTOy=tAf0U;}%3xtV7pvJpLsX**JRh=th}@@qz%bLt1EM7WobU`I zpnLL%zs1yDr#S@G6@xR(%%i729HiS<nc=z!z7tCM5_84Q751r^)J%wa`pifa)2l$^ z9U6U7e)^4QZBkoDyJKeUh|m5RINPXeBegrEwqsDmmFC>==1=eNF9$J<-&$h9?_-Gf zTdPMdrhCjY7gBkqAKU5~k1sS*uu1jVyT~5xzTtt!^(iqqm<bH>Ec+*;Pp*FJ>Bn^< ziNDA7URBf~2TB{*{;jFM|HU|SRo7WM*dh0?hy1_pVba!%VhNGY-Ry#+(pR?tm)&vf Kv07_F(tiOru>)NI literal 92813 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 OPe$^wMDD|9-v0-lq2Gi6 diff --git a/architecture/index.rst b/architecture/index.rst index 5f298bfa0..83111b8cd 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -7,7 +7,7 @@ System Architecture The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. .. figure:: /_static/images/sqream_db_table_crop.png - :scale: 40 % + :scale: 60 % diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 9d50cccc5..97075a0af 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -7,6 +7,8 @@ Internals and Architecture Get to know the SQreamDB key functions and system architecture components and the best practices and customization possibilities. .. figure:: /_static/images/sqream_db_internals.png + :align: left + :width: 75% :alt: SQreamDB internals Key Functions and Components From 6d116ff6c199ac991a9e62bd4b5f58f5a90a2a06 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 13:45:55 +0300 Subject: [PATCH 0808/1892] Update add_column.rst --- .../ddl_commands/add_column.rst | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index bac71bd2c..da4587fc0 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -3,10 +3,12 @@ ********************** ADD COLUMN ********************** + The ``ADD COLUMN`` command is used to add columns to an existing table. Syntax ========== + The following is the correct syntax for adding a column to an existing table: .. code-block:: postgres @@ -19,7 +21,7 @@ The following is the correct syntax for adding a column to an existing table: schema_name ::= identifier - column_def :: = { column_name type_name [ default ] [ column_constraint ] } + column_def :: = { column_name type_name [ default ] [ column_constraint ] CHECK('CS "compression_type"') } column_name ::= identifier @@ -31,6 +33,7 @@ The following is the correct syntax for adding a column to an existing table: Parameters ============ + The following parameters can be used for adding a table: .. list-table:: @@ -50,6 +53,7 @@ The following parameters can be used for adding a table: Usage Notes =========== + The following usage notes apply when adding a column to an existing table: * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. @@ -60,14 +64,10 @@ The following usage notes apply when adding a column to an existing table: Examples =========== -The **Examples** section includes the following examples: - -.. contents:: - :local: - :depth: 1 Adding a Simple Column with a Default Value ----------------------------------------- + This example shows how to add a simple column with a default value: .. code-block:: postgres @@ -77,6 +77,7 @@ This example shows how to add a simple column with a default value: Adding Several Columns in One Command ------------------------------------------- + This example shows how to add several columns in one command: .. code-block:: postgres @@ -84,7 +85,18 @@ This example shows how to add several columns in one command: ALTER TABLE cool_animals ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + +Adding Compressed Column +-------------------------- + +.. code-block:: + + ALTER TABLE coo_animals ADD COLUMN animal_salary INT CHECK('CS "dict"'); + +Follow SQreamDB :ref:`compression guide<compression>` for compression types and methods. + Permissions ============= + The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From 7aefd07074f59565768e756fcb475812bbaa7bc1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:36:48 +0300 Subject: [PATCH 0809/1892] Driver and platform pages edit --- connecting_to_sqream/client_drivers/index.rst | 61 ++++++++++++++++++- .../client_platforms/index.rst | 50 +++++++++++++-- connecting_to_sqream/index.rst | 8 +++ 3 files changed, 111 insertions(+), 8 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index d5b5d2e06..730a27456 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -4,11 +4,12 @@ Client Drivers ************** -The guides on this page describe how to use the Sqream DB client drivers and client applications with SQream. +The guides on this page describe how to use the SqreamDB client drivers and client applications. Client Driver Downloads ======================= +<<<<<<< Updated upstream All Operating Systems --------------------- @@ -69,13 +70,65 @@ The following are applicable to Windows: * **Net driver** - `SQream .Net driver v3.0.2 <https://sq-ftp-public.s3.amazonaws.com/SqreamNet_net48_3.0.2.zip>`_ +======= +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Driver + - Download + - Docs + - Notes + - Operating System + * - **JDBC** + - `sqream-jdbc 4.5.9 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.9.jar>`_ + - :ref:`java_jdbc` + - Recommended installation via ``mvn`` + - All + * - **.NET** + - `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ + - :ref:`net` + - + - All + * - **Spark** + - `Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ + - :ref:`spark` + - + - All + * - **Python** + - `pysqream v3.2.5 <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ + - :ref:`pysqream` + - Recommended installation via ``pip`` + - All + * - **Node.JS** + - `sqream-v4.2.4 <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ + - :ref:`nodejs` + - Recommended installation via ``npm`` + - All + * - **Tableau** + - `Tableau Connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ + - :ref:`tableau` + - + - All + * - **Power BI** + - `Power BI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ + - :ref:`power_bi` + - + - All + * - **ODBC** + - For the **ODBC installer**, please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ + - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` + - + - Windows, Linux + +>>>>>>> Stashed changes .. toctree:: :maxdepth: 4 - :caption: Client Driver Documentation: :titlesonly: + :hidden: jdbc/index python/index @@ -90,4 +143,8 @@ The following are applicable to Windows: .. rubric:: Need help? +<<<<<<< Updated upstream +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ +======= If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ +>>>>>>> Stashed changes diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index acd0b757f..004008da9 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -2,27 +2,59 @@ **************** Client Platforms +<<<<<<< Updated upstream **************** These topics explain how to install and connect a variety of third party tools. +======= +************************************ +>>>>>>> Stashed changes -Browse the articles below, in the sidebar, or use the search to find the information you need. +SQreamDB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. +<<<<<<< Updated upstream Overview ======== +======= +.. figure:: /_static/images/connectivity_ecosystem.png + :align: right + :width: 800 +>>>>>>> Stashed changes -SQream DB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, tools, vizualisers, and utilities. +:ref:`Informatica Cloud Services<informatica>` -The tools listed have been tested and approved for use with SQream DB. Most 3\ :sup:`rd` party tools that work through JDBC, ODBC, and Python should work. +:ref:`microstrategy` +:ref:`Pentaho Data Integration<pentaho_data_integration>` + +:ref:`PHP<php>` + +:ref:`BI Desktop<power_bi>` + +:ref:`R<r>` + +:ref:`SAP BusinessObjects<sap_businessobjects>` + +:ref:`SAS Viya<connect_to_sas_viya>` + +:ref:`SQL Workbench<connect_to_sql_workbench>` + +:ref:`Tableau<tableau>` + +:ref:`Talend<talend>` + +:ref:`TUBCO<tibco_spotfire>` + + +<<<<<<< Updated upstream If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or contact your SQream account manager for more information. +======= +>>>>>>> Stashed changes .. toctree:: :maxdepth: 4 - :caption: In this section: :titlesonly: - - + :hidden: informatica microstrategy @@ -35,8 +67,14 @@ If you are looking for a tool that is not listed, SQream and our partners can he tableau talend tibco_spotfire +<<<<<<< Updated upstream denodo .. image:: /_static/images/connectivity_ecosystem.png +======= + + + +>>>>>>> Stashed changes diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index 1fc769b95..38626fddc 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,8 +1,16 @@ .. _connecting_to_sqream: +<<<<<<< Updated upstream ********************** Connecting to SQreamDB ********************** +======= +************************* +Connecting to SQream +************************* + +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. +>>>>>>> Stashed changes SQreamDB supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. From 911ccf0cebdcbb45d32f4ce7812b32965062f8a7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:46:49 +0300 Subject: [PATCH 0810/1892] Driver and platform pages edit --- connecting_to_sqream/client_drivers/index.rst | 76 +------------------ .../client_platforms/index.rst | 27 +------ connecting_to_sqream/index.rst | 14 +--- 3 files changed, 12 insertions(+), 105 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 730a27456..19b7eebfd 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -3,74 +3,12 @@ ************** Client Drivers ************** - + The guides on this page describe how to use the SqreamDB client drivers and client applications. Client Driver Downloads -======================= - -<<<<<<< Updated upstream -All Operating Systems ---------------------- - -The following are applicable to all operating systems: - - -**JDBC** - recommended installation via ``mvn``: - - * `JDBC .jar file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.9.jar>`_ - sqream-jdbc-4.5.9 (.jar) - * :ref:`java_jdbc` - - -**.NET**: - - * `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ - * :ref:`net` - -**Spark**: - - * `Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ - * :ref:`spark` - - -**Python** - Recommended installation via ``pip``: - - * `Python .tar file <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ - pysqream v3.2.5 (.tar.gz) - * :ref:`pysqream` - - -**Node.JS** - Recommended installation via ``npm``: +============================= - * `Node.JS <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - sqream-v4.2.4 (.tar.gz) - * :ref:`nodejs` - - -**Tableau**: - - * `Tableau connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - SQream (.taco) - * :ref:`tableau` - - -**Power BI**: - - * `Power BI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - SQream (.mez) - * :ref:`power_bi` - - - - -Windows -------- - -The following are applicable to Windows: - -* For the **ODBC installer**, please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_. - - For more information on installing and configuring ODBC on Windows, see :ref:`Install and configure ODBC on Windows <install_odbc_windows>`. - - -* **Net driver** - `SQream .Net driver v3.0.2 <https://sq-ftp-public.s3.amazonaws.com/SqreamNet_net48_3.0.2.zip>`_ -======= .. list-table:: :widths: auto :header-rows: 1 @@ -121,7 +59,6 @@ The following are applicable to Windows: - - Windows, Linux ->>>>>>> Stashed changes @@ -130,21 +67,16 @@ The following are applicable to Windows: :titlesonly: :hidden: + trino/index jdbc/index python/index nodejs/index odbc/index dotnet/index - php spark/index - .. rubric:: Need help? -<<<<<<< Updated upstream -If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ -======= -If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ ->>>>>>> Stashed changes +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 004008da9..4fdefb8fb 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -1,25 +1,14 @@ .. _client_platforms: -**************** +************************************ Client Platforms -<<<<<<< Updated upstream -**************** - -These topics explain how to install and connect a variety of third party tools. -======= ************************************ ->>>>>>> Stashed changes - + SQreamDB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. -<<<<<<< Updated upstream -Overview -======== -======= .. figure:: /_static/images/connectivity_ecosystem.png :align: right :width: 800 ->>>>>>> Stashed changes :ref:`Informatica Cloud Services<informatica>` @@ -46,19 +35,17 @@ Overview :ref:`TUBCO<tibco_spotfire>` -<<<<<<< Updated upstream -If you are looking for a tool that is not listed, SQream and our partners can help. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or contact your SQream account manager for more information. -======= ->>>>>>> Stashed changes .. toctree:: :maxdepth: 4 :titlesonly: :hidden: + trino informatica microstrategy pentaho + php power_bi r sap_businessobjects @@ -67,14 +54,8 @@ If you are looking for a tool that is not listed, SQream and our partners can he tableau talend tibco_spotfire -<<<<<<< Updated upstream - denodo - -.. image:: /_static/images/connectivity_ecosystem.png -======= ->>>>>>> Stashed changes diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index 38626fddc..fe7cc4f14 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -1,18 +1,12 @@ .. _connecting_to_sqream: -<<<<<<< Updated upstream + ********************** Connecting to SQreamDB ********************** -======= -************************* -Connecting to SQream -************************* - -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualiztion tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. ->>>>>>> Stashed changes + +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. -SQreamDB supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. .. toctree:: :maxdepth: 2 @@ -22,4 +16,4 @@ SQreamDB supports the most common database tools and interfaces, giving you dire client_platforms/index client_drivers/index -If you need a tool that SQream does not support, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or your SQream account manager for more information. \ No newline at end of file +If you need a tool that SQream does not support, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or your SQreamDB account manager for more information. \ No newline at end of file From 6333b3902f6339e18bea560366d32256d2ace7fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:56:53 +0300 Subject: [PATCH 0811/1892] Platform and Drivers --- .../client_platforms/index.rst | 38 ++++++++++++++----- .../client_platforms/microstrategy.rst | 2 +- connecting_to_sqream/index.rst | 5 ++- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 4fdefb8fb..32f9f6b24 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -10,30 +10,50 @@ SQreamDB is designed to work with most common database tools and interfaces, all :align: right :width: 800 -:ref:`Informatica Cloud Services<informatica>` +Data Integration Tools +---------------------- -:ref:`microstrategy` +:ref:`Informatica Cloud Services<informatica>` :ref:`Pentaho Data Integration<pentaho_data_integration>` -:ref:`PHP<php>` +:ref:`Talend<talend>` -:ref:`BI Desktop<power_bi>` +:ref:`SQL Workbench<connect_to_sql_workbench>` -:ref:`R<r>` +Business Intelligence (BI) Tools +-------------------------------- + +:ref:`MicroStrategy<micro_strategy>` + +:ref:`BI Desktop<power_bi>` :ref:`SAP BusinessObjects<sap_businessobjects>` :ref:`SAS Viya<connect_to_sas_viya>` -:ref:`SQL Workbench<connect_to_sql_workbench>` - :ref:`Tableau<tableau>` -:ref:`Talend<talend>` - :ref:`TUBCO<tibco_spotfire>` +Data Analysis and Programming Languages +--------------------------------------- + +:ref:`PHP<php>` + +:ref:`R<r>` + + + + + + + + + + + + .. toctree:: diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index 8947eb0e6..6c0aca4e6 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -1,4 +1,4 @@ -.. _microstrategy: +.. _micro_strategy: ************* diff --git a/connecting_to_sqream/index.rst b/connecting_to_sqream/index.rst index fe7cc4f14..5fe149e5f 100644 --- a/connecting_to_sqream/index.rst +++ b/connecting_to_sqream/index.rst @@ -5,7 +5,7 @@ Connecting to SQreamDB ********************** -SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. The tools described on this page have been tested and approved for use with SQream. Most third party tools that work through JDBC, ODBC, and Python should work. +SQream supports the most common database tools and interfaces, giving you direct access through a variety of drivers, connectors, and visualization tools and utilities. .. toctree:: @@ -16,4 +16,7 @@ SQream supports the most common database tools and interfaces, giving you direct client_platforms/index client_drivers/index + +.. rubric:: Need help? + If you need a tool that SQream does not support, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ or your SQreamDB account manager for more information. \ No newline at end of file From 6e7ad4bb5c8942d245d165c1e4283b7d70f350e8 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 10:41:49 +0300 Subject: [PATCH 0812/1892] Update decode.rst --- .../sql/sql_functions/scalar_functions/string/decode.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/decode.rst b/reference/sql/sql_functions/scalar_functions/string/decode.rst index 5329c49c8..6376bc3e3 100644 --- a/reference/sql/sql_functions/scalar_functions/string/decode.rst +++ b/reference/sql/sql_functions/scalar_functions/string/decode.rst @@ -37,14 +37,15 @@ Returns the same type as the argument supplied. Example ======= -.. code-block:: postgres +.. code-block:: sql CREATE TABLE test1 (european_size int not null); INSERT INTO test1 values (8),(9),(10),(11); SELECT european_size,DECODE(european_size,8,40,9,41,10,42,99) from test1; - +.. code-block:: none + +---------------+---------+ |european_size |decode | +---------------+---------+ From 8acf7bbedd615d2a64263de9bd6f66b103632b12 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 14:05:15 +0300 Subject: [PATCH 0813/1892] Update 2022.1.rst --- releases/2022.1.rst | 48 +++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 77386a5ae..6659d455e 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -1,8 +1,8 @@ .. _2022.1: -******************** +************************** Release Notes 2022.1 -******************** +************************** The 2022.1 release notes were released on 7/19/2022 and describe the following: @@ -11,9 +11,9 @@ The 2022.1 release notes were released on 7/19/2022 and describe the following: :depth: 1 Version Content ---------------- +---------------- -The 2022.1 Release Notes describes the following: +The 2022.1 Release Notes describe the following: * Enhanced security features. * New data manipulation command. @@ -25,7 +25,7 @@ Storage Version The storage version presently in effect is version 40. New Features ------------- +------------- The 2022.1 Release Notes include the following new features: @@ -34,7 +34,7 @@ The 2022.1 Release Notes include the following new features: :depth: 1 Data Encryption -*************** +***************** SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. @@ -43,21 +43,21 @@ Using the data encryption feature may lead to a maximum of a 10% increase in per For more information, see `Data Encryption <https://docs.sqream.com/en/v2022.1/feature_guides/data_encryption.html>`_. Update Feature -************** +**************** SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. For more information, see `UPDATE <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/update.html#update>`_. Avro Ingestion -************** +*************** SQream now supports ingesting data from Avro files. For more information, see `Inserting Data from Avro <https://docs.sqream.com/en/v2022.1/data_ingestion/avro.html>`_. Known Issues ------------- +------------- The following table lists the known issues for Version 2022.1: @@ -78,7 +78,7 @@ The following table lists the known issues for Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ Resolved Issues ---------------- +---------------- The following table lists the issues that were resolved in Version 2022.1: @@ -89,37 +89,37 @@ The following table lists the issues that were resolved in Version 2022.1: +-------------+-------------------------------------------------------------------------------------------+ Operations and Configuration Changes ------------------------------------- +---------------------------------------- No relevant operations and configuration changes were made. Naming Changes --------------- +----------------- No relevant naming changes were made. Deprecated Features -------------------- +--------------------- In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. -If you are using an earlier version of SQream, see the :ref:`Using Legacy String Literals <use_legacy_string_literals>` configuration flag. +If you are using an earlier version of SQream, see the `Using Legacy String Literals <https://docs.sqream.com/en/v2022.1/configuration_guides/use_legacy_string_literals.html>`_ configuration flag. End of Support --------------- +---------------- The End of Support section is not relevant to Version 2022.1. Upgrading to v2022.1 --------------------- +----------------------- -1. Generate a back-up of the metadata by running the following command: +1. Generate a backup of the metadata by running the following command: .. code-block:: console - $ select backup_metadata('out_path'); + $ select backup_metadata('out_path', 'single_file'); - .. tip:: SQream recommends storing the generated back-up locally in case needed. + .. tip:: SQream recommends storing the generated backup locally in case needed. SQream runs the Garbage Collector and creates a clean backup tarball package. @@ -127,11 +127,11 @@ Upgrading to v2022.1 :: -3. Extract the recently created back-up file. +3. Extract the recently created backup file. :: -4. Replace your current metadata with the metadata you stored in the back-up file. +4. Replace your current metadata with the metadata you stored in the backup file. :: @@ -147,3 +147,9 @@ Upgrading to v2022.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. toctree:: + :maxdepth: 2 + :glob: + :hidden: + + 2022.1 From d3fd72e6f53b3ab1f794d059161ca3e5bda30503 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 14:09:33 +0300 Subject: [PATCH 0814/1892] Update index.rst --- index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/index.rst b/index.rst index 05aa05061..796e5b230 100644 --- a/index.rst +++ b/index.rst @@ -73,7 +73,6 @@ If you couldn't find what you're looking for, we're always happy to help. Visit feature_guides/index data_ingestion/index external_storage_platforms/index - loading_and_unloading_data/index reference/index data_type_guides/index releases/index From b3e29fbba9e0676f06743137c07feea5ff781ad8 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 27 Aug 2023 14:11:45 +0300 Subject: [PATCH 0815/1892] Delete index.rst --- loading_and_unloading_data/index.rst | 37 ---------------------------- 1 file changed, 37 deletions(-) delete mode 100644 loading_and_unloading_data/index.rst diff --git a/loading_and_unloading_data/index.rst b/loading_and_unloading_data/index.rst deleted file mode 100644 index 88ee2d47a..000000000 --- a/loading_and_unloading_data/index.rst +++ /dev/null @@ -1,37 +0,0 @@ -.. _loading_and_unloading_data: - -************************** -Loading and Unloading Data -************************** - -The **Loading Data** section describes concepts and operations related to importing data into your SQream database: - -* :ref:`Overview of loading data <ingesting_data>` - Describes best practices and considerations for loading data into SQream from a variety of sources and locations. - -* :ref:`Alternatives to loading data (foreign tables) <foreign_tables>` - Useful for running queries directly on external data without importing into your SQream database. - -* :ref:`Supported data types <supported_data_types>` - Overview of supported data types, including descriptions, examples, and relevant aliases. - -* :ref:`Ingesting data from external sources <data_ingestion>` - List of data ingestion sources that SQream supports. - -* :ref:`Inserting data from external tables <insert>` - Inserts one or more rows into a table. - -* :ref:`Ingesting data from third party client platforms <client_platforms>` - Gives you direct access to a variety of drivers, connectors, tools, visualizers, and utilities.. - -* :ref:`Using the COPY FROM statement <copy_from>` - Used for loading data from files located on a filesystem into SQream tables. - -* :ref:`Importing data using Studio <executing_statements_and_running_queries_from_the_editor>` - SQream's web-based client providing users with all functionality available from the command line in an intuitive and easy-to-use format. - -* :ref:`Loading data using Amazon S3 <s3>` - Used for loading data from Amazon S3. - -* Troubleshooting - Describes troubleshooting solutions related to importing data from the following: - - * :ref:`SAS Viya <connect_to_sas_viya>` - - * :ref:`Tableau <tableau>` - -The **Unloading Data** section describes concepts and operations related to exporting data from your SQream database: - -* :ref:`Overview of unloading data <foreign_tables>` - Describes best practices and considerations for unloading data from SQream to a variety of sources and locations. - -* :ref:`The COPY TO statement <copy_to>` - Used for unloading data from a SQream database table or query to a file on a filesystem. \ No newline at end of file From dab428a6d452c2ea57f997e8be0737dbd87b8c76 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:22:19 +0300 Subject: [PATCH 0816/1892] Update catalog_reference_catalog_tables.rst --- .../catalog_reference_catalog_tables.rst | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index b62b6c321..24ddeb20f 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -3,6 +3,7 @@ ************************************* Catalog Tables ************************************* + The ``sqream_catalog`` includes the following tables: .. contents:: @@ -13,6 +14,7 @@ The ``sqream_catalog`` includes the following tables: Clustering Keys ---------------- + The ``clustering_keys`` data object is used for explicit clustering keys for tables. If you define more than one clustering key, each key is listed in a separate row, and is described in the following table: .. list-table:: @@ -36,6 +38,7 @@ The ``clustering_keys`` data object is used for explicit clustering keys for tab Columns ---------------- + The **Columns** database object shows the following tables: .. contents:: @@ -44,6 +47,7 @@ The **Columns** database object shows the following tables: Columns *********** + The ``column`` data object is used with standard tables and is described in the following table: .. list-table:: @@ -80,7 +84,8 @@ The ``column`` data object is used with standard tables and is described in the - Shows the timestamp displaying when the column was last altered. External Table Columns -*********** +************************ + The ``external_table_columns`` is used for viewing data from foreign tables. For more information on foreign tables, see :ref:`CREATE FOREIGN TABLE<create_foreign_table>`. @@ -89,6 +94,7 @@ For more information on foreign tables, see :ref:`CREATE FOREIGN TABLE<create_fo Databases ---------------- + The ``databases`` data object is used for displaying database information, and is described in the following table: .. list-table:: @@ -116,6 +122,7 @@ The ``databases`` data object is used for displaying database information, and i Permissions ---------------- + The ``permissions`` data object is used for displaying permissions information, such as roles (also known as **grantees**), and is described in the following tables: .. contents:: @@ -123,7 +130,8 @@ The ``permissions`` data object is used for displaying permissions information, :depth: 1 Permission Types -*********** +***************** + The ``permission_types`` object identifies the permission names existing in the database. The following table describes the ``permission_types`` data object: @@ -140,7 +148,8 @@ The following table describes the ``permission_types`` data object: - Shows the name of the permission type. Default Permissions -*********** +******************** + The commands included in the **Default Permissions** section describe how to check the following default permissions: .. contents:: @@ -148,7 +157,8 @@ The commands included in the **Default Permissions** section describe how to che :depth: 1 Default Table Permissions -~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~ + The ``sqream_catalog.table_default_permissions`` command shows the columns described below: .. list-table:: @@ -169,7 +179,8 @@ The ``sqream_catalog.table_default_permissions`` command shows the columns descr - Shows the type of permission granted. Default Schema Permissions -~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The ``sqream_catalog.schema_default_permissions`` command shows the columns described below: .. list-table:: @@ -190,7 +201,8 @@ The ``sqream_catalog.schema_default_permissions`` command shows the columns desc For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/access_control_commands/alter_default_permissions.html#granting-default-table-permissions>`_. Table Permissions -*********** +****************** + The ``table_permissions`` data object identifies all permissions granted to tables. Each role-permission combination displays one row. The following table describes the ``table_permissions`` data object: @@ -211,7 +223,8 @@ The following table describes the ``table_permissions`` data object: - Identifies the permission type. Database Permissions -*********** +********************* + The ``database_permissions`` data object identifies all permissions granted to databases. Each role-permission combination displays one row. The following table describes the ``database_permissions`` data object: @@ -230,7 +243,8 @@ The following table describes the ``database_permissions`` data object: - Identifies the permission type. Schema Permissions -*********** +******************** + The ``schema_permissions`` data object identifies all permissions granted to schemas. Each role-permission combination displays one row. The following table describes the ``schema_permissions`` data object: @@ -245,19 +259,23 @@ The following table describes the ``schema_permissions`` data object: - Shows the name of the database containing the schema. * - ``schema_id`` - Shows the ID of the schema the permission applies to. + * - ``getter_role_type`` + - Shows the type of role that is granted permissions. * - ``role_id`` - Shows the ID of the role granted permissions. * - ``permission_type`` - Identifies the permission type. UDF Permissions -*********** +***************** + **Comment** - *No content.* .. _queries: Queries ---------------- + The ``savedqueries`` data object identifies the saved_queries in the database, as shown in the following table: .. list-table:: @@ -277,6 +295,7 @@ For more information, see :ref:`saved_queries<saved_queries>`. Roles ---------------- + The ``roles`` data object is used for displaying role information, and is described in the following tables: .. contents:: @@ -285,6 +304,7 @@ The ``roles`` data object is used for displaying role information, and is descri Roles *********** + The ``roles`` data object identifies the roles in the database, as shown in the following table: .. list-table:: @@ -305,7 +325,8 @@ The ``roles`` data object identifies the roles in the database, as shown in the - Identifies whether the role has a password (``1`` - yes, ``0`` - no). Role Memberships -*********** +******************* + The ``roles_memberships`` data object identifies the role memberships in the database, as shown below: .. list-table:: @@ -327,6 +348,7 @@ The ``roles_memberships`` data object identifies the role memberships in the dat Schemas ---------------- + The ``schemas`` data object identifies all the database's schemas, as shown below: .. list-table:: @@ -348,16 +370,19 @@ The ``schemas`` data object identifies all the database's schemas, as shown belo Sequences ---------------- + The ``sequences`` data object is used for displaying identity key information, as shown below: Identity Key -*********** +************* + **Comment** - *No content.* .. _tables: Tables ---------------- + The ``tables`` data object is used for displaying table information, and is described in the following tables: .. contents:: @@ -366,6 +391,7 @@ The ``tables`` data object is used for displaying table information, and is desc Tables *********** + The ``tables`` data object identifies proper (**Comment** - *What does "proper" mean?*) SQream tables in the database, as shown in the following table: .. list-table:: @@ -390,7 +416,8 @@ The ``tables`` data object identifies proper (**Comment** - *What does "proper" - Relevant for internal use. Foreign Tables -*********** +**************** + The ``external_tables`` data object identifies foreign tables in the database, as shown below: .. list-table:: @@ -416,6 +443,7 @@ The ``external_tables`` data object identifies foreign tables in the database, a Views ---------------- + The ``views`` data object is used for displaying views in the database, as shown below: .. list-table:: @@ -438,7 +466,8 @@ The ``views`` data object is used for displaying views in the database, as shown .. _udfs: User Defined Functions ----------------- +----------------------- + The ``udf`` data object is used for displaying UDFs in the database, as shown below: .. list-table:: @@ -452,4 +481,4 @@ The ``udf`` data object is used for displaying UDFs in the database, as shown be * - ``function_id`` - Shows the UDF's database-unique ID. * - ``function_name`` - - Shows the name of the UDF. \ No newline at end of file + - Shows the name of the UDF. From 9d45ac81ac9c7fd082566ae032c1a8d8cb329114 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:26:50 +0300 Subject: [PATCH 0817/1892] Update avg.rst --- reference/sql/sql_functions/aggregate_functions/avg.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/avg.rst b/reference/sql/sql_functions/aggregate_functions/avg.rst index 4768061c8..9176b33b3 100644 --- a/reference/sql/sql_functions/aggregate_functions/avg.rst +++ b/reference/sql/sql_functions/aggregate_functions/avg.rst @@ -36,13 +36,13 @@ Arguments Returns ============ -Return type is dependant on the argument. +The return type depends on the argument. * For ``TINYINT``, ``SMALLINT`` and ``INT``, the return type is ``INT``. * For ``BIGINT``, the return type is ``BIGINT``. -* For ``REAL``, the return type is ``REAL`` +* For ``REAL``, the return type is ``DOUBLE`` * For ``DOUBLE``, rhe return type is ``DOUBLE`` From 7987a49368a0763ef10e95bce242273e6312a533 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:43:15 +0300 Subject: [PATCH 0818/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 32f9f6b24..d780b8ae5 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -34,7 +34,7 @@ Business Intelligence (BI) Tools :ref:`Tableau<tableau>` -:ref:`TUBCO<tibco_spotfire>` +:ref:`TIBCO<tibco_spotfire>` Data Analysis and Programming Languages --------------------------------------- From 1604128a0304eedee612daaed8ffdd0270e64178 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:45:49 +0300 Subject: [PATCH 0819/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index d780b8ae5..926b40154 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -4,7 +4,7 @@ Client Platforms ************************************ -SQreamDB is designed to work with most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. +SQreamDB is designed to work with the most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. .. figure:: /_static/images/connectivity_ecosystem.png :align: right @@ -26,7 +26,7 @@ Business Intelligence (BI) Tools :ref:`MicroStrategy<micro_strategy>` -:ref:`BI Desktop<power_bi>` +:ref:`POWERBI DESKTOP<power_bi>` :ref:`SAP BusinessObjects<sap_businessobjects>` From e761d18a51ca0086ed6ef5b8701dd613fc69c329 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:46:21 +0300 Subject: [PATCH 0820/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 19b7eebfd..39f47bfc2 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -54,7 +54,7 @@ Client Driver Downloads - - All * - **ODBC** - - For the **ODBC installer**, please contact your `Sqream representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ + - For the **ODBC installer**, please contact your `SQreamDB representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` - - Windows, Linux @@ -79,4 +79,4 @@ Client Driver Downloads .. rubric:: Need help? -If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ \ No newline at end of file +If you couldn't find what you're looking for, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ From 2a49e0df6baf302d7ebce7432fbd057868cbf506 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 27 Aug 2023 15:47:13 +0300 Subject: [PATCH 0821/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 39f47bfc2..d5f5a8670 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -49,7 +49,7 @@ Client Driver Downloads - - All * - **Power BI** - - `Power BI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ + - `POWERBI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - :ref:`power_bi` - - All From afd1090f28bcb7d97c99873e2b6cda98720093d8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:42:25 +0300 Subject: [PATCH 0822/1892] Update catalog_reference_catalog_tables.rst --- reference/catalog_reference_catalog_tables.rst | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 24ddeb20f..2dad31f6f 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -1,8 +1,8 @@ .. _catalog_reference_catalog_tables: -************************************* +************** Catalog Tables -************************************* +************** The ``sqream_catalog`` includes the following tables: @@ -123,7 +123,7 @@ The ``databases`` data object is used for displaying database information, and i Permissions ---------------- -The ``permissions`` data object is used for displaying permissions information, such as roles (also known as **grantees**), and is described in the following tables: +The ``permissions`` data object is used for displaying permission information, such as roles (also known as **grantees**), and is described in the following tables: .. contents:: :local: @@ -134,8 +134,6 @@ Permission Types The ``permission_types`` object identifies the permission names existing in the database. -The following table describes the ``permission_types`` data object: - .. list-table:: :widths: 20 180 :header-rows: 1 @@ -198,7 +196,7 @@ The ``sqream_catalog.schema_default_permissions`` command shows the columns desc * - ``permission_type`` - Shows the type of permission granted. -For an example of using the ``sqream_catalog.table_default_permissions`` command, see `Granting Default Table Permissions <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/access_control_commands/alter_default_permissions.html#granting-default-table-permissions>`_. +For an example of using the ``sqream_catalog.table_default_permissions`` command, see :ref:`Granting Default Table Permissions <alter_default_permissions>`. Table Permissions ****************** From 2d5d389ad71488220acafecda9948efe21ad2c60 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:43:19 +0300 Subject: [PATCH 0823/1892] Update rename_column.rst --- .../sql/sql_statements/ddl_commands/rename_column.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst index 1022ce0f2..239d7c7f8 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_column.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_column.rst @@ -3,10 +3,12 @@ ********************** RENAME COLUMN ********************** + The ``RENAME COLUMN`` command can be used to rename columns in a table. Syntax ========== + The following is the correct syntax for the ``RENAME_COLUMN`` command: .. code-block:: postgres @@ -25,6 +27,7 @@ The following is the correct syntax for the ``RENAME_COLUMN`` command: Parameters ============ + The following table describes the `RENAME_COLUMN`` parameters: .. list-table:: @@ -44,6 +47,7 @@ The following table describes the `RENAME_COLUMN`` parameters: Examples =========== + The **Examples** section includes the following examples: .. contents:: @@ -52,6 +56,7 @@ The **Examples** section includes the following examples: Renaming a Column ----------------------------------------- + The following is an example of renaming a column: .. code-block:: postgres @@ -61,12 +66,14 @@ The following is an example of renaming a column: Renaming a Quoted Name -------------------------- + The following is an example of renaming a quoted name: .. code-block:: postgres - ALTER TABLE users RENAME COLUMN "mass" TO "Mass (Kilograms); + ALTER TABLE users RENAME COLUMN "mass" TO "Mass" (Kilograms); Permissions ============= + The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file From d810a525d5afe7bc9da7f034bdf293bda3f75682 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 08:58:21 +0300 Subject: [PATCH 0824/1892] Update installing_prometheus_using_binary_packages.rst --- ...lling_prometheus_using_binary_packages.rst | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst index add951b1c..bd46d2fcc 100644 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ b/installation_guides/installing_prometheus_using_binary_packages.rst @@ -2,23 +2,18 @@ .. _install_prometheus_binary_top: -******************************************* +********************************************** Installing Prometheus Using Binary Packages -******************************************* +********************************************** -The **Installing Prometheus Using Binary Packages** guide includes the following sections: +Prometheus is an application used for event monitoring and alerting. .. contents:: :local: :depth: 1 -Overview -^^^^^^^^ - -Prometheus is an application used for event monitoring and alerting. - Installing Prometheus -^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^ You must install Prometheus before installing the Dashboard Data Collector. @@ -102,12 +97,12 @@ You must install Prometheus before installing the Dashboard Data Collector. $ sudo chown -R prometheus:prometheus /etc/prometheus/consoles $ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries -For more information on installing the Dashboard Data Collector, see `Installing the Dashboard Data Collector <https://docs.sqream.com/en/v2022.1/installation_guides/installing_dashboard_data_collector.html>`_. +For more information on installing the Dashboard Data Collector, see :ref:`Installing the Dashboard Data Collector<installing_dashboard_data_collector>`. Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Configuring Your Prometheus Settings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ After installing Prometheus you must configure your Prometheus settings. You must perform all Prometheus configurations in the **/etc/prometheus/prometheus.yml** file. @@ -164,7 +159,7 @@ After installing Prometheus you must configure your Prometheus settings. You mus Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Configuring Your Prometheus Service File -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ After configuring your Prometheus settings you must configure your Prometheus service file. @@ -221,9 +216,9 @@ After configuring your Prometheus settings you must configure your Prometheus se Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` Accessing the Prometheus User Interface -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -After configuring your prometheus service file, you can access the Prometheus user interface. +After configuring your Prometheus service file, you can access the Prometheus user interface. You can access the Prometheus user interface by running the following command: @@ -231,14 +226,5 @@ You can access the Prometheus user interface by running the following command: $ http://<prometheus-ip>:9090/graph -The Prometheus user interface is displayed. - -From the **Query** tab you can query metrics, as shown below: - -.. list-table:: - :widths: auto - :header-rows: 0 - - * - .. image:: /_static/images/3c9c4e8b-49bd-44a8-9829-81d1772ed962.gif +Once the Prometheus user interface is displayed, go to the **Query** tab and query metrics. -Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` \ No newline at end of file From 59a23356a0f3ce3e127a27f3f3b614f014aebd3b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 09:05:50 +0300 Subject: [PATCH 0825/1892] Update window_functions.rst --- reference/sql/sql_syntax/window_functions.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 7718e8b3a..b236c73b2 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -152,6 +152,7 @@ Window frame functions allows a user to perform rolling operations, such as calc ``PARTITION BY`` ------------------ + The ``PARTITION BY`` clause groups the rows of the query into partitions, which are processed separately by the window function. ``PARTITION BY`` works similarly to a query-level ``GROUP BY`` clause, but expressions are always just expressions and cannot be output-column names or numbers. @@ -168,10 +169,6 @@ Without ``ORDER BY``, rows are processed in an unspecified order. Frames ------- - - -.. note:: Frames and frame exclusions have been tested extensively, but are a complex feature. They are released as a preview in v2020.1 pending longer-term testing. - The ``frame_clause`` specifies the set of rows constituting the window frame, which is a subset of the current partition, for those window functions that act on the frame instead of the whole partition. The set of rows in the frame can vary depending on which row is the current row. The frame can be specified in ``RANGE`` or ``ROWS`` mode; in each case, it runs from the ``frame_start`` to the ``frame_end``. If ``frame_end`` is omitted, the end defaults to ``CURRENT ROW``. @@ -207,10 +204,9 @@ Frame Exclusion The ``frame_exclusion`` option allows rows around the current row to be excluded from the frame, even if they would be included according to the frame start and frame end options. ``EXCLUDE CURRENT ROW`` excludes the current row from the frame. ``EXCLUDE GROUP`` excludes the current row and its ordering peers from the frame. ``EXCLUDE TIES`` excludes any peers of the current row from the frame, but not the current row itself. ``EXCLUDE NO OTHERS`` simply specifies explicitly the default behavior of not excluding the current row or its peers. Limitations -================== -Window functions do not support the Numeric data type. - +================= +Window functions do not support the Numeric data type. Examples ========== From c8cf4dee9a423c3cd1b6a86c4dc4e9152626c8d0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 09:49:54 +0300 Subject: [PATCH 0826/1892] Update compression.rst --- feature_guides/compression.rst | 77 +++++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 20 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index e6143bc59..36d968b3c 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -3,40 +3,37 @@ *********************** Compression *********************** -The **Compression** page describes the following: + +SQreamDB uses a variety of compression and encoding methods to optimize query performance and to save disk space. .. contents:: :local: :depth: 1 -.. |icon-new_dark_gray_2022.1.1.png| image:: /_static/images/new_dark_gray_2022.1.1.png - :align: middle - :width: 110 - -SQream uses a variety of compression and encoding methods to optimize query performance and to save disk space. - Encoding ============= + **Encoding** is an automatic operation used to convert data into common formats. For example, certain formats are often used for data stored in columnar format, in contrast with data stored in a CSV file, which stores all data in text format. Encoding enhances performance and reduces data size by using specific data formats and encoding methods. SQream encodes data in a number of ways in accordance with the data type. For example, a **date** is stored as an **integer**, starting with **March 1st 1CE**, which is significantly more efficient than encoding the date as a string. In addition, it offers a wider range than storing it relative to the Unix Epoch. Lossless Compression -============== +======================= + **Compression** transforms data into a smaller format without sacrificing accuracy, known as **lossless compression**. -After encoding a set of column values, SQream packs the data and compresses it and decompresses it to make it accessible to users. Depending on the compression scheme used, these operations can be performed on the CPU or the GPU. Some users find that GPU compressions provide better performance. +After encoding a set of column values, SQream packs the data and compresses it and decompresses it to make it accessible to users. Depending on the compression scheme used, these operations can be performed on the CPU or the GPU. Some users find that GPU compression provide better performance. Automatic Compression ------------------------ -By default, SQream automatically compresses every column (see :ref:`Specifying Compression Strategies<specifying_compressions>` below for overriding default compressions). This feature is called **automatic adaptive compression** strategy. -When loading data, SQream DB automatically decides on the compression schemes for specific chunks of data by trying several compression schemes and selecting the one that performs best. SQream DB tries to balance more agressive compressions with the time and CPU/GPU time required to compress and decompress the data. +By default, SQream automatically compresses every column (see :ref:`Specifying Compression Strategies<specifying_compressions>` below for overriding default compression). This feature is called **automatic adaptive compression** strategy. + +When loading data, SQreamDB automatically decides on the compression schemes for specific chunks of data by trying several compression schemes and selecting the one that performs best. SQreamDB tries to balance more aggressive compression with the time and CPU/GPU time required to compress and decompress the data. Compression Methods ------------------------ - The following table shows the supported compression methods: .. list-table:: @@ -56,9 +53,9 @@ The following table shows the supported compression methods: - Automatic scheme selection - NA * - ``DICT`` - - Integer types, dates and timestamps, short texts + - All - - Dictionary compression with RLE. For each chunk, SQream DB creates a dictionary of distinct values and stores only their indexes. + Dictionary compression with RLE. For each chunk, SQreamDB creates a dictionary of distinct values and stores only their indexes. Works best for integers and texts shorter than 120 characters, with <10% unique values. @@ -67,7 +64,7 @@ The following table shows the supported compression methods: If the data is optionally sorted, this compression will perform even better. - GPU * - ``P4D`` - - Integer types, dates and timestamps + - ``Integer``, ``dates``, ``timestamps``, and ``float`` types - Patched frame-of-reference + Delta @@ -84,16 +81,44 @@ The following table shows the supported compression methods: - CPU * - ``RLE`` - Integer types, dates and timestamps - - Run-length encoding. This replaces sequences of values with a single pair. It is best for low cardinality columns that are used to sort data (``ORDER BY``). + - Run-Length Encoding. This replaces sequences of values with a single pair. It is best for low cardinality columns that are used to sort data (``ORDER BY``). - GPU * - ``SEQUENCE`` - - Integer types + - ``Integer``, ``date``, and ``timestamp`` - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. - GPU * - ``zlib`` - All types - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - CPU + * - ``SPACES`` + - + - Reduces the storage space required for data by identifying repeating sequences of values and replacing them with a compact representation. This method is particularly effective when there are repetitive patterns in the data. + - + * - ``DELTA_RLE`` + - Integer types + - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. + - CPU + * - ``SPADES`` + - + - An extension of ``SPACES`` compression, optimizing the compression scheme further to handle specific data patterns and types efficiently. + - + * - ``SPAPPY`` + - + - Specialized variation of the ``Snappy`` compression algorithm. ``Snappy`` is a fast and efficient compression method that works well with various types of data, offering good compression ratios and decompression speeds. + - + * - ``SPAZLY`` + - + - + - + * - ``CRLE`` + - + - + - + * - ``LZ4_ZIGZAG`` + - + - + - .. note:: Automatic compression does **not** select the ``zlib`` compression method. @@ -101,6 +126,7 @@ The following table shows the supported compression methods: Specifying Compression Strategies ---------------------------------- + When you create a table without defining any compression specifications, SQream defaults to automatic adaptive compression (``"default"``). However, you can prevent this by specifying a compression strategy when creating a table. This section describes the following compression strategies: @@ -111,6 +137,7 @@ This section describes the following compression strategies: Explicitly Specifying Automatic Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + When you explicitly specify automatic compression, the following two are equivalent: .. code-block:: postgres @@ -131,6 +158,7 @@ In this version, the default compression is specified explicitly: Forcing No Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + **Forcing no compression** is also known as "flat", and can be used in the event that you want to remove compression entirely on some columns. This may be useful for reducing CPU or GPU resource utilization at the expense of increased I/O. The following is an example of removing compression: @@ -144,6 +172,7 @@ The following is an example of removing compression: Forcing Compression ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + In other cases, you may want to force SQream to use a specific compression scheme based on your knowledge of the data, as shown in the following example: .. code-block:: postgres @@ -159,6 +188,7 @@ However, if SQream finds that the given compression method cannot effectively co Examining Compression Effectiveness -------------------------------------- + Queries made on the internal metadata catalog can expose how effective the compression is, as well as what compression schemes were selected. This section describes the following: @@ -169,6 +199,7 @@ This section describes the following: Querying the Catalog ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following is a sample query that can be used to query the catalog: .. code-block:: postgres @@ -191,7 +222,8 @@ The following is a sample query that can be used to query the catalog: 2; Example Subset from "Ontime" Table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following is an example (subset) from the ``ontime`` table: .. code-block:: psql @@ -283,7 +315,8 @@ The following is an example (subset) from the ``ontime`` table: year | rle | 6 | 2065915 | 317216.08 | default Notes on Reading the "Ontime" Table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following are some useful notes on reading the "Ontime" table shown above: #. Higher numbers in the **Compression effectiveness** column represent better compressions. **0** represents a column that has **not been compressed**. @@ -302,6 +335,7 @@ The following are some useful notes on reading the "Ontime" table shown above: Best Practices ============================== + This section describes the best compression practices: .. contents:: @@ -309,16 +343,19 @@ This section describes the best compression practices: :depth: 1 Letting SQream Determine the Best Compression Strategy ----------------------------------------------------- +------------------------------------------------------- + In general, SQream determines the best compression strategy for most cases. If you decide to override SQream's selected compression strategies, we recommend benchmarking your query and load performance **in addition to** your storage size. Maximizing the Advantage of Each Compression Scheme ------------------------------------------------------- + Some compression schemes perform better when data is organized in a specific way. For example, to take advantage of RLE, sorting a column may result in better performance and reduced disk-space and I/O usage. Sorting a column partially may also be beneficial. As a rule of thumb, aim for run-lengths of more than 10 consecutive values. Choosing Data Types that Fit Your Data --------------------------------------- + Adapting to the narrowest data type improves query performance while reducing disk space usage. However, smaller data types may compress better than larger types. For example, SQream recommends using the smallest numeric data type that will accommodate your data. Using ``BIGINT`` for data that fits in ``INT`` or ``SMALLINT`` can use more disk space and memory for query execution. Using ``FLOAT`` to store integers will reduce compression's effectiveness significantly. \ No newline at end of file From 70dddd9a221c325390f289ce5ee5fad993ce62c8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 10:06:31 +0300 Subject: [PATCH 0827/1892] naming platforms and drivers --- connecting_to_sqream/client_drivers/index.rst | 6 +++--- connecting_to_sqream/client_platforms/index.rst | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index d5f5a8670..8173c9a1a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -28,8 +28,8 @@ Client Driver Downloads - :ref:`net` - - All - * - **Spark** - - `Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ + * - **Apache Spark** + - `Apache Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ - :ref:`spark` - - All @@ -49,7 +49,7 @@ Client Driver Downloads - - All * - **Power BI** - - `POWERBI PowerQuery Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ + - `Power BI Power Query Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - :ref:`power_bi` - - All diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 926b40154..a6c6d1aca 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -15,7 +15,7 @@ Data Integration Tools :ref:`Informatica Cloud Services<informatica>` -:ref:`Pentaho Data Integration<pentaho_data_integration>` +:ref:`Pentaho Data Integration and Analytics<pentaho_data_integration>` :ref:`Talend<talend>` @@ -26,7 +26,7 @@ Business Intelligence (BI) Tools :ref:`MicroStrategy<micro_strategy>` -:ref:`POWERBI DESKTOP<power_bi>` +:ref:`Power BI Desktop<power_bi>` :ref:`SAP BusinessObjects<sap_businessobjects>` From 832c7bde184ba2cc15da0831ac4a63e78417b3f4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:06:56 +0300 Subject: [PATCH 0828/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 3671474b2..990f49075 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -108,10 +108,10 @@ Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: “gpu”: 0, “licensePath”: “home/test_user/SQream/tests/license.enc”, “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, + “metadataServerIp”: 127.0.0.1, + “metadataServerPort”: 3105, “port”: 5000, - “useConfigIP”” true, + “useConfigIP”: true, “limitQueryMemoryGB" : 201, } From 4d1928aa26fba7997df94bb9cca84c05aead499a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 13:28:17 +0300 Subject: [PATCH 0829/1892] Update drop_database.rst --- .../sql_statements/ddl_commands/drop_database.rst | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/drop_database.rst b/reference/sql/sql_statements/ddl_commands/drop_database.rst index f45b0a5c4..76b75c5b3 100644 --- a/reference/sql/sql_statements/ddl_commands/drop_database.rst +++ b/reference/sql/sql_statements/ddl_commands/drop_database.rst @@ -17,7 +17,7 @@ Syntax .. code-block:: postgres drop_database_statement ::= - DROP DATABASE database_name + DROP DATABASE [ IF EXISTS ] database_name ; database_name ::= identifier @@ -35,7 +35,9 @@ Parameters - Description * - ``database_name`` - The name of the database to drop. This can not be the current database in use. - + * - ``IF EXISTS`` + - Drop the database if it exists. No error if the database does not exist. + Examples =========== @@ -60,4 +62,10 @@ The current database in use can't be dropped. Switch to another database first. raviga=> \c master master=> DROP DATABASE raviga; - executed \ No newline at end of file + executed + +.. code-block:: sql + + DROP DATABASE IF EXISTS green_database; + + Status: Ended successfully \ No newline at end of file From e72b278de539621b55b38ae5bb6c22957f84bcaa Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:22:15 +0300 Subject: [PATCH 0830/1892] clustering --- connecting_to_sqream/client_drivers/index.rst | 1 - .../client_platforms/index.rst | 2 +- .../ddl_commands/create_table.rst | 38 +++++++++++++------ 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 8173c9a1a..40f34d659 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -67,7 +67,6 @@ Client Driver Downloads :titlesonly: :hidden: - trino/index jdbc/index python/index nodejs/index diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index a6c6d1aca..925d01ff1 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -34,7 +34,7 @@ Business Intelligence (BI) Tools :ref:`Tableau<tableau>` -:ref:`TIBCO<tibco_spotfire>` +:ref:`TIBCO Spotfire<tibco_spotfire>` Data Analysis and Programming Languages --------------------------------------- diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 5ca988f19..76b3e3086 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -14,6 +14,7 @@ The ``CREATE TABLE`` statement is used to create a new table in an existing data Syntax ========== + The following is the correct syntax for creating a table: .. code-block:: postgres @@ -42,6 +43,7 @@ The following is the correct syntax for creating a table: Parameters ============ + The following parameters can be used when creating a table: .. list-table:: @@ -60,9 +62,9 @@ The following parameters can be used when creating a table: - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. * - ``CLUSTER BY column_name1 ...`` - - A commma separated list of clustering column keys. + A comma separated list of clustering column keys. - See :ref:`flexible_data_clustering` for more information. + See :ref:`cluster_by` for more information. * - ``LIKE`` - Duplicates the column structure of an existing table. @@ -70,7 +72,7 @@ The following parameters can be used when creating a table: .. _default_values: Default Value Constraints -=============== +=========================== The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. @@ -80,6 +82,7 @@ The default value may be a literal or NULL. Syntax --------- + The following is the correct syntax for using the **DEFAULT** value constraints: @@ -105,6 +108,7 @@ The following is the correct syntax for using the **DEFAULT** value constraints: Identity ----------------------- + The ``Identity`` (or sequence) columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. The **identity** property on a column guarantees that each new row inserted is generated based on the current seed & increment. @@ -127,6 +131,7 @@ The following table describes the identity parameters: Examples =========== + This section includes the following examples: .. contents:: @@ -134,7 +139,8 @@ This section includes the following examples: :depth: 1 Creating a Standard Table ------------------ +-------------------------- + The following is an example of the syntax used to create a standard table: .. code-block:: postgres @@ -147,7 +153,8 @@ The following is an example of the syntax used to create a standard table: ); Creating a Table with Default Value Constraints for Some Columns ---------------------------------------------------- +-------------------------------------------------------------------- + The following is an example of the syntax used to create a table with default value constraints for some columns: @@ -164,6 +171,7 @@ The following is an example of the syntax used to create a table with default va Creating a Table with an Identity Column --------------------------------------------------- + The following is an example of the syntax used to create a table with an identity (auto-increment) column: @@ -179,6 +187,7 @@ The following is an example of the syntax used to create a table with an identit Creating a Table from a SELECT Query ----------------------------------------- + The following is an example of the syntax used to create a table from a SELECT query: .. code-block:: postgres @@ -189,6 +198,7 @@ For more information on creating a new table from the results of a SELECT query, Creating a Table with a Clustering Key ---------------------------------------------- + When data in a table is stored in a sorted order, the sorted columns are considered clustered. Good clustering can have a significant positive impact on performance. In the following example, we expect the ``start_date`` column to be naturally clustered, as new users sign up and get a newer start date. @@ -205,13 +215,14 @@ The following is an example of the syntax used to create a table with a clusteri country TEXT(30) DEFAULT 'Unknown' NOT NULL ) CLUSTER BY start_date; -For more information on data clustering, see :ref:`data_clustering`. +For more information on data clustering, see :ref:`cluster_by`. Duplicating the Column Structure of an Existing Table ------------------ +------------------------------------------------------------ Syntax ************ + The following is the correct syntax for duplicating the column structure of an existing table: .. code-block:: postgres @@ -226,6 +237,7 @@ The following is the correct syntax for duplicating the column structure of an e Examples ************** + This section includes the following examples of duplicating the column structure of an existing table using the ``LIKE`` clause: .. contents:: @@ -233,15 +245,17 @@ This section includes the following examples of duplicating the column structure :depth: 3 Creating a Table Using an Explicit Column List -~~~~~~~~~~~~ -The following is an example of creating a table using an explict column list: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following is an example of creating a table using an explicit column list: .. code-block:: postgres CREATE TABLE t1(x int default 0 not null, y text(10) null); Creating a Second Table Based on the Structure of Another Table -~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Either of the following examples can be used to create a second table based on the structure of another table. **Example 1** @@ -259,7 +273,8 @@ Either of the following examples can be used to create a second table based on t The generated output of both of the statements above is identical. Creating a Table based on Foreign Tables and Views -~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The following is an example of creating a table based on foreign tables and views: @@ -290,4 +305,5 @@ The following table describes which properties are copied from the target table Permissions ============= + The role must have the ``CREATE`` permission at the schema level. From 4fb29e0025a24c31673a5444e35aafcde2d0af57 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:34:13 +0300 Subject: [PATCH 0831/1892] Update ceiling.rst --- .../sql/sql_functions/scalar_functions/numeric/ceiling.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index 9d91611a6..64464ee9f 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -When using the ``CEILING`` and ``CEIL`` floating point number scalar functions, ``real`` arguments are automatically cast to ``double`` precision. +``real`` arguments are automatically cast to ``double`` precision. Notes From eb547f2687ec1abbe0975952f52d5d96c27c74b9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:34:59 +0300 Subject: [PATCH 0832/1892] Update ceiling.rst --- .../sql/sql_functions/scalar_functions/numeric/ceiling.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst index 64464ee9f..8c48420fd 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/ceiling.rst @@ -32,7 +32,7 @@ Arguments Returns ============ -``real`` arguments are automatically cast to ``double`` precision. +``Real`` arguments are automatically cast to ``double`` precision. Notes From 49b292f262ac886c8d8c25daf839a0679a8adfcd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 28 Aug 2023 15:53:45 +0300 Subject: [PATCH 0833/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 990f49075..a0ff5128e 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -7,7 +7,7 @@ Sizing Concurrency and Scaling in SQreamDB =================================== -A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions with minimal resource requirements, such as :ref:`show_server_status`, will be executed regardless of the workload. +A SQreamDB cluster can execute one statement per worker process while also supporting the concurrent operation of multiple workers. Utility functions with minimal resource requirements, such as :ref:`show_server_status`, :ref:`show_locks`, and :ref:`show_node_info` will be executed regardless of the workload. Minimum Resource Required Per Worker: From d74704dcfdc857b62ad4198bb9ea2a051764263e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 29 Aug 2023 08:50:49 +0300 Subject: [PATCH 0834/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 1d10fb819..ddf97464c 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -733,11 +733,11 @@ Improving Query Performance .. code-block:: sql - SELECT AVG(t_b.j :: BIGINT), - t_a.country_code - FROM t_a - JOIN t_b ON (crc64_join(t_a.fk) = crc64_join(t_b.id)) - GROUP BY t_a.country_code + SELECT AVG(t_b.j::BIGINT), t_a.country_code + FROM "public"."t_a" + JOIN "public"."t_b" ON (CRC64(t_a.fk::TEXT) = CRC64(t_b.id::TEXT)) + GROUP BY t_a.country_code; + The execution below has been shortened, but note the highlighted rows for ``Join``. The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. From 463d1e9929646dfc38494dedc465e7ccceb6b59e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 29 Aug 2023 09:48:52 +0300 Subject: [PATCH 0835/1892] Update add_column.rst --- reference/sql/sql_statements/ddl_commands/add_column.rst | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index da4587fc0..0cf7143fd 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -54,13 +54,7 @@ The following parameters can be used for adding a table: Usage Notes =========== -The following usage notes apply when adding a column to an existing table: - - * When adding a new column to an existing table, a default (or null constraint) has to be specified, even if the table is empty. - - :: - - * New columns you add to the table cannot be TEXT or contain an IDENTITY. +When adding an empty column, the default values for that column will be set to ``NULL``. Examples =========== From dcf7d55678422a75069ec517f02af704c365ba56 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 29 Aug 2023 11:53:49 +0300 Subject: [PATCH 0836/1892] Update current_method_configuring_your_parameter_values.rst --- .../current_method_configuring_your_parameter_values.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/current_method_configuring_your_parameter_values.rst b/configuration_guides/current_method_configuring_your_parameter_values.rst index 027a1a710..91c79e6d4 100644 --- a/configuration_guides/current_method_configuring_your_parameter_values.rst +++ b/configuration_guides/current_method_configuring_your_parameter_values.rst @@ -23,11 +23,11 @@ Parameter Values +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ | ``SELECT show_conf_extended();`` | Used to print all information output by the show_conf UF command, in addition to description, usage, data type, default value and range. | ``rechunkThreshold,90,true,RND,regular`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``show_md_flag UF`` | Used to show a specific flag/all flags stored in the metadata file. |* Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` | +| ``show_md_flag UF`` | Used to show a specific flag/all flags stored in the metadata. |* Example 1: ``* master=> ALTER SYSTEM SET heartbeatTimeout=111;`` | | | |* Example 2: ``* master=> select show_md_flag(‘all’); heartbeatTimeout,111`` | | | |* Example 3: ``* master=> select show_md_flag(‘heartbeatTimeout’); heartbeatTimeout,111`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``ALTER SYSTEM SET <flag-name>`` | Used for storing or modifying flag attributes in the metadata file. | ``ALTER SYSTEM SET <heartbeatInterval=12;>`` | +| ``ALTER SYSTEM SET <flag-name>`` | Used for storing or modifying flag attributes in the metadata. | ``ALTER SYSTEM SET <heartbeatInterval=12;>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ -| ``ALTER SYSTEM RESET <flag-name / ALL>`` | Used to remove a flag or all flag attributes from the metadata file. | ``ALTER SYSTEM RESET <heartbeatInterval ALTER SYSTEM RESET ALL>`` | +| ``ALTER SYSTEM RESET <flag-name / ALL>`` | Used to remove a flag or all flag attributes from the metadata. | ``ALTER SYSTEM RESET <heartbeatInterval ALTER SYSTEM RESET ALL>`` | +-----------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------+ \ No newline at end of file From 52ad9cbe4ea78b482d461dbe2e0db8a2a54ecc77 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:53:29 +0300 Subject: [PATCH 0837/1892] python and ODBC --- .../odbc/install_configure_odbc_linux.rst | 4 ++-- .../odbc/install_configure_odbc_windows.rst | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index 61919f161..075ba254c 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -14,9 +14,9 @@ The ODBC driver for Windows is provided as a shared library. This tutorial shows how to install and configure ODBC on Linux. -.. contents:: In this topic: +.. contents:: :local: - :depth: 2 + :depth: 1 Prerequisites ============== diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst index 4972e3057..e3f198d0c 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst @@ -8,9 +8,9 @@ The ODBC driver for Windows is provided as a self-contained installer. This tutorial shows you how to install and configure ODBC on Windows. -.. contents:: In this topic: +.. contents:: :local: - :depth: 2 + :depth: 1 Installing the ODBC Driver ================================== @@ -31,7 +31,7 @@ Administrator Privileges The SQream DB ODBC driver requires administrator privileges on your computer to add the DSNs (data source names). -1. Run the Windows installer +Running the Windows Installer ------------------------------ Install the driver by following the on-screen instructions in the easy-to-follow installer. @@ -40,7 +40,7 @@ Install the driver by following the on-screen instructions in the easy-to-follow .. note:: The installer will install the driver in ``C:\Program Files\SQream Technologies\ODBC Driver`` by default. This path is changable during the installation. -2. Selecting Components +Selecting Components ^^^^^^^^^^^^^^^^^^^^^^^^^^ The installer includes additional components, like JDBC and Tableau customizations. @@ -53,7 +53,7 @@ Once the installer finishes, you will be ready to configure the DSN for connecti .. _create_windows_odbc_dsn: -3. Configuring the ODBC Driver DSN +Configuring the ODBC Driver DSN ====================================== ODBC driver configurations are done via DSNs. Each DSN represents one SQream DB database. @@ -104,7 +104,7 @@ Connection Parameters * - Database - Specifies the database name to connect to. For example, ``master`` * - Service - - Specifices :ref:`service queue<workload_manager>` to use. For example, ``etl``. Leave blank for default service ``sqream``. + - Specifies :ref:`service queue<workload_manager>` to use. For example, ``etl``. Leave blank for default service ``sqream``. * - Server - Hostname of the SQream DB worker. For example, ``127.0.0.1`` or ``sqream.mynetwork.co`` * - Port From b5c70921209db85333a9792b4b145061291e1b0f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 29 Aug 2023 15:32:33 +0300 Subject: [PATCH 0838/1892] Update 4.3.rst --- releases/4.3.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index f87235fb8..b742bf32c 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -173,8 +173,7 @@ There are two methods of granting back access to services: .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -Version 4.3.1 Rollback To Version 4.0.1 ---------------------------------------- + From 1e98bbde0dc9d9b546d77f29ee3eaa38ca232f20 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 30 Aug 2023 09:04:41 +0300 Subject: [PATCH 0839/1892] Update internals_architecture.rst --- architecture/internals_architecture.rst | 45 +++++++++---------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 97075a0af..0d319678f 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -19,38 +19,37 @@ Statement Compiler The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement plans. -Concurrency and Admission Control ---------------------------------- - -The SQreamDB execution engine employs thread workers and message passing for its foundation. This threading approach enables the concurrent execution of diverse operations, seamlessly integrating IO and GPU tasks with CPU operations while boosting the performance of CPU-intensive tasks. +Building Blocks +--------------- -Learn more about :ref:`concurrency_and_scaling_in_sqream`. +In SQreamDB, the main workload is carried out by specialized C++/CUDA building blocks intentionally kept devoid of inherent intelligence; they require precise instructions for operation. The task of effectively assembling these components relies largely on the capabilities of the statement compiler. Storage Layer ------------- -The storage is split into the metadata layer and an append-only / garbage collected bulk data layer. +The storage is split into the metadata layer and an append-only / garbage-collected bulk data layer. Metadata Layer ^^^^^^^^^^^^^^ -The metadata layer uses RocksDB, and uses RocksDB's snapshot and write atomic features as part of the transaction system. - -The metadata layer, together with the append-only bulk data layer help ensure consistency. +Utilizing RocksDB, the metadata layer incorporates features such as snapshots and atomic writes within the transaction system, while working in conjunction with the append-only bulk data layer to maintain overall data consistency. Bulk Data Layer ^^^^^^^^^^^^^^^ -The bulk data layer is comprised of extents, which are optimized for IO performance as much as possible. Inside the extents, are chunks, which are optimized for processing in the CPU and GPU. Compression is used in the extents and chunks. - -When you run small inserts, you will get less optimized chunks and extents, but the system is designed to both be able to still run efficiently on this, and to be able to reorganize them transactionally in the background, without blocking DML operations. By writing small chunks in small inserts, then reorganizing later, it supports both fast medium sized insert transactions and fast querying. +The bulk data layer consists of IO-optimized extents, containing CPU and GPU-efficient chunks, both of which incorporate compression. During small insert operations, less optimized chunks and extents might result, yet the system is intentionally designed to maintain operational efficiency in such scenarios. It achieves this by facilitating background transactional reorganization without disrupting DML operations. By initially writing small chunks via small inserts and subsequently reorganizing them, the system accommodates swift medium-sized insert transactions while enabling rapid querying capabilities. Columnar Storage ^^^^^^^^^^^^^^^^ -Like many other analytical database management systems, SQreamDB uses a column store for tables. +Similar to numerous other analytical database management systems, SQreamDB employs a column store structure for its tables, leveraging the advantages it provides. This approach enhances I/O efficiency and overall performance when dealing with analytic workloads. Furthermore, columns exhibit superior compression properties and are particularly suited for handling bulk data operations. + +Concurrency and Admission Control +--------------------------------- + +The SQreamDB execution engine employs thread workers and message passing for its foundation. This threading approach enables the concurrent execution of diverse operations, seamlessly integrating IO and GPU tasks with CPU operations while boosting the performance of CPU-intensive tasks. -Column stores offer better I/O and performance with analytic workloads. Columns also compress much better, and lend themselves well to bulk data. +Learn more about :ref:`concurrency_and_scaling_in_sqream`. Transactions ------------ @@ -67,27 +66,13 @@ SQreamDB has serializable transactions, with these features: * Other operations such as :ref:`delete`, :ref:`truncate`, and DDL use :ref:`coarse-grained exclusive locking<concurrency_and_locks>`. - - -Building Blocks ---------------- - -The heavy lifting in SQreamDB is done by single purpose C++/CUDA building blocks. - -These are purposely designed to not be smart - they have to be instructed exactly what to do. - -Most of the intelligence in piecing things together is in the statement compiler. - - - - GPU Usage ========= -SQreamDB uses GPUs for accelerating database operations. This acceleration brings additional benefit to columnar data processing. +SQreamDB uses GPUs for accelerating database operations. This acceleration brings additional benefits to columnar data processing. SQreamDB's GPU acceleration is integral to database operations. It is not an additional feature, but rather core to most data operations, e.g. ``GROUP BY``, scalar functions, ``JOIN``, ``ORDER BY``, and more. -Using a GPU is an extended form of SIMD (Single-instruction, multiple data) intended for high throughput operations. When GPU acceleraiton is used, SQreamDB uses special building blocks to take advantage of the high degree of parallelism of the GPU. This means that GPU operations use a single instruction that runs on multiple values. +Using a GPU is an extended form of SIMD (Single-Instruction, Multiple Data) intended for high throughput operations. When GPU acceleration is used, SQreamDB uses special building blocks to take advantage of the high degree of parallelism of the GPU. This means that GPU operations use a single instruction that runs on multiple values. From 8043d7de767989cd73c99f473094e6c1a78c6e07 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 30 Aug 2023 14:25:37 +0300 Subject: [PATCH 0840/1892] Update catalog_reference_catalog_tables.rst --- reference/catalog_reference_catalog_tables.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 2dad31f6f..e771b9697 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -195,6 +195,8 @@ The ``sqream_catalog.schema_default_permissions`` command shows the columns desc - Shows the role that the permission is granted to. * - ``permission_type`` - Shows the type of permission granted. + * - ``getter_role_type`` + - Shows the type of role that is granted permissions. For an example of using the ``sqream_catalog.table_default_permissions`` command, see :ref:`Granting Default Table Permissions <alter_default_permissions>`. @@ -257,8 +259,6 @@ The following table describes the ``schema_permissions`` data object: - Shows the name of the database containing the schema. * - ``schema_id`` - Shows the ID of the schema the permission applies to. - * - ``getter_role_type`` - - Shows the type of role that is granted permissions. * - ``role_id`` - Shows the ID of the role granted permissions. * - ``permission_type`` From 9817a68ddbf725b65ad628c15319638e453743dc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 08:07:53 +0300 Subject: [PATCH 0841/1892] Update compression.rst --- feature_guides/compression.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 36d968b3c..818e0366d 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -114,7 +114,7 @@ The following table shows the supported compression methods: * - ``CRLE`` - - - - + - CPU * - ``LZ4_ZIGZAG`` - - From ac7085acf1b96a395f06c75577f8e7999c9f25a1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 08:08:42 +0300 Subject: [PATCH 0842/1892] Update 4.3.rst --- releases/4.3.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index b742bf32c..9a47fe2c9 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -34,6 +34,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► A new :ref:`SQLoader <ingesting_from_databases>` will enable you to load data into SQreamDB from other databases. + ► Access control permissions in SQreamDB have been expanded, allowing roles to now grant and revoke access to other roles for the following: * VIEWS @@ -174,6 +176,3 @@ There are two methods of granting back access to services: .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - - - From acb4f07fa7d1f3ecb7697d515483642378879500 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 08:31:38 +0300 Subject: [PATCH 0843/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 45 +++++++++++++------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 2cda212d6..5c399ab8e 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -44,15 +44,16 @@ Syntax table_name ::= identifier fdw_name ::= - { csv_fdw | orc_fdw | parquet_fdw } + { csv_fdw | orc_fdw | parquet_fdw | json_fdw | avro_fdw } option_def ::= { - LOCATION = '{ path_spec }' - | DELIMITER = '{ field_delimiter }' -- for CSV only - | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only - | AWS_ID '{ AWS ID }' - | AWS_SECRET '{ AWS SECRET }' + LOCATION = '{ path_spec }', + | DELIMITER = '{ field_delimiter }' -- for CSV only, + | RECORD_DELIMITER = '{ record_delimiter }', -- for CSV only + | AWS_ID '{ AWS ID }', + | AWS_SECRET '{ AWS SECRET }', + | OFFSET -- for CSV and JSON only } path_spec ::= { local filepath | S3 URI | HDFS URI } @@ -85,23 +86,25 @@ Parameters * - Parameter - Description * - ``OR REPLACE`` - - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + - Create a new table, and overwrite any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name * - ``schema_name`` - - The name of the schema in which to create the table. + - The name of the schema in which to create the table * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. + - The name of the table to create, which must be unique inside the schema * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally * - ``WRAPPER ...`` - - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, or ``csv_fdw``. + - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, or ``csv_fdw`` * - ``LOCATION = ...`` - - Specifies a path or URI of the source files, such as ``/path/to/*.parquet``. + - Specifies a path or URI of the source files, such as ``/path/to/*.parquet`` * - ``DELIMITER = ...`` - - Specifies the field delimiter for CSV files. Defaults to ``,``. + - Specifies the field delimiter for CSV files. Defaults to ``,`` * - ``RECORD_DELIMITER = ...`` - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` * - ``AWS_ID``, ``AWS_SECRET`` - Credentials for authenticated S3 access + * - ``OFFSET`` + - Used to specify the number of rows to skip from the beginning of the result set Examples @@ -162,4 +165,20 @@ Materializes a foreign table into a regular table. CREATE TABLE real_table AS SELECT * FROM some_foreign_table; + +Using the ``OFFSET`` Parameter +-------------------------------- + +The ``OFFSET`` parameter may be used with Parquet and CSV textual formats. + +.. code-block:: + + CREATE FOREIGN TABLE users7 + (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) + WRAPPER parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet', + OFFSET = 2 + ); From d67186acc7d6cce6d27427f980e0f886f3bd6002 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:04:36 +0300 Subject: [PATCH 0844/1892] Update show_node_info.rst --- .../sql/sql_statements/utility_commands/show_node_info.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst index 9c1e1ec11..47e43be5b 100644 --- a/reference/sql/sql_statements/utility_commands/show_node_info.rst +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -4,7 +4,7 @@ SHOW_NODE_INFO ******************** -``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. +``SHOW_NODE_INFO`` returns a snapshot of the current query plan, similarly to the ``EXPLAIN ANALYZE`` function used in other databases. The snapshot provides information about execution which can be used for monitoring and troubleshooting slow running statements by helping identify long-running execution nodes (components that process data), etc. From f6b0da4f4170844ed567a3ceca3e1976b405f742 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 10:33:32 +0300 Subject: [PATCH 0845/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index ddf97464c..4d65abbbc 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -11,9 +11,10 @@ This guide focuses specifically on identifying bottlenecks and possible optimiza Performance tuning options for each query are different. You should adapt the recommendations and tips for your own workloads. See also our :ref:`sql_best_practices` guide for more information about data loading considerations and other best practices. -.. contents:: In this section: +.. contents:: :local: - :depths: 1 + :depth: 1 + Setting Up the System for Monitoring ==================================== @@ -147,8 +148,7 @@ Consider the example show_node_info presented above. The source node with ID #11 (``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: .. figure:: /_static/images/show_node_info_graph.png - - :height: 70em + :scale: 60 % :align: center This graph explains how the query execution details are arranged in a logical order, from the bottom up. From 7ee6bb2218193ede56e39bde91667003bed61d1c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:25:16 +0300 Subject: [PATCH 0846/1892] Update compression.rst --- feature_guides/compression.rst | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 818e0366d..a56826ffa 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -53,7 +53,7 @@ The following table shows the supported compression methods: - Automatic scheme selection - NA * - ``DICT`` - - All + - All types - Dictionary compression with RLE. For each chunk, SQreamDB creates a dictionary of distinct values and stores only their indexes. @@ -92,33 +92,33 @@ The following table shows the supported compression methods: - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - CPU * - ``SPACES`` - - + - All types - Reduces the storage space required for data by identifying repeating sequences of values and replacing them with a compact representation. This method is particularly effective when there are repetitive patterns in the data. - - + - CPU * - ``DELTA_RLE`` - Integer types - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. - CPU * - ``SPADES`` - - + - All types - An extension of ``SPACES`` compression, optimizing the compression scheme further to handle specific data patterns and types efficiently. - - + - CPU * - ``SPAPPY`` - - + - All types - Specialized variation of the ``Snappy`` compression algorithm. ``Snappy`` is a fast and efficient compression method that works well with various types of data, offering good compression ratios and decompression speeds. - - + - CPU * - ``SPAZLY`` - - - - - - + - All types + - An encryption method involving the transformation of plaintext characters into a jumbled or disorderly arrangement + - CPU * - ``CRLE`` - - - - + - All types + - An encryption process involving the compression and run-length encoding of data to secure it - CPU * - ``LZ4_ZIGZAG`` - - - - - - + - All types + - An encryption approach combining LZ4 compression with a zigzag pattern + - CPU .. note:: Automatic compression does **not** select the ``zlib`` compression method. From c8076eb0361fa5c5971c3f38aa9ba158434ee920 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:03:04 +0300 Subject: [PATCH 0847/1892] Update tableau.rst --- .../client_platforms/tableau.rst | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 4f3d60289..08119a29d 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -59,7 +59,7 @@ Installing the Tableau Connector * - Tableau Prep Conductor on Tableau Server - ``/data/tabsvc/flowprocessor/Connectors`` * - Tableau Server - - ``C:\ProgramData\Tableau\Tableau Server\data\tabsvc\vizqlserver\Connectors`` + - ``C:\<directory_name>\Tableau\Tableau Server\<directory_name>\Connectors`` 3. Restart Tableau Desktop or Tableau server. @@ -83,12 +83,8 @@ Connecting to SQream :: -#. In the connection dialog box, fill in the fields and click **Sign In**. +#. In the connection dialog box, fill in the following fields: - The connection is established, and the data source page is displayed. - -Information about step 4 fields: - .. list-table:: :widths: 15 38 38 :header-rows: 1 @@ -97,26 +93,32 @@ Information about step 4 fields: - Description - Example * - Server - - Defines the server of the SQream worker. - - ``127.0.0.1`` or ``sqream.mynetwork.co`` + - Defines the SQreamDB worker machine IP. + + Avoid using the loopback address (127.0.0.1) or "localhost" as a server address since it typically refers to the local machine where Tableau is installed and may create issues and limitations + - ``192.162.4.182`` or ``sqream.mynetwork.com`` * - Port - - Defines the TCP port of the SQream worker. - - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL. + - Defines the TCP port of the SQream worker + - ``3108`` when using a load balancer, or ``5100`` when connecting directly to a worker with SSL * - Database - - Defines the database to establish a connection with. + - Defines the database to establish a connection with - ``master`` * - Cluster - - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection. + - Enables (``true``) or disables (``false``) the load balancer. After enabling or disabling the load balance, verify the connection - * - Username - - Specifies the username of a role to use when connecting. + - Specifies the username of a role to use when connecting - ``rhendricks`` * - Password - - Specifies the password of the selected role. + - Specifies the password of the selected role - ``Tr0ub4dor&3`` * - Require SSL - - Sets SSL as a requirement for establishing this connection. + - Sets SSL as a requirement for establishing this connection - +5. Click **Sign In**. + The connection is established, and the data source page is displayed. + + From 518c8cfdd96d4d161cf9ad02255a1235941dbcfd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 11:13:48 +0300 Subject: [PATCH 0848/1892] User-Defined Functions page edit --- reference/sql/sql_functions/user_defined_functions/index.rst | 5 +++-- .../user_defined_functions/simple_scalar_sql_udf.rst | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/user_defined_functions/index.rst b/reference/sql/sql_functions/user_defined_functions/index.rst index 028e35a07..b3c52022b 100644 --- a/reference/sql/sql_functions/user_defined_functions/index.rst +++ b/reference/sql/sql_functions/user_defined_functions/index.rst @@ -8,5 +8,6 @@ The following user-defined functions are functions that can be defined and confi The **User-Defined Functions** page describes the following: -* `Python user-defined functions <https://docs.sqream.com/en/v2022.1/feature_guides/python_functions.html>`_ -* `Scalar SQL user-defined functions <https://docs.sqream.com/en/v2022.1/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.html>`_ \ No newline at end of file +* :ref:`Python user-defined functions<python_functions>` +* :ref:`Scalar SQL user-defined functions<scalar_sql_udf>` +* :ref:`Simple Scalar SQL UDF's<simple_scalar_sql_udf>` \ No newline at end of file diff --git a/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst b/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst index 1a78e2e8c..f47983c4a 100644 --- a/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst +++ b/reference/sql/sql_functions/user_defined_functions/simple_scalar_sql_udf.rst @@ -6,6 +6,7 @@ Simple Scalar SQL UDF's Syntax ~~~~~~~~~~~~ + The following example shows the correct syntax for simple scalar SQL UDF's: @@ -27,6 +28,7 @@ The following example shows the correct syntax for simple scalar SQL UDF's: Usage Notes ~~~~~~~~~~~~~~ + The following usage notes apply when using simple scalar SQL UDF's: * During this stage, the SQL embedded in the function body must be of the type ``SELECT expr;``. Creating a UDF with invalid SQL, or with valid SQL of any other type, results in an error. @@ -45,6 +47,7 @@ Because SQL UDF's are one type of supported UDFs, the following Python UDF chara Restrictions ~~~~~~~~~~~~~~~~~~~~~ + The following restrictions apply to simple scalar SQL UDF's: * Simple scalar SQL UDF's cannot currently reference other UDF's. From 99978c052213435670999af2a27ae08984612ee8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 14:34:14 +0300 Subject: [PATCH 0849/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index fc9c1a115..cfa7956bc 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader-0.0.6`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader-0.0.6.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc-oracle-incr.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc-oracle-incr.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``/n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 478d69fc408395f68fdbca6cd38d5a3564967ebd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 15:02:50 +0300 Subject: [PATCH 0850/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index cfa7956bc..2670202dd 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``/n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``incremental``. Please note that ``cdc``, and ``incremental`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: auto :header-rows: 1 * - Loading Type - Description * - Full Table - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``NTEXT`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``decimal``, ``numeric`` - ``numeric`` * - ``float``, ``double`` - ``double`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader-0.0.6.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader-0.0.6.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``/n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 2f4c0e7df183ef744afaa2eaa7077a1159bd9188 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:34:24 +0300 Subject: [PATCH 0851/1892] \n + architecture --- architecture/internals_architecture.rst | 25 +++++++++------------ data_ingestion/ingesting_from_databases.rst | 2 +- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index 0d319678f..af5ec0acf 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -17,32 +17,27 @@ Key Functions and Components Statement Compiler ------------------ -The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement plans. +The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement execution plans. -Building Blocks ---------------- +Building Blocks (GPU Workers) +----------------------------- -In SQreamDB, the main workload is carried out by specialized C++/CUDA building blocks intentionally kept devoid of inherent intelligence; they require precise instructions for operation. The task of effectively assembling these components relies largely on the capabilities of the statement compiler. +In SQreamDB, the main workload is carried out by specialized C++/CUDA building blocks, also known as Workers, which intentionally lack inherent intelligence and require precise instructions for operation. Effectively assembling these components relies largely on the capabilities of the statement compiler. Storage Layer ------------- -The storage is split into the metadata layer and an append-only / garbage-collected bulk data layer. +The storage is split into the metadata layer and an append-only data layer. Metadata Layer ^^^^^^^^^^^^^^ -Utilizing RocksDB, the metadata layer incorporates features such as snapshots and atomic writes within the transaction system, while working in conjunction with the append-only bulk data layer to maintain overall data consistency. +Utilizing RocksDB key/value data store, the metadata layer incorporates features such as snapshots and atomic writes within the transaction system, while working in conjunction with the append-only bulk data layer to maintain overall data consistency. -Bulk Data Layer -^^^^^^^^^^^^^^^ +Bulk Data Layer Optimization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The bulk data layer consists of IO-optimized extents, containing CPU and GPU-efficient chunks, both of which incorporate compression. During small insert operations, less optimized chunks and extents might result, yet the system is intentionally designed to maintain operational efficiency in such scenarios. It achieves this by facilitating background transactional reorganization without disrupting DML operations. By initially writing small chunks via small inserts and subsequently reorganizing them, the system accommodates swift medium-sized insert transactions while enabling rapid querying capabilities. - -Columnar Storage -^^^^^^^^^^^^^^^^ - -Similar to numerous other analytical database management systems, SQreamDB employs a column store structure for its tables, leveraging the advantages it provides. This approach enhances I/O efficiency and overall performance when dealing with analytic workloads. Furthermore, columns exhibit superior compression properties and are particularly suited for handling bulk data operations. +SQreamDB harnesses the power of its columnar storage architecture within the bulk data layer for performance optimization. This layer employs IO-optimized extents containing compression-enabled CPU and GPU-efficient chunks. Even during small insert operations, SQreamDB maintains efficiency by generating less optimized chunks and extents as needed. This is achieved through background transactional reorganization that doesn't disrupt Data Manipulation Language (DML) operations. The system initially writes small chunks via small inserts and subsequently reorganizes them, facilitating swift medium-sized insert transactions and rapid queries. This optimization strategy, coupled with SQreamDB's columnar storage, ensures peak performance across diverse data processing tasks. Concurrency and Admission Control --------------------------------- @@ -54,7 +49,7 @@ Learn more about :ref:`concurrency_and_scaling_in_sqream`. Transactions ------------ -SQreamDB has serializable transactions, with these features: +SQreamDB has serializable (auto commit) transactions, with these features: * Serializable, with any kind of statement diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 2670202dd..19b45e235 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``/n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From a9a5d83a807c85ac59853a45d8c1cff668055658 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Sep 2023 16:58:10 +0300 Subject: [PATCH 0852/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 45 +++++++++++-------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 91c32cd01..403836e27 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -107,7 +107,7 @@ Elements - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in **COPY FROM** and foreign tables. * - ``fdw_name`` - - - ``csv_fdw``, ``orc_fdw``, or ``parquet_fdw`` + - ``csv_fdw``, ``orc_fdw``, ``parquet_fdw``, ``json_fdw``, or ``avro_fdw`` - The name of the Foreign Data Wrapper to use * - ``LOCATION`` - None @@ -259,20 +259,16 @@ Supported Field Delimiters Field delimiters can be one or more characters. Customizing Quotations Using Alternative Characters ----------------------------- +----------------------------------------------------- -Customizing Quotations Using Alternative Characters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The following is the correct syntax for customizing quotations using alternative characters: +Syntax: .. code-block:: postgres - copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote='@'); - copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote='@'); + COPY t FROM wrapper csv_fdw OPTIONS (location = '/tmp/source_file.csv', quote='@'); + COPY t TO wrapper csv_fdw OPTIONS (location = '/tmp/destination_file.csv', quote='@'); -Customizing Quotations Using Alternative Characters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example: The following is an example of line taken from a CSV when customizing quotations using a character: @@ -284,15 +280,14 @@ The following is an example of line taken from a CSV when customizing quotations Customizing Quotations Using ASCII Character Codes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The following is the correct syntax for customizing quotations using ASCII character codes: +Syntax: .. code-block:: postgres copy t from wrapper csv_fdw options (location = '/tmp/source_file.csv', quote=E'\064'); copy t to wrapper csv_fdw options (location = '/tmp/destination_file.csv', quote=E'\064'); -Customizing Quotations Using ASCII Character Codes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Example: The following is an example of line taken from a CSV when customizing quotations using an ASCII character code: @@ -300,12 +295,10 @@ The following is an example of line taken from a CSV when customizing quotations Pepsi-"Cola",@Coca-"Cola"@,Sprite,Fanta - - Multi-Character Delimiters -------------------------- -SQream DB supports multi-character field delimiters, sometimes found in non-standard files. +SQreamDB supports multi-character field delimiters, sometimes found in non-standard files. A multi-character delimiter can be specified. For example, ``DELIMITER '%%'``, ``DELIMITER '{~}'``, etc. @@ -378,6 +371,7 @@ Whenever the data can’t be parsed because it is improperly formatted or doesn When ``ERROR_LOG`` is not used, the ``COPY`` command will stop and roll back the transaction upon the first error. .. image:: /_static/images/copy_from_rejected_rows.png + :width: 50% CSV Support @@ -472,7 +466,20 @@ Loading a Parquet File .. code-block:: postgres COPY table_name FROM WRAPPER parquet_fdw OPTIONS (location = '/tmp/file.parquet'); + +Loading a JSON File +---------------------- + +.. code-block:: postgres + + COPY t FROM WRAPPER json_fdw OPTIONS (location = 'somefile.json'); + +Loading an AVRO File +---------------------- + +.. code-block:: postgres + COPY t FROM WRAPPER fdw_name OPTIONS ([ copy_from_option [, ...] ]); Loading a Text File with Non-Printable Delimiters ------------------------------------------------- @@ -577,12 +584,12 @@ When the source of the files does not match the table structure, tell the ``COPY Loading Non-Standard Dates ---------------------------------- -If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQream DB. +If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQreamDB. -These are called date parsers. You can find the supported dates in the :ref:`'Supported date parsers' table<copy_date_parsers>` above +These are called date parsers. You can find the supported dates in the :ref:`'Supported date parsers' table<copy_date_parsers>` above. In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. ``date_col3`` is mentioned explicitly, but can be left out. Any column that is not specified is assumed to be ``ISO8601``. .. code-block:: postgres - COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/*.csv', datetime_format = 'DMY'); + COPY my_table (date_col1, date_col2, date_col3) FROM '/tmp/my_data.csv' WITH CSV HEADER datetime_format 'DMY'; From 7d19cb136bf70397cd33878102a211a99ec3fb2d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 08:41:04 +0300 Subject: [PATCH 0853/1892] Update sqream_db_internals.png --- _static/images/sqream_db_internals.png | Bin 327579 -> 287611 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/_static/images/sqream_db_internals.png b/_static/images/sqream_db_internals.png index 646b96e4c1b5db4d7a37df8fdfe5097ff47738d9..d41ea5478f98e2edff5423ea01cce806a582fba1 100644 GIT binary patch literal 287611 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 JA#EJ;zW^h6Yj6Mn literal 327579 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%0AG}rs;1K1 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%0DA~ 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%0D8m6}5{%?= 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 F{|D>(B?bTh From ddfb553f5bda54d7cb6c31b2e71a58e6fae1a8dc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:40:34 +0300 Subject: [PATCH 0854/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 19b45e235..c38177e2a 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-0.0.6.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-0.0.6.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 83ff562051d91338f674b04401ce129544679de3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 10:47:42 +0300 Subject: [PATCH 0855/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index c38177e2a..826ec0adb 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: The ``type`` Parameter :widths: 10 20 :header-rows: 1 * - Loading Type - Description * - Full Table ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 082cb642eb3b9e183be88249fffca27fdf3651dc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:49:53 +0300 Subject: [PATCH 0856/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 826ec0adb..48eb7084f 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar.gz 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 9cf593574fd00dd5bd13179fc91205bd4ce15eea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 12:56:39 +0300 Subject: [PATCH 0857/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 48eb7084f..ecf9ebf63 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc-oracle.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc-oracle.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From e4d0635d9cc87ba802c397a68a7fd57acaafb550 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:30:17 +0300 Subject: [PATCH 0858/1892] Retrieving Execution Plan Output Using Studio --- .../studio_icon_execution_details_view.png | Bin 0 -> 459 bytes troubleshooting/index.rst | 2 +- ...ing_execution_plan_output_using_studio.rst | 25 ++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 _static/images/studio_icon_execution_details_view.png create mode 100644 troubleshooting/retrieving_execution_plan_output_using_studio.rst diff --git a/_static/images/studio_icon_execution_details_view.png b/_static/images/studio_icon_execution_details_view.png new file mode 100644 index 0000000000000000000000000000000000000000..b6665946d22e3ff6b21e584f161a9c66a0c62680 GIT binary patch literal 459 zcmV;+0W|)JP)<h;3K|Lk000e1NJLTq001fg001Kh1^@s6;>?(n00001b5ch_0Itp) z=>Px$g-Jv~R9HvtmCb5{P!NSj&>95Y1&jfkuChwgZMw5hlfFZ<O5dS*nu@C?&=9f? z4K$$8pkORn=)zkRl(bF#p`#>l-8y`8JacAb;7lIoOmqSjiajanD0LLu0c;-4D0MW; zfv3rYn5LPQwA*dC9}Y{!=D&<W%^pT0a;Isj&}UtT$MKl)gMfT`UgnfVQ3RgnnZFoC zBT`DJrfHz-IwV3Div{`EZZmtyvJ5x<ek$}QqY|MB^w3dnw}bc125j4gOI3wtv-z!e zt&Zm9D-1(o7zXf-2HXw?N2ip>$aA*P=<^`a`_*bi-q!0#C`gio#!Y&o0e#<(U6orc zxbF4PxadM7;BvW)mn*suEX$&bMTNPpOQy3Kbh}-+>U2=qsIbV@m+6!QK@ew^<G7T6 zGRu@?$+m6sI-kP@$AKUSpePEcs#?#%FS7NAHICyD%d%j<-~SR?>A^26^jLi@zfcUJ zCznx-k2=Oc-+C&vDhIH+boA6wYzMG;G^5y#egPT;$RrWkx(WaQ002ovPDHLkV1ifu B(;WZ+ literal 0 HcmV?d00001 diff --git a/troubleshooting/index.rst b/troubleshooting/index.rst index 985008e09..21586efaa 100644 --- a/troubleshooting/index.rst +++ b/troubleshooting/index.rst @@ -12,9 +12,9 @@ The **Troubleshooting** page describes solutions to the following issues: remedying_slow_queries resolving_common_issues - examining_logs identifying_configuration_issues lock_related_issues log_related_issues core_dumping_related_issues + retrieving_execution_plan_output_using_studio information_for_support \ No newline at end of file diff --git a/troubleshooting/retrieving_execution_plan_output_using_studio.rst b/troubleshooting/retrieving_execution_plan_output_using_studio.rst new file mode 100644 index 000000000..41f7a9735 --- /dev/null +++ b/troubleshooting/retrieving_execution_plan_output_using_studio.rst @@ -0,0 +1,25 @@ +.. _retrieving_execution_plan_output_using_studio: + +********************************************** +Retrieving Execution Plan Output Using Studio +********************************************** + +You may use SQreamDB Studio to create a query plan snapshot to be used for monitoring and troubleshooting slow running statements and for identifying long-running execution nodes (components that process data), etc. + +Retrieving Execution Plan Output +================================ + +1. In the **Result Panel**, select **Execution Details View** |icon-execution-details-view|. + + The **Execution Tree** window opens. + +.. |icon-execution-details-view| image:: /_static/images/studio_icon_execution_details_view.png + +2. From the upper-right corner, select the |icon-download| to download a CSV execution plan table. + +.. |icon-download| image:: /_static/images/studio_icon_download.png + :align: middle + +3. Save the execution plan on your local machine. + +The information may be analyzed by :ref:`monitoring_query_performance` or with help from `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. \ No newline at end of file From d0c0546d5c49858f40a3d963680853f06e5320ca Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:54:08 +0300 Subject: [PATCH 0859/1892] Denodo --- .../client_platforms/denodo.rst | 2 ++ .../client_platforms/index.rst | 25 ++++++++----------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst index 701ab3d3d..76da3264f 100644 --- a/connecting_to_sqream/client_platforms/denodo.rst +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -74,6 +74,8 @@ Setting Up a Connection to SQreamDB 5. To verify your newly created connection, select the **Test connection** button. +.. note:: When adding the JDBC driver in Denodo, it's important to note that a restart of Denodo may be required. Additionally, in some cases, the SQream driver may not immediately appear in the list of available JDBC drivers. If you encounter this issue, a simple solution is to reboot the machine and attempt the process again. + Limitation ========== diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 925d01ff1..1c1c164b8 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -24,6 +24,8 @@ Data Integration Tools Business Intelligence (BI) Tools -------------------------------- +:ref:`Denodo<denodo>` + :ref:`MicroStrategy<micro_strategy>` :ref:`Power BI Desktop<power_bi>` @@ -44,24 +46,12 @@ Data Analysis and Programming Languages :ref:`R<r>` - - - - - - - - - - - - .. toctree:: :maxdepth: 4 :titlesonly: :hidden: - trino + denodo informatica microstrategy pentaho @@ -70,10 +60,15 @@ Data Analysis and Programming Languages r sap_businessobjects sas_viya - sql_workbench + sql_workbench tableau talend - tibco_spotfire + tibco_spotfire + trino + + + + From 3f2d8b47c524038803cb454760400a22a4b4745d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:00:09 +0300 Subject: [PATCH 0860/1892] Update 4.4.rst --- releases/4.4.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 6f81fc55a..6f35d05c5 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- - +:ref:`denodo` may now be used for data visualization and real-time visualization of various sources. Known Issues ------------ @@ -106,8 +106,8 @@ The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_ With the improvement of the core functionalities of the platform and to align with the constantly evolving ecosystem requirements, the ``VARCHAR`` data type is deprecated and may not be used. The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. -Upgrading to v4.4 ------------------ +Upgrading to Version 4.4 +------------------------- 1. Generate a back-up of the metadata by running the following command: .. code-block:: console From bf5e679061cb070a0e76db820277b0cae776ad8b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:13:50 +0300 Subject: [PATCH 0861/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index ecf9ebf63..3ace7f4b7 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` (8bytes), ``INTEGER`` (4 bytes), ``SMALLINT`` (2 bytes) - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT`` (8 bytes), ``DOUBLE`` (4 bytes) - ``DOUBLE`` * - ``REAL`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 29dbf2e4c99055b8e7251908eb833741246055f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 15:39:22 +0300 Subject: [PATCH 0862/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 3ace7f4b7..d6324b517 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 3d0c2c437c6cb66555fa6dda94d97afdda6dbd07 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 16:08:13 +0300 Subject: [PATCH 0863/1892] retrieve the query execution plan output --- operational_guides/monitoring_query_performance.rst | 6 ++++-- troubleshooting/information_for_support.rst | 1 + troubleshooting/resolving_common_issues.rst | 2 +- .../retrieving_execution_plan_output_using_studio.rst | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 4d65abbbc..547d37d0a 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -117,8 +117,8 @@ Using the ``SHOW_NODE_INFO`` Command The :ref:`show_node_info` command returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. The :ref:`show_node_info` result, just like the periodically-logged execution plans described above, are an at-the-moment view of the compiler's execution plan and runtime statistics for the specified statement. -To inspect a currently running statement, execute the ``show_node_info`` utility function in a SQL client like - :ref:`sqream sql<sqream_sql_cli_reference>`, the :ref:`SQream Studio Editor<studio_editor>`, or any other :ref:`third party SQL terminal<third_party_tools>`. +To inspect a currently running statement, execute the ``show_node_info`` utility function in a SQL client like :ref:`sqream sql<sqream_sql_cli_reference>`, the :ref:`SQream Studio Editor<studio_editor>`, or any other :ref:`third party SQL terminal<third_party_tools>`. + In this example, we inspect a statement with statement ID of 176. The command looks like this: .. code-block:: sql @@ -138,6 +138,8 @@ In this example, we inspect a statement with statement ID of 176. The command lo 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 +Alternatively, you may also :ref:`retrieve the query execution plan output<retrieving_execution_plan_output_using_studio>` using SQreamDB Studio, and contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. + Understanding the Query Execution Plan Output ============================================= diff --git a/troubleshooting/information_for_support.rst b/troubleshooting/information_for_support.rst index 159247c95..8450cc664 100644 --- a/troubleshooting/information_for_support.rst +++ b/troubleshooting/information_for_support.rst @@ -23,6 +23,7 @@ When possible, please attach as many of the following: * DDL and queries that reproduce the issue * :ref:`Log files<logging>` * Screen captures if relevant +* :ref:`Execution plan output<retrieving_execution_plan_output_using_studio>` How SQream Debugs Issues ======================== diff --git a/troubleshooting/resolving_common_issues.rst b/troubleshooting/resolving_common_issues.rst index fd90472d3..73a9c07e8 100644 --- a/troubleshooting/resolving_common_issues.rst +++ b/troubleshooting/resolving_common_issues.rst @@ -40,7 +40,7 @@ Troubleshooting Connectivity Issues Troubleshooting Query Performance ------------------------------------ -#. Use :ref:`show_node_info` to examine which building blocks consume time in a statement. If the query has finished, but the results are not yet materialized in the client, it could point to a problem in the application's data buffering or a network throughput issue.. +#. Use :ref:`show_node_info` to examine which building blocks consume time in a statement. If the query has finished, but the results are not yet materialized in the client, it could point to a problem in the application's data buffering or a network throughput issue. Alternatively, you may also :ref:`retrieve the query execution plan output<retrieving_execution_plan_output_using_studio>` using SQreamDB Studio. #. If a problem occurs through a 3\ :sup:`rd` party client, try reproducing it directly with :ref:`the built in SQL client<sqream_sql_cli_reference>`. If the performance is better in the local client, it could point to a problem in the application or network connection. diff --git a/troubleshooting/retrieving_execution_plan_output_using_studio.rst b/troubleshooting/retrieving_execution_plan_output_using_studio.rst index 41f7a9735..80991669c 100644 --- a/troubleshooting/retrieving_execution_plan_output_using_studio.rst +++ b/troubleshooting/retrieving_execution_plan_output_using_studio.rst @@ -9,6 +9,8 @@ You may use SQreamDB Studio to create a query plan snapshot to be used for monit Retrieving Execution Plan Output ================================ +You can retrieve the execution plan output either after the query execution has completed, in the case of a hanging query, or if you suspect no progress is being made. + 1. In the **Result Panel**, select **Execution Details View** |icon-execution-details-view|. The **Execution Tree** window opens. From 1b80975c12b5d8297336a1fc6b6d5926994410a0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Sep 2023 16:47:11 +0300 Subject: [PATCH 0864/1892] CentOS 7 EOL --- releases/4.3.rst | 8 +++++++- releases/4.4.rst | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 9a47fe2c9..6993b9d40 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -16,7 +16,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS / REHL - 7.6 - 7.9 | +| Supported OS | * CentOS / RHEL - 8.x | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ | Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | @@ -120,6 +120,12 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa Deprecated Features ------------------- +► **CentOS Linux 7.x** + +As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +**CentOS Linux 8.x** is now officially supported. + ► ``INT96`` Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. diff --git a/releases/4.4.rst b/releases/4.4.rst index 6f35d05c5..33e34f501 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -16,7 +16,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS / REHL - 7.6 - 7.9 | +| Supported OS | * CentOS / REHL - 8.x | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | @@ -92,6 +92,12 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa Deprecated Features ------------------- +► **CentOS Linux 7.x** + +As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +**CentOS Linux 8.x** is now officially supported. + ► ``INT96`` Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. From 2676b553c4ea061b642760770a43102a642e43aa Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:03:39 +0300 Subject: [PATCH 0865/1892] Update 4.4.rst --- releases/4.4.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 33e34f501..ae02154e0 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -16,7 +16,8 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS / REHL - 8.x | +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | | | * IBM RedHat 7.6 | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | @@ -94,7 +95,7 @@ Deprecated Features ► **CentOS Linux 7.x** -As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. Due to the fact that CentOS will no longer support production deployments, we recommend users to explore migration to the Red Hat Enterprise Linux (RHEL) commercial Linux distribution developed by Red Hat. **CentOS Linux 8.x** is now officially supported. From 03bd720c5d3f31aa66487d5ae621fb27771754df Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Sep 2023 12:08:06 +0300 Subject: [PATCH 0866/1892] Update 4.4.rst --- releases/4.4.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index ae02154e0..136533b49 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -18,7 +18,7 @@ Compatibility Matrix +=========================+========================================================================+ | Supported OS | * CentOS - 7.x | | | * RHEL - 7.x / 8.x | -| | * IBM RedHat 7.6 | +| | * IBM Red Hat 7.6 | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ From a7938fb7c8429127a30df2ae4f74c0fd5f5d67fd Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Sep 2023 14:28:06 +0300 Subject: [PATCH 0867/1892] Update access_control_managing_roles.rst --- operational_guides/access_control_managing_roles.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index 3f032bcd5..f601b63a9 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -3,6 +3,7 @@ ************** Managing Roles ************** + Roles are used for both users and groups, and are global across all databases in the SQream cluster. For a ``ROLE`` to be used as a user, it requires a password and log-in and connect permissionss to the relevant databases. The Managing Roles section describes the following role-related operations: @@ -13,7 +14,8 @@ The Managing Roles section describes the following role-related operations: Creating New Roles (Users) ------------------------------ -A user role logging in to the database requires ``LOGIN`` permissions and as a password. + +A user role logging in to the database requires ``LOGIN`` permissions and a password. The following is the syntax for creating a new role: @@ -37,6 +39,7 @@ A database role may have a number of permissions that define what tasks it can p Dropping a User ------------------------------ + The following is the syntax for dropping a user: .. code-block:: postgres @@ -51,6 +54,7 @@ The following is an example of dropping a user: Altering a User Name ------------------------------ + The following is the syntax for altering a user name: .. code-block:: postgres @@ -65,6 +69,7 @@ The following is an example of altering a user name: Changing a User Password ------------------------------ + You can change a user role's password by granting the user a new password. The following is an example of changing a user password: @@ -78,7 +83,7 @@ The following is an example of changing a user password: Altering Public Role Permissions ------------------------------ -There is a public role which always exists. Each role is granted to the ``PUBLIC`` role (i.e. is a member of the public group), and this cannot be revoked. You can alter the permissions granted to the public role. +The database has a predefined ``PUBLIC`` role that cannot be deleted. Each user role is automatically granted membership in the ``PUBLIC`` role public group, and this membership cannot be revoked. However, you have the capability to adjust the permissions associated with this 'public' role. The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can :ref:`insert`, :ref:`delete`, :ref:`select`, :ref:`UPDATE` and ``CREATE`` (:ref:`databases<create_database>`, :ref:`schemas<create_schema>`, :ref:`roles<create_role>`, :ref:`functions<create_function>`, :ref:`views<create_view>`, and :ref:`tables<create_table>`) from objects in the ``PUBLIC`` schema. @@ -121,4 +126,4 @@ Removing users and permissions can be done with the ``REVOKE`` command: .. code-block:: postgres -- remove my_other_user from this group - REVOKE my_group FROM my_other_user; \ No newline at end of file + REVOKE my_group FROM my_other_user; From 1d0036d83f7db4374ecf14d2c0fe5879513a37fa Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Sep 2023 15:33:33 +0300 Subject: [PATCH 0868/1892] Update access_control_managing_roles.rst --- operational_guides/access_control_managing_roles.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index f601b63a9..9b81b855d 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -83,9 +83,9 @@ The following is an example of changing a user password: Altering Public Role Permissions ------------------------------ -The database has a predefined ``PUBLIC`` role that cannot be deleted. Each user role is automatically granted membership in the ``PUBLIC`` role public group, and this membership cannot be revoked. However, you have the capability to adjust the permissions associated with this 'public' role. +The database has a predefined ``PUBLIC`` role that cannot be deleted. Each user role is automatically granted membership in the ``PUBLIC`` role public group, and this membership cannot be revoked. However, you have the capability to adjust the permissions associated with this ``PUBLIC`` role. -The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, new users can :ref:`insert`, :ref:`delete`, :ref:`select`, :ref:`UPDATE` and ``CREATE`` (:ref:`databases<create_database>`, :ref:`schemas<create_schema>`, :ref:`roles<create_role>`, :ref:`functions<create_function>`, :ref:`views<create_view>`, and :ref:`tables<create_table>`) from objects in the ``PUBLIC`` schema. +The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schema by default, therefore, newly created user roles are granted ``CREATE`` (:ref:`databases<create_database>`, :ref:`schemas<create_schema>`, :ref:`roles<create_role>`, :ref:`functions<create_function>`, :ref:`views<create_view>`, and :ref:`tables<create_table>`) on the public schema. Other permissions, such as :ref:`insert`, :ref:`delete`, :ref:`select`, and :ref:`update` on objects in the public schema are not automatically granted. Altering Role Membership (Groups) From bbe025597a041731dbbd2047225aa7ce04bbd079 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Sep 2023 08:20:12 +0300 Subject: [PATCH 0869/1892] release notes --- releases/4.3.rst | 4 ++-- releases/4.4.rst | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 6993b9d40..c32924576 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -16,8 +16,8 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS / RHEL - 8.x | -| | * IBM RedHat 7.6 | +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x | +-------------------------+------------------------------------------------------------------------+ | Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ diff --git a/releases/4.4.rst b/releases/4.4.rst index 136533b49..2fcc8125e 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -18,7 +18,6 @@ Compatibility Matrix +=========================+========================================================================+ | Supported OS | * CentOS - 7.x | | | * RHEL - 7.x / 8.x | -| | * IBM Red Hat 7.6 | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ From 96cf2f5ac1f1c6d63f22524ec6ebf8d8d960c549 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Sep 2023 14:49:15 +0300 Subject: [PATCH 0870/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 403836e27..5d3fde038 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -531,7 +531,25 @@ Loading a File from a Public S3 Bucket .. code-block:: postgres - COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = 's3://sqream-demo-data/file.csv', delimiter = '\r\n', offset = 2); + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = 's3://sqream-demo-data/file.csv', delimiter = '\r\n', offset = 2); + +Loading a File From a Google Cloud Platform Bucket +---------------------------------------------------- + +To access a Google Cloud Platform (GCP) Bucket it is required that your environment be authorized. + +.. code-block:: + + COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = 'gs://<gcs path>/<gcs_bucket>/*'); + +Loading a File From Azure +---------------------------------- + +To access Azure it is required that your environment be authorized. + +.. code-block:: + + COPY table_name FROM WRAPPER csv_fdw OPTIONS(location = 'azure://sqreamrole.core.windows.net/sqream-demo-data/file.csv'); Loading Files from an Authenticated S3 Bucket --------------------------------------------------- From 20b323b8912606fe715d34203d5f6b293a3311f1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Sep 2023 16:58:07 +0300 Subject: [PATCH 0871/1892] Azure --- external_storage_platforms/azure.rst | 58 +++++++++ external_storage_platforms/gcp.rst | 184 +++++++++++++++++++++++++++ external_storage_platforms/index.rst | 4 +- 3 files changed, 245 insertions(+), 1 deletion(-) create mode 100644 external_storage_platforms/azure.rst create mode 100644 external_storage_platforms/gcp.rst diff --git a/external_storage_platforms/azure.rst b/external_storage_platforms/azure.rst new file mode 100644 index 000000000..2a974a044 --- /dev/null +++ b/external_storage_platforms/azure.rst @@ -0,0 +1,58 @@ +.. _azure: + +*********************** +Azure +*********************** + + +.. contents:: + :local: + :depth: 1 + + +Azure URI Format +================= + +Specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. + +The following is an example of the general Azure syntax: + +.. code-block:: console + + azure://accountname.core.windows.net/path + + +Connection String +=================== + +Connection String Example: + +.. code-block:: + + "DefaultEndpointsProtocol=https;AccountName=myaccount101;AccountKey=#######################################==;EndpointSuffix=core.windows.net" + +Use the following parameters within your SQreamDB legacy configuration file for authentication: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``DefaultEndpointsProtocol`` + - Specifies the protocol (e.g., https or http) used for accessing the storage service + * - ``AccountName`` + - Represents the unique name of your Azure Storage account + * - ``AccountKey`` + - Acts as the primary access key for securely authenticating and accessing resources within the storage account + * - ``EndpointSuffix`` + - Denotes the Azure Storage service endpoint suffix for a specific region or deployment, such as ``.core.windows.net`` + + + +Example +============ + +.. code-block:: + + COPY table_name FROM WRAPPER csv_fdw OPTIONS(location = 'azure://sqreamrole.core.windows.net/sqream-demo-data/file.csv'); \ No newline at end of file diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst new file mode 100644 index 000000000..9734820e6 --- /dev/null +++ b/external_storage_platforms/gcp.rst @@ -0,0 +1,184 @@ +.. _gcp: + +*********************** +Google Cloud Platform +*********************** + +SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. + +.. contents:: + :local: + :depth: 1 + +S3 Configuration +================ + +A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. + + +S3 URI Format +============= +With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. + +The following is an example of the general S3 syntax: + +.. code-block:: console + + s3://bucket_name/path + + +Authentication +============== +SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. + + +Connecting to S3 Using SQreamDB Legacy Configuration File +========================================================= + + +You may use the following parameters within your SQreamDB legacy configuration file: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + - Parameter Value + - Example + * - ``AwsEndpointOverride`` + - Overrides the AWS S3 HTTP endpoint when using Virtual Private Cloud (VPC) + - ``URL`` + Default: None + - .. code-block:: + + sqream_config_legacy.json: + { + ..., + "AwsEndpointOverride": "https://my.endpoint.local" + } + * - ``AwsObjectAccessStyle`` + - Enables configuration of S3 object access styles, which determine how you can access and interact with the objects stored in an S3 bucket + - ``virtual-host`` or ``path``. Default is ``virtual-host`` + - .. code-block:: + + sqream_config_legacy.json: + { + ..., + "AwsObjectAccessStyle": "path" + } + +Examples +======== + +Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. + +.. contents:: + :local: + :depth: 1 + +Planning for Data Staging +------------------------- +The examples in this section are based on the following table: + ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Name | Team | Number | Position | Age | Height | Weight | College | Salary | ++===============+================+========+==========+=====+========+========+===================+===========+ +| Avery Bradley | Boston Celtics | 0 | PG | 25 | 2-Jun | 180 | Texas | 7730337 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-Jun | 235 | Marquette | 6796117 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| John Holland | Boston Celtics | 30 | SG | 27 | 5-Jun | 205 | Boston University | | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| R.J. Hunter | Boston Celtics | 28 | SG | 22 | 5-Jun | 185 | Georgia State | 1148640 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 10-Jun | 231 | | 5000000 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Amir Johnson | Boston Celtics | 90 | PF | 29 | 9-Jun | 240 | | 12000000 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Jordan Mickey | Boston Celtics | 55 | PF | 21 | 8-Jun | 235 | LSU | 1170960 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Kelly Olynyk | Boston Celtics | 41 | C | 25 | Jul-00 | 238 | Gonzaga | 2165160 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ +| Terry Rozier | Boston Celtics | 12 | PG | 22 | 2-Jun | 190 | Louisville | 1824360 | ++---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ + + +The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. + +Creating a Foreign Table +------------------------ +Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: + +.. code-block:: postgres + + CREATE FOREIGN TABLE nba + ( + Name text(40), + Team text(40), + Number tinyint, + Position text(2), + Age tinyint, + Height text(4), + Weight real, + College text(40), + Salary float + ) + WRAPPER csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-demo-data/nba_players.csv', + RECORD_DELIMITER = '\r\n' -- DOS delimited file + ) + ; + +In the example above the file format is CSV, and it is stored as an S3 object. If the path is on HDFS, you must change the URI accordingly. Note that the record delimiter is a DOS newline (``\r\n``). + +For more information, see the following: + +* :ref:`create a foreign table<create_foreign_table>` +* :ref:`hdfs` + +Querying Foreign Tables +----------------------- +The following shows the data in the foreign table: + +.. code-block:: psql + + t=> SELECT * FROM nba LIMIT 10; + name | team | number | position | age | height | weight | college | salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + +Bulk Loading a File from a Public S3 Bucket +------------------------------------------- +The ``COPY FROM`` command can also be used to load data without staging it first. + +.. note:: The bucket must be publicly available and objects can be listed. + +The following is an example of bulk loading a file from a public S3 bucket: + +.. code-block:: postgres + + COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + +For more information on the ``COPY FROM`` command, see :ref:`copy_from`. + +Loading Files from an Authenticated S3 Bucket +--------------------------------------------------- +The following is an example of loading fles from an authenticated S3 bucket: + +.. code-block:: postgres + + COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' + AWS_ID '12345678' + AWS_SECRET 'super_secretive_secret'; \ No newline at end of file diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index 827fdf190..4cb178938 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -9,9 +9,11 @@ SQream supports the following external storage platforms: :maxdepth: 1 :titlesonly: + azure + hdfs s3 - hdfs + For more information, see the following: From 6b2258d4c91906e15658d4cd7318c21f16ab5077 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:15:28 +0300 Subject: [PATCH 0872/1892] Update gcp.rst --- external_storage_platforms/gcp.rst | 179 ++--------------------------- 1 file changed, 11 insertions(+), 168 deletions(-) diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst index 9734820e6..2a0edbd84 100644 --- a/external_storage_platforms/gcp.rst +++ b/external_storage_platforms/gcp.rst @@ -4,181 +4,24 @@ Google Cloud Platform *********************** -SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. +Google Cloud Platform (GCP) offers a robust and scalable cloud infrastructure for various computing and data storage needs. -.. contents:: - :local: - :depth: 1 - -S3 Configuration -================ - -A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. +Azure URI Format +================= -S3 URI Format -============= -With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. +Specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. -The following is an example of the general S3 syntax: +The following is an example of the general Azure syntax: .. code-block:: console - s3://bucket_name/path - - -Authentication -============== -SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. - - -Connecting to S3 Using SQreamDB Legacy Configuration File -========================================================= - - -You may use the following parameters within your SQreamDB legacy configuration file: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - - Parameter Value - - Example - * - ``AwsEndpointOverride`` - - Overrides the AWS S3 HTTP endpoint when using Virtual Private Cloud (VPC) - - ``URL`` - Default: None - - .. code-block:: - - sqream_config_legacy.json: - { - ..., - "AwsEndpointOverride": "https://my.endpoint.local" - } - * - ``AwsObjectAccessStyle`` - - Enables configuration of S3 object access styles, which determine how you can access and interact with the objects stored in an S3 bucket - - ``virtual-host`` or ``path``. Default is ``virtual-host`` - - .. code-block:: - - sqream_config_legacy.json: - { - ..., - "AwsObjectAccessStyle": "path" - } - -Examples -======== - -Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. - -.. contents:: - :local: - :depth: 1 - -Planning for Data Staging -------------------------- -The examples in this section are based on the following table: - -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Name | Team | Number | Position | Age | Height | Weight | College | Salary | -+===============+================+========+==========+=====+========+========+===================+===========+ -| Avery Bradley | Boston Celtics | 0 | PG | 25 | 2-Jun | 180 | Texas | 7730337 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-Jun | 235 | Marquette | 6796117 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| John Holland | Boston Celtics | 30 | SG | 27 | 5-Jun | 205 | Boston University | | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| R.J. Hunter | Boston Celtics | 28 | SG | 22 | 5-Jun | 185 | Georgia State | 1148640 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 10-Jun | 231 | | 5000000 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Amir Johnson | Boston Celtics | 90 | PF | 29 | 9-Jun | 240 | | 12000000 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jordan Mickey | Boston Celtics | 55 | PF | 21 | 8-Jun | 235 | LSU | 1170960 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Kelly Olynyk | Boston Celtics | 41 | C | 25 | Jul-00 | 238 | Gonzaga | 2165160 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Terry Rozier | Boston Celtics | 12 | PG | 22 | 2-Jun | 190 | Louisville | 1824360 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ - - -The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. - -Creating a Foreign Table ------------------------- -Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: - -.. code-block:: postgres - - CREATE FOREIGN TABLE nba - ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float - ) - WRAPPER csv_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n' -- DOS delimited file - ) - ; - -In the example above the file format is CSV, and it is stored as an S3 object. If the path is on HDFS, you must change the URI accordingly. Note that the record delimiter is a DOS newline (``\r\n``). - -For more information, see the following: - -* :ref:`create a foreign table<create_foreign_table>` -* :ref:`hdfs` - -Querying Foreign Tables ------------------------ -The following shows the data in the foreign table: - -.. code-block:: psql - - t=> SELECT * FROM nba LIMIT 10; - name | team | number | position | age | height | weight | college | salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 - -Bulk Loading a File from a Public S3 Bucket -------------------------------------------- -The ``COPY FROM`` command can also be used to load data without staging it first. - -.. note:: The bucket must be publicly available and objects can be listed. - -The following is an example of bulk loading a file from a public S3 bucket: - -.. code-block:: postgres - - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + gs://<gcs path>/<gcs_bucket>/ -For more information on the ``COPY FROM`` command, see :ref:`copy_from`. - -Loading Files from an Authenticated S3 Bucket ---------------------------------------------------- -The following is an example of loading fles from an authenticated S3 bucket: +Example +============ -.. code-block:: postgres +.. code-block:: - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' - AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; \ No newline at end of file + COPY table_name FROM WRAPPER csv_fdw OPTIONS(location = 'gs://mybucket/sqream-demo-data/file.csv'); + From a6a9820b285fb8a195b930bdf41e76b7580e1911 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 10 Sep 2023 12:25:13 +0300 Subject: [PATCH 0873/1892] Update gcp.rst --- external_storage_platforms/gcp.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst index 2a0edbd84..e54bdb32b 100644 --- a/external_storage_platforms/gcp.rst +++ b/external_storage_platforms/gcp.rst @@ -7,12 +7,12 @@ Google Cloud Platform Google Cloud Platform (GCP) offers a robust and scalable cloud infrastructure for various computing and data storage needs. -Azure URI Format -================= +Google Cloud Platform URI Format +================================= Specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. -The following is an example of the general Azure syntax: +The following is an example of the general GCP syntax: .. code-block:: console From 8dff7e1a039b47251e6d46b23dddb995deef3c3f Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 10 Sep 2023 16:32:34 +0300 Subject: [PATCH 0874/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 0b8bc6067..f45dd6919 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -69,9 +69,6 @@ Supported Operators * - Limiting number of arrayed elements - You may limit the number of arrayed elements within an ``ARRAY`` - Limiting the number of arrayed elements to 4: ``CREATE TABLE <table_name> (<column1> TEXT[4]);`` - * - Creating different column types - - You may create a table that has arrayed columns and non-arrayed columns - - ``CREATE TABLE <table_name> (<column1> TEXT('a','b','c')['d']);`` * - Compression - You may follow SQreamDB :ref:`compression guide <compression>` for compression types and methods - ``CREATE TABLE t (comp_dict INT[] CHECK('CS "dict"');`` @@ -105,7 +102,7 @@ Creating a table with arrayed columns: .. code-block:: sql - CREATE TABLE my_array (clmn1 TEXT[], clmn2 TEXT[], clmn3 INT[]); + CREATE TABLE my_array (clmn1 TEXT[], clmn2 TEXT[], clmn3 INT[], clmn4 NUMERIC(38,20)[]); Inserting arrayed values into a table: @@ -251,4 +248,4 @@ It is possible to use the ``UNNEST`` operator within a statement only once. Window ^^^^^^ -Window functions are not supported. \ No newline at end of file +Window functions are not supported. From ab8c0c8ab976a7b6b999537b40dd4b90a3deeef4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:36:10 +0300 Subject: [PATCH 0875/1892] Create deferred gather.rst --- feature_guides/deferred gather.rst | 133 +++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 feature_guides/deferred gather.rst diff --git a/feature_guides/deferred gather.rst b/feature_guides/deferred gather.rst new file mode 100644 index 000000000..7bf789721 --- /dev/null +++ b/feature_guides/deferred gather.rst @@ -0,0 +1,133 @@ +.. _deferred gather: + +*************** +Deferred Gather +*************** + +Deferred Gather is an optimization that prevents unnecessary chunk decompression when tables are joined. + +For example, Deferred Gather limits decompression to once for each join. It achieves this by merging cached GPU operation results with other result sets. + +The run-time of a deferred gather is based on the following: + +* The number of keys in the ``JOIN`` statement. +* The number of non-keys in the ``SELECT`` statement, such as the attributes or fields of a table. + +Example +========= + +The following example illustrates how the Deferred Gather optimization reduces extraneous compression, based on a ``SELECT`` ``JOIN`` query of table a that has 100 million rows and table a that has 1 million rows. + +.. code-block:: + + CREATE TABLE a (x int ,y int); + CREATE TABLE b (x int,y int); + +.. code-block:: + + SELECT a.y,b.y + FROM a + INNER JOIN b on a.x = b.x; + +The following is the output result for table a: + +.. code-block:: + + ['column[1]_5','column[1]_9','column[1]_13'] + ['column[1]_17','column[1]_21','column[1]_25','column[1]_29'] + ['column[1]_33','column[1]_37','column[1]_41','column[1]_45'] + ['column[1]_49','column[1]_53','column[1]_57','column[1]_61','column[1]_65'] + ['column[1]_69','column[1]_73','column[1]_77','column[1]_81','column[1]_85'] + ['column[1]_89','column[1]_93','column[1]_97','column[1]_101','column[1]_105'] + ['column[1]_109','column[1]_113','column[1]_117','column[1]_121','column[1]_125'] + ['column[1]_129','column[1]_133','column[1]_137','column[1]_141'] + ['column[1]_145','column[1]_149','column[1]_153','column[1]_157'] + ['column[1]_161','column[1]_165','column[1]_169','column[1]_173','column[1]_177'] + ['column[1]_181','column[1]_185','column[1]_189','column[1]_193','column[1]_197'] + ['column[1]_201','column[1]_205','column[1]_209','column[1]_213','column[1]_217'] + ['column[1]_221','column[1]_225','column[1]_229','column[1]_233'] + ['column[1]_237','column[1]_241','column[1]_245','column[1]_249'] + ['column[1]_253','column[1]_257','column[1]_261','column[1]_265','column[1]_269'] + ['column[1]_273','column[1]_277','column[1]_281','column[1]_285','column[1]_289'] + ['column[1]_293','column[1]_297','column[1]_301','column[1]_305'] + ['column[1]_309','column[1]_313','column[1]_317','column[1]_321'] + ['column[1]_325','column[1]_329','column[1]_333','column[1]_337','column[1]_341'] + ['column[1]_345','column[1]_349','column[1]_353','column[1]_357','column[1]_361'] + ['column[1]_365','column[1]_369','column[1]_373','column[1]_377'] + ['column[1]_381','column[1]_385','column[1]_389','column[1]_393'] + ['column[1]_397','column[1]_401','column[1]_405','column[1]_409'] + ['column[1]_413','column[1]_417','column[1]_421','column[1]_425','column[1]_429'] + ['column[1]_433','column[1]_437','column[1]_441','column[1]_445','column[1]_449'] + ['column[1]_453','column[1]_457','column[1]_461','column[1]_465'] + ['column[1]_469','column[1]_473','column[1]_477','column[1]_481','column[1]_485'] + ['column[1]_489','column[1]_493','column[1]_497','column[1]_501','column[1]_505'] + ['column[1]_509','column[1]_513','column[1]_517','column[1]_521'] + ['column[1]_525','column[1]_529','column[1]_533','column[1]_537'] + ['column[1]_541','column[1]_545','column[1]_549','column[1]_553'] + ['column[1]_557','column[1]_561','column[1]_565','column[1]_569'] + ['column[1]_573','column[1]_577','column[1]_581','column[1]_585'] + ['column[1]_589','column[1]_593','column[1]_597','column[1]_601','column[1]_605'] + ['column[1]_609','column[1]_613','column[1]_617','column[1]_621','column[1]_625'] + ['column[1]_629','column[1]_633','column[1]_637','column[1]_641','column[1]_645'] + ['column[1]_649','column[1]_653','column[1]_657','column[1]_661','column[1]_665'] + ['column[1]_669','column[1]_673','column[1]_677','column[1]_681','column[1]_685'] + ['column[1]_689','column[1]_693','column[1]_697','column[1]_701'] + ['column[1]_705','column[1]_709','column[1]_713','column[1]_717'] + ['column[1]_721','column[1]_725','column[1]_729','column[1]_733'] + ['column[1]_737','column[1]_741','column[1]_745','column[1]_749'] + ['column[1]_753','column[1]_757','column[1]_761','column[1]_765'] + ['column[1]_769','column[1]_773','column[1]_777','column[1]_781'] + ['column[1]_785','column[1]_789','column[1]_793','column[1]_797'] + ['column[1]_801','column[1]_805','column[1]_809','column[1]_813'] + ['column[1]_817','column[1]_821','column[1]_825','column[1]_829','column[1]_833'] + ['column[1]_837','column[1]_841','column[1]_845'] + +The following is the output result for table b: + +.. code-block:: + + ['column[3]_7','column[3]_11','column[3]_15','column[3]_19','column[3]_23', + 'column[3]_27','column[3]_31','column[3]_35','column[3]_39','column[3]_43', + 'column[3]_47','column[3]_51','column[3]_55','column[3]_59','column[3]_63', + 'column[3]_67','column[3]_71','column[3]_75','column[3]_79','column[3]_83', + 'column[3]_87','column[3]_91','column[3]_95','column[3]_99','column[3]_103', + 'column[3]_107','column[3]_111','column[3]_115','column[3]_119','column[3]_123', + 'column[3]_127','column[3]_131','column[3]_135','column[3]_139','column[3]_143', + 'column[3]_147','column[3]_151','column[3]_155','column[3]_159','column[3]_163', + 'column[3]_167','column[3]_171','column[3]_175','column[3]_179','column[3]_183', + 'column[3]_187','column[3]_191','column[3]_195','column[3]_199','column[3]_203', + 'column[3]_207','column[3]_211','column[3]_215','column[3]_219','column[3]_223', + 'column[3]_227','column[3]_231','column[3]_235','column[3]_239','column[3]_243', + 'column[3]_247','column[3]_251','column[3]_255','column[3]_259','column[3]_263', + 'column[3]_267','column[3]_271','column[3]_275','column[3]_279','column[3]_283', + 'column[3]_287','column[3]_291','column[3]_295','column[3]_299','column[3]_303', + 'column[3]_307','column[3]_311','column[3]_315','column[3]_319','column[3]_323', + 'column[3]_327','column[3]_331','column[3]_335','column[3]_339','column[3]_343', + 'column[3]_347','column[3]_351','column[3]_355','column[3]_359','column[3]_363', + 'column[3]_367','column[3]_371','column[3]_375','column[3]_379','column[3]_383', + 'column[3]_387','column[3]_391','column[3]_395','column[3]_399','column[3]_403', + 'column[3]_407','column[3]_411','column[3]_415','column[3]_419','column[3]_423', + 'column[3]_427','column[3]_431','column[3]_435','column[3]_439','column[3]_443', + 'column[3]_447','column[3]_451','column[3]_455','column[3]_459','column[3]_463', + 'column[3]_467','column[3]_471','column[3]_475','column[3]_479','column[3]_483', + 'column[3]_487','column[3]_491','column[3]_495','column[3]_499','column[3]_503', + 'column[3]_507','column[3]_511','column[3]_515','column[3]_519','column[3]_523', + 'column[3]_527','column[3]_531','column[3]_535','column[3]_539','column[3]_543', + 'column[3]_547','column[3]_551','column[3]_555','column[3]_559','column[3]_563', + 'column[3]_567','column[3]_571','column[3]_575','column[3]_579','column[3]_583', + 'column[3]_587','column[3]_591','column[3]_595','column[3]_599','column[3]_603', + 'column[3]_607','column[3]_611','column[3]_615','column[3]_619','column[3]_623', + 'column[3]_627','column[3]_631','column[3]_635','column[3]_639','column[3]_643', + 'column[3]_647','column[3]_651','column[3]_655','column[3]_659','column[3]_663', + 'column[3]_667','column[3]_671','column[3]_675','column[3]_679','column[3]_683', + 'column[3]_687','column[3]_691','column[3]_695','column[3]_699','column[3]_703', + 'column[3]_707','column[3]_711','column[3]_715','column[3]_719','column[3]_723', + 'column[3]_727','column[3]_731','column[3]_735','column[3]_739','column[3]_743', + 'column[3]_747','column[3]_751','column[3]_755','column[3]_759','column[3]_763', + 'column[3]_767','column[3]_771','column[3]_775','column[3]_779','column[3]_783', + 'column[3]_787','column[3]_791','column[3]_795','column[3]_799','column[3]_803', + 'column[3]_807','column[3]_811','column[3]_815','column[3]_819','column[3]_823', + 'column[3]_827','column[3]_831','column[3]_835','column[3]_839','column[3]_843', + 'column[3]_847'] + +Joining the above tables decompresses table a 844 times and table b 211 times, including ``NULL`` and value columns for each table. Using the table in this example, the longest process was ``DeferredGather.GpuDecompress``, taking 6.7 seconds. \ No newline at end of file From 4f33dcc7a1d706cee7a0b6abd845bdeefce43b70 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:42:44 +0300 Subject: [PATCH 0876/1892] deferred gather --- feature_guides/{deferred gather.rst => deferred_gather.rst} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename feature_guides/{deferred gather.rst => deferred_gather.rst} (99%) diff --git a/feature_guides/deferred gather.rst b/feature_guides/deferred_gather.rst similarity index 99% rename from feature_guides/deferred gather.rst rename to feature_guides/deferred_gather.rst index 7bf789721..bf63790c5 100644 --- a/feature_guides/deferred gather.rst +++ b/feature_guides/deferred_gather.rst @@ -1,4 +1,4 @@ -.. _deferred gather: +.. _deferred_gather: *************** Deferred Gather From 47bcc7b1951288ec20534dcabc2cb0170d1c1d49 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 12:46:44 +0300 Subject: [PATCH 0877/1892] GCP --- external_storage_platforms/gcp.rst | 31 +++++++++++++++++++++++++++- external_storage_platforms/index.rst | 1 + 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst index e54bdb32b..6ce03dea0 100644 --- a/external_storage_platforms/gcp.rst +++ b/external_storage_platforms/gcp.rst @@ -4,7 +4,7 @@ Google Cloud Platform *********************** -Google Cloud Platform (GCP) offers a robust and scalable cloud infrastructure for various computing and data storage needs. +Ingesting data using Google Cloud Platform (GCP) requires configuring Google Cloud Storage (GCS) bucket access. You may configure SQreamDB to separate source and destination by granting read access to one bucket and write access to a different bucket. Such separation requires that each bucket be individually configured. Google Cloud Platform URI Format @@ -18,6 +18,35 @@ The following is an example of the general GCP syntax: gs://<gcs path>/<gcs_bucket>/ +Granting GCP access +==================== + +#. In your Google Cloud console, go to **Select a project** and select the desired project. + +#. From the **PRODUCTS** menu, select **Cloud Storage** > **Buckets**. + +#. Select the bucket you wish to configure; or create a new bucket by selecting **CREATE** and following the **Create a bucket** procedure, and select the newly created bucket. + +#. Select **UPLOAD FILES** and upload the data files you wish SQreamDB to ingest. + +#. Go to **PERMISSIONS** and select **GRANT ACCESS**. + +#. Under **Add principals**, in the **New principals** box, paste the following string: + +.. code-block:: + + sample_service_account@sample_project.iam.gserviceaccount.com + +7. Under **Assign roles**, in the **Select a role** box, select **Storage Admin**. + +8. Select **ADD ANOTHER ROLE** and in the newly created **Select a role** box, select **Storage Object Admin**. + +9. Select **SAVE**. + +.. note:: + + Optimize access time to your data by configuring the location of your bucket according to `Google Cloud location considerations <https://cloud.google.com/storage/docs/locations#location-r>`_. + Example ============ diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index 4cb178938..bec142ce0 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -10,6 +10,7 @@ SQream supports the following external storage platforms: :titlesonly: azure + gcp hdfs s3 From df93350d2387336bf68b3dc5b762e7404fa45135 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 14:38:19 +0300 Subject: [PATCH 0878/1892] Update gcp.rst --- external_storage_platforms/gcp.rst | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst index 6ce03dea0..7f52a386f 100644 --- a/external_storage_platforms/gcp.rst +++ b/external_storage_platforms/gcp.rst @@ -21,6 +21,17 @@ The following is an example of the general GCP syntax: Granting GCP access ==================== +Before You Begin +---------------- + +It is essential that you have a GCP service account string. + +String example: + +.. code-block:: + + sample_service_account@sample_project.iam.gserviceaccount.com + #. In your Google Cloud console, go to **Select a project** and select the desired project. #. From the **PRODUCTS** menu, select **Cloud Storage** > **Buckets**. @@ -31,17 +42,13 @@ Granting GCP access #. Go to **PERMISSIONS** and select **GRANT ACCESS**. -#. Under **Add principals**, in the **New principals** box, paste the following string: - -.. code-block:: - - sample_service_account@sample_project.iam.gserviceaccount.com +#. Under **Add principals**, in the **New principals** box, paste your service account string. -7. Under **Assign roles**, in the **Select a role** box, select **Storage Admin**. +#. Under **Assign roles**, in the **Select a role** box, select **Storage Admin**. -8. Select **ADD ANOTHER ROLE** and in the newly created **Select a role** box, select **Storage Object Admin**. +#. Select **ADD ANOTHER ROLE** and in the newly created **Select a role** box, select **Storage Object Admin**. -9. Select **SAVE**. +#. Select **SAVE**. .. note:: From 37f01f603b6e62a624df7dcbb3b67bc479b4a7c2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 16:39:15 +0300 Subject: [PATCH 0879/1892] Update saved_queries.rst --- operational_guides/saved_queries.rst | 44 +++++++++++----------------- 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index 2ec42f247..5dd9e91f2 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -4,20 +4,18 @@ Saved Queries *********************** - - Using the ``save_query`` command will both generate and save an execution plan. This allows you to save time when running frequently used complex queries. Note that the saved execution plan is tightly coupled with the structure of its underlying tables, which means that if one or more of the objects mentioned in the query is modified, the saved query must be re-created. How saved queries work -========================== +======================= Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. Parameters support -=========================== +----------------------- Query parameters can be used as substitutes for constants expressions in queries. @@ -30,36 +28,15 @@ Creating a saved query A saved query is created using the :ref:`save_query` utility command. -Saving a simple query ---------------------------- - .. code-block:: psql t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); executed -Saving a parametrized query ------------------------------------------- - -Use parameters to replace them later at execution time. - - - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - executed - -.. TODO tip Use dollar quoting (`$$`) to avoid escaping strings. -.. this makes no sense unless you have a query which would otherwise need escaping -.. t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); -.. executed - - Executing saved queries ======================= -Executing a saved query requires calling it by it's name in a :ref:`execute_saved_query` statement. A saved query with no parameter is called without parameters. +Executing a saved query requires calling it by it's name using a :ref:`execute_saved_query` statement. A saved query with no parameters is called without parameters. .. code-block:: psql @@ -127,4 +104,17 @@ When you're done with a saved query, or would like to replace it with another, y t=> SELECT LIST_SAVED_QUERIES(); saved_query ------------------------- - select_by_weight \ No newline at end of file + select_by_weight + +Prepared Statements +==================== + +Prepared statements, also known as parameterized queries, enable the usage of parameters which may be replaced by actual values when executing the query. They are are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. + +Saving a Prepared Statement +=============================== + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); + executed \ No newline at end of file From aed7960e90f78d6b5b8d8d652b1e3cfea333b720 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Sep 2023 16:50:55 +0300 Subject: [PATCH 0880/1892] Update saved_queries.rst --- operational_guides/saved_queries.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index 5dd9e91f2..7ae629b32 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -112,9 +112,10 @@ Prepared Statements Prepared statements, also known as parameterized queries, enable the usage of parameters which may be replaced by actual values when executing the query. They are are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. Saving a Prepared Statement -=============================== +---------------------------- .. code-block:: psql t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - executed \ No newline at end of file + executed + From e9a83d6bce15bc7e353b6b0182567421ee2795f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Sep 2023 09:25:47 +0300 Subject: [PATCH 0881/1892] Update keywords_and_identifiers.rst --- reference/sql/sql_syntax/keywords_and_identifiers.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 646b12e20..aa27daf51 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -70,7 +70,7 @@ Identifiers are different than **keywords**, which are predefined words reserved SQreamDB reserved keywords: -``ALL`` | ``ANALYSE`` | ``ANALYZE`` | ``AND`` | ``ANY`` | ``ARRAY`` | ``AS`` | ``ASC`` | ``AUTHORIZATION`` | ``BINARY`` | ``BIGINT`` | ``BOTH`` | ``CASE`` | ``CAST`` | ``CHECK`` | ``COLLATE`` | ``COLUMN`` | ``CONCURRENTLY`` | ``CONSTRAINT`` | ``CREATE`` | ``CROSS`` | ``CURRENT_CATALOG`` | ``CURRENT_ROLE`` | ``CURRENT_TIME`` | ``CURRENT_USER`` | ``DEFAULT`` | ``DEFERRABLE`` | ``DESC`` | ``DISTINCT`` | ``DO`` | ``ELSE`` | ``END`` | ``EXCEPT`` | ``FALSE`` | ``FETCH`` | ``FOR`` | ``FREEZE`` | ``FROM`` | ``FULL`` | ``FUNCTION`` | ``GRANT`` | ``GROUP`` | ``HASH`` | ``HAVING`` | ``ILIKE`` | ``IN`` | ``INITIALLY`` | ``INNER`` | ``INTERSECT`` | ``INTO`` | ``IS`` | ``ISNULL`` | ``JOIN`` | ``KEY`` | ``LEADING`` | ``LEFT`` | ``LIKE`` | ``LIMIT`` | ``LOCALTIME`` | ``LOCALTIMESTAMP`` | ``LOOP`` | ``MERGE`` | ``NATURAL`` | ``NOT`` | ``NOTNULL`` | - ``NULL`` | ``OFFSET`` | ``ON`` | ``ONLY`` | ``OPTION`` | ``OR`` | ``ORDER`` | ``OUTER`` | ``OVER`` | ``OVERLAPS`` | ``PERCENT`` | ``PLACING`` | ``PRIMARY`` | ``PRECISION`` | ``PROC`` | ``REFERENCES`` | ``RETURNING`` | ``RIGHT`` | ``RLIKE`` | ``SELECT`` | ``SESSION_USER`` | ``SET`` | ``SIMILAR`` | ``SOME`` | ``SYMMETRIC`` | ``TABLE`` | ``THEN`` | ``TO`` | ``TRAILING`` | ``TRAN`` | ``TRUE`` | ``UNION`` | ``UNIQUE`` | ``USER`` | ``USING`` | ``VARIADIC`` | ``VERBOSE`` | ``WHEN`` | ``WHERE`` | ``WINDOW`` | ``WITH`` +``ALL`` | ``ANALYSE`` | ``ANALYZE`` | ``AND`` | ``ANY`` | ``ARRAY`` | ``AS`` | ``ASC`` | ``AUTHORIZATION`` | ``BINARY`` | ``BIGINT`` | ``BOTH`` | ``CASE`` | ``CAST`` | ``CHECK`` | ``COLLATE`` | ``COLUMN`` | ``COMMENT`` | ``CONCURRENTLY`` | ``CONSTRAINT`` | ``CREATE`` | ``CROSS`` | ``CURRENT_CATALOG`` | ``CURRENT_ROLE`` | ``CURRENT_TIME`` | ``CURRENT_USER`` | ``DEFAULT`` | ``DEFERRABLE`` | ``DESC`` | ``DISTINCT`` | ``DO`` | ``ELSE`` | ``END`` | ``EXCEPT`` | ``FALSE`` | ``FETCH`` | ``FOR`` | ``FREEZE`` | ``FROM`` | ``FULL`` | ``FUNCTION`` | ``GRANT`` | ``GROUP`` | ``HASH`` | ``HAVING`` | ``ILIKE`` | ``IN`` | ``INITIALLY`` | ``INNER`` | ``INTERSECT`` | ``INTO`` | ``IS`` | ``ISNULL`` | ``JOIN`` | ``KEY`` | ``LEADING`` | ``LEFT`` | ``LIKE`` | ``LIMIT`` | ``LOCALTIME`` | ``LOCALTIMESTAMP`` | ``LOOP`` | ``MERGE`` | ``NATURAL`` | ``NOT`` | ``NOTNULL`` | ``NULL`` | ``OFF`` | ``OFFSET`` | ``OFFSETS`` | ``ON`` | ``ONLY`` | ``OPTION`` | ``OR`` | ``ORDER`` | ``OUTER`` | ``OVER`` | ``OVERLAPS`` | ``PERCENT`` | ``PLACING`` | ``PRIMARY`` | ``PRECISION`` | ``PROC`` | ``PROCEDURE`` | ``REFERENCES`` | ``RETURNING`` | ``RIGHT`` | ``RLIKE`` | ``RULE`` | ``SCHEMA`` | ``SELECT`` | ``SESSION_USER`` | ``SET`` | ``SIMILAR`` | ``SOME`` | ``STATISTICS`` | ``SYMMETRIC`` | ``TABLE`` | ``THEN`` | ``TO`` | ``TOP`` | ``TRAILING`` | ``TRAN`` | ``TRUE`` | ``UNION`` | ``UNIQUE`` | ``USER`` | ``USING`` | ``VARIADIC`` | ``VERBOSE`` | ``WHEN`` | ``WHERE`` | ``WINDOW`` | ``WITH`` | From 880aae60cd1dee99ac0816181a6ad637386dafc1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Sep 2023 09:32:31 +0300 Subject: [PATCH 0882/1892] Update compression.rst --- feature_guides/compression.rst | 33 +-------------------------------- 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index a56826ffa..e674b6d57 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -87,38 +87,7 @@ The following table shows the supported compression methods: - ``Integer``, ``date``, and ``timestamp`` - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. - GPU - * - ``zlib`` - - All types - - The **basic_zlib_compressor** and **basic_zlib_decompressor** compress and decompress data in the **ZLIB** format, using **DualUseFilters** for input and output. In general, compression filters are for output, and decompression filters for input. - - CPU - * - ``SPACES`` - - All types - - Reduces the storage space required for data by identifying repeating sequences of values and replacing them with a compact representation. This method is particularly effective when there are repetitive patterns in the data. - - CPU - * - ``DELTA_RLE`` - - Integer types - - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. - - CPU - * - ``SPADES`` - - All types - - An extension of ``SPACES`` compression, optimizing the compression scheme further to handle specific data patterns and types efficiently. - - CPU - * - ``SPAPPY`` - - All types - - Specialized variation of the ``Snappy`` compression algorithm. ``Snappy`` is a fast and efficient compression method that works well with various types of data, offering good compression ratios and decompression speeds. - - CPU - * - ``SPAZLY`` - - All types - - An encryption method involving the transformation of plaintext characters into a jumbled or disorderly arrangement - - CPU - * - ``CRLE`` - - All types - - An encryption process involving the compression and run-length encoding of data to secure it - - CPU - * - ``LZ4_ZIGZAG`` - - All types - - An encryption approach combining LZ4 compression with a zigzag pattern - - CPU + .. note:: Automatic compression does **not** select the ``zlib`` compression method. From c4df2de23ff1aed6056099daade9458ed5ef3bd5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Sep 2023 09:33:39 +0300 Subject: [PATCH 0883/1892] Update compression.rst --- feature_guides/compression.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index e674b6d57..cfe0917f7 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -88,8 +88,7 @@ The following table shows the supported compression methods: - Optimized RLE + Delta type for built-in :ref:`identity columns<identity>`. - GPU - -.. note:: Automatic compression does **not** select the ``zlib`` compression method. + .. _specifying_compressions: From e07fa55253f770d9cef2f1189e7025bea9229e0c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Sep 2023 11:10:57 +0300 Subject: [PATCH 0884/1892] prepared statement --- .../client_drivers/jdbc/index.rst | 26 +++++++++- .../jdbc/samplepreparedstatement.java | 48 +++++++++++++++++++ operational_guides/saved_queries.rst | 4 +- 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 connecting_to_sqream/client_drivers/jdbc/samplepreparedstatement.java diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index a2d7272f6..daf0f13fe 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -166,7 +166,7 @@ The following is an example of a SQream cluster with a load balancer and a speci jdbc:Sqream://sqream.mynetwork.co:3108/raviga;user=rhendricks;password=Tr0ub4dor&3;cluster=true;service=etl -Sample Java Program +Java Program Sample -------------------- You can download the :download:`JDBC Application Sample File <sample.java>` below by right-clicking and saving it to your computer. @@ -175,3 +175,27 @@ You can download the :download:`JDBC Application Sample File <sample.java>` belo :language: java :caption: JDBC Application Sample :linenos: + +Prepared Statements +==================== + +Prepared statements, also known as parameterized queries, are a feature of JDBC that enable the use of parameters to optimize query execution, enhance security, and enable query template reuse with different parameter values in Java applications. + +Saving a Prepared Statement +---------------------------- + +.. code-block:: psql + + t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); + +Prepared Statement Sample +--------------------------- + +The following is a Java code snippet employing a JDBC prepared statement object to ingest a batch of one million records into SQreamDB. + +You may download the :download:`Prepared statement <samplepreparedstatement.java>` by right-clicking and saving it to your computer. + +.. literalinclude:: samplePreparedStatement.java + :language: java + :caption: Prepared Statement Sample + :linenos: \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/jdbc/samplepreparedstatement.java b/connecting_to_sqream/client_drivers/jdbc/samplepreparedstatement.java new file mode 100644 index 000000000..0b96ab9c2 --- /dev/null +++ b/connecting_to_sqream/client_drivers/jdbc/samplepreparedstatement.java @@ -0,0 +1,48 @@ +try (BufferedReader br = new BufferedReader(new FileReader(csv_file))) { + + int i = 0; + String csv_line; + int batchSize = 1000000; + String url = "jdbc:Sqream://" + host + ":" + port + + "/riru;cluster=false;user=sqream;password=sqream"; + LocalDateTime start_time = LocalDateTime.now(); + + Class.forName("com.sqream.jdbc.SQDriver"); + + Connection con = + DriverManager.getConnection(url, "sqream", "sqream"); + + String inStmt = + "INSERT INTO message values(?,?,?,?,?,?,?,?,?,?,?,?)"; + + PreparedStatement ps = con.prepareStatement(inStmt); + + while((csv_line = br.readLine()) != null){ + String[] message = csv_line.split(","); + + ps.setString(1, message[0].trim()); + ps.setInt(2, Integer.parseInt(message[1].trim())); + ps.setInt(3, Integer.parseInt(message[2].trim())); + ps.setInt(4, Integer.parseInt(message[3].trim())); + ps.setInt(5, Integer.parseInt(message[4].trim())); + ps.setString(6, message[5].trim()); + ps.setString(7, message[6].trim()); + ps.setString(8, message[7].trim()); + ps.setString(9, message[8].trim()); + ps.setString(10, message[9].trim()); + ps.setInt(11, Integer.parseInt(message[10].trim())); + ps.setInt(12, Integer.parseInt(message[11].trim())); + + ps.addBatch(); + + if(++i == batchSize) { + i = 0; + ps.executeBatch(); + ps.close(); + System.out.println(LocalDateTime.now().toString() + + ": Inserted " + batchSize + " records."); + ps = con.prepareStatement(inStmt); + } + + + } \ No newline at end of file diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index 7ae629b32..3386a4bad 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -109,7 +109,7 @@ When you're done with a saved query, or would like to replace it with another, y Prepared Statements ==================== -Prepared statements, also known as parameterized queries, enable the usage of parameters which may be replaced by actual values when executing the query. They are are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. +Prepared statements, also known as parameterized queries, enable the usage of parameters which may be replaced by actual values when executing the query. They are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. Saving a Prepared Statement ---------------------------- @@ -117,5 +117,5 @@ Saving a Prepared Statement .. code-block:: psql t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - executed + From 0828cc4424cbf0557e1c331ed0292707802d0ce4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 09:09:18 +0300 Subject: [PATCH 0885/1892] Update 4.3.rst --- releases/4.3.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index c32924576..9a97160c7 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -178,7 +178,19 @@ There are two methods of granting back access to services: * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` +8. To re-enable catalog and UI access, you may either grant access to all system roles using your ``public`` role: - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. +.. code-block:: + + GRANT ALL PERMISSIONS ON CATALOG <catalog_name> TO public; + +Or individually grant access to roles: + +.. code-block:: + + GRANT ALL PERMISSIONS ON CATALOG <catalog_name> TO <role_name>; + + +.. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From 02d2a98d5c9f4e8322db7541abf42ab6b3528b1d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 09:11:14 +0300 Subject: [PATCH 0886/1892] Update 4.3.rst --- releases/4.3.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 9a97160c7..70fb526c0 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -190,7 +190,6 @@ Or individually grant access to roles: GRANT ALL PERMISSIONS ON CATALOG <catalog_name> TO <role_name>; - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From e93e8474b71aa2f8d16c329b0e4034f45402a3b2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 09:18:38 +0300 Subject: [PATCH 0887/1892] Array data type --- data_type_guides/supported_casts.rst | 2 +- data_type_guides/supported_data_types.rst | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/data_type_guides/supported_casts.rst b/data_type_guides/supported_casts.rst index 39844772b..a6b7a3a32 100644 --- a/data_type_guides/supported_casts.rst +++ b/data_type_guides/supported_casts.rst @@ -3,6 +3,7 @@ ************************* Supported Casts ************************* + The **Supported Casts** section describes supported casts for the following types: .. toctree:: @@ -15,4 +16,3 @@ The **Supported Casts** section describes supported casts for the following type sql_data_types_floating_point sql_data_types_string sql_data_types_date - sql_data_type_array \ No newline at end of file diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 6dc8a2b03..09c7656b4 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -4,6 +4,13 @@ Supported Data Types ******************** +.. toctree:: + :maxdepth: 1 + :glob: + :hidden: + + sql_data_type_array + The following table shows the supported data types. .. list-table:: From bf8c0b0bbad7fa5f014d8ff2b591f90856dc5efd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 10:10:23 +0300 Subject: [PATCH 0888/1892] Update 4.3.rst --- releases/4.3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 70fb526c0..1c01b8ff1 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -171,7 +171,7 @@ Upgrading to v4.3 $ ./upgrade_storage <levelDB path> -7. Version 4.3 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.3 or later, this feature initializes access to services, causing existing roles to lose their access to services. +7. Version 4.3 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.3 or later, this feature initializes access to services and catalog tables, causing existing roles to lose their access to both services and catalog tables. There are two methods of granting back access to services: From 01c256c9ef27dc6f008d403613ecdad630dbd792 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 10:53:34 +0300 Subject: [PATCH 0889/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 5c399ab8e..8c36a0f75 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -52,6 +52,8 @@ Syntax | DELIMITER = '{ field_delimiter }' -- for CSV only, | RECORD_DELIMITER = '{ record_delimiter }', -- for CSV only | AWS_ID '{ AWS ID }', + | CONTINUE_ON_ERROR = { true | false } + | ERROR_COUNT = '{ error count }' | AWS_SECRET '{ AWS SECRET }', | OFFSET -- for CSV and JSON only } @@ -105,6 +107,11 @@ Parameters - Credentials for authenticated S3 access * - ``OFFSET`` - Used to specify the number of rows to skip from the beginning of the result set + * - ``CONTINUE_ON_ERROR`` + - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT`` When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false``. + * - ``ERROR_COUNT`` + - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. Default value: ``unlimited``. Value range: 1 to 2147483647. + Examples @@ -182,3 +189,18 @@ The ``OFFSET`` parameter may be used with Parquet and CSV textual formats. OFFSET = 2 ); +Using the ``CONTINUE_ON_ERROR`` and ``ERROR_COUNT`` Parameters +---------------------------------------------------------------- + +.. code-block:: + + CREATE OR REPLACE FOREIGN TABLE cool_animalz + (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) + WRAPPER csv_fdw + OPTIONS + ( LOCATION = '/home/rhendricks/cool_animals.csv', + DELIMITER = '\t', + continue_on_error = true, + ERROR_COUNT = 3 + ) + ; \ No newline at end of file From 12bfbc725e99a1545a7b70c2a0a206c01f344839 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 11:11:21 +0300 Subject: [PATCH 0890/1892] Update 4.3.rst --- releases/4.3.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 1c01b8ff1..16e85c052 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -171,20 +171,20 @@ Upgrading to v4.3 $ ./upgrade_storage <levelDB path> -7. Version 4.3 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.3 or later, this feature initializes access to services and catalog tables, causing existing roles to lose their access to both services and catalog tables. +7. Version 4.3 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.3 or later, this feature initializes access to services and to catalog tables, causing existing roles to lose their access to services, catalog tables and consequently also to the UI (Catalog tables may also be used to determine user access rights and privileges. The UI can integrate with these permissions to control what actions users are allowed to perform in the database.). There are two methods of granting back access to services: * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` -8. To re-enable catalog and UI access, you may either grant access to all system roles using your ``public`` role: +To grant back access to catalog tables and the UI, you may either grant access to all system roles, using your ``public`` role: .. code-block:: GRANT ALL PERMISSIONS ON CATALOG <catalog_name> TO public; -Or individually grant access to roles: +Or individually grant access to selected roles: .. code-block:: From 32eb5c02860e84c141c6866215bf9af7b8e88795 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:07:05 +0300 Subject: [PATCH 0891/1892] ODBC .NET ARRAY --- .../client_drivers/dotnet/index.rst | 5 +++++ .../odbc/install_configure_odbc_linux.rst | 4 ++++ .../odbc/install_configure_odbc_windows.rst | 5 +++++ data_type_guides/sql_data_type_array.rst | 13 +++++++++++-- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index 22512fd93..d21dfd0a1 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -139,3 +139,8 @@ You can download the :download:`.NET Application Sample File <sample.cs>` below :language: C# :caption: .NET Application Sample :linenos: + +Limitations +=============== + +Please note that .NET does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using .NET to connect to the database. \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index 075ba254c..575b8739c 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -249,5 +249,9 @@ ODBC DSN Parameters * 5 = Debug tracing * 6 = Detailed tracing +Limitations +=============== + +Please note that ODBC does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst index e3f198d0c..51112f3a7 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst @@ -132,3 +132,8 @@ After installing the ODBC driver, you may experience the following error: (c:\Program Files\SQream Technologies\ODBC Driver\sqreamOdbc64.dll) This is an issue with the Visual Studio Redistributable packages. Verify you've correctly installed them, as described in the :ref:`Visual Studio 2015 Redistributables <vcredist>` section above. + +Limitations +=============== + +Please note that ODBC does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. \ No newline at end of file diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index f45dd6919..b3e296686 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -199,7 +199,15 @@ Result: Limitations =========== -Casting Limitations +Connectors +------------ + +Limitations +=============== + +Please note that the SQreamDB ODBC and .NET connectors do not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using these connectors. + +Casting ------------------- Numeric @@ -228,7 +236,7 @@ Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not INSERT INTO t_int VALUES (array[1,2,3]); INSERT INTO t_text SELECT xint::TEXT[] FROM t_int; -Function Limitations +Function -------------------- || (Concatenate) @@ -249,3 +257,4 @@ Window ^^^^^^ Window functions are not supported. + From e3d4c0f5ae7be0479c213f75b0cac347214f02f6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:09:42 +0300 Subject: [PATCH 0892/1892] ARRAY ODBC .NET --- .../client_drivers/odbc/install_configure_odbc_linux.rst | 2 +- .../client_drivers/odbc/install_configure_odbc_windows.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index 575b8739c..ff99fd6ee 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -252,6 +252,6 @@ ODBC DSN Parameters Limitations =============== -Please note that ODBC does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. +Please note that the SQreamDB ODBC connector does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst index 51112f3a7..92a947e57 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst @@ -136,4 +136,4 @@ This is an issue with the Visual Studio Redistributable packages. Verify you've Limitations =============== -Please note that ODBC does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. \ No newline at end of file +Please note that the SQreamDB ODBC connector does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using ODBC to connect to the database. \ No newline at end of file From 98dfb991b4ebf1c76e5cedb3fc69224bb020f3b2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:09:30 +0300 Subject: [PATCH 0893/1892] Update workload_manager.rst --- feature_guides/workload_manager.rst | 73 ++++++++++++++--------------- 1 file changed, 34 insertions(+), 39 deletions(-) diff --git a/feature_guides/workload_manager.rst b/feature_guides/workload_manager.rst index 9cf582dde..484980532 100644 --- a/feature_guides/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -62,49 +62,44 @@ Queries from management uses any available worker. Creating the Configuration ----------------------------------- -The persistent configuration for this set-up is listed in the four configuration files shown below. - -Each worker gets a comma-separated list of service queues that it subscribes to. These services are specified in the ``initialSubscribedServices`` attribute. - .. code-block:: json - :caption: Worker #1 - :emphasize-lines: 7 - { - "compileFlags": { - }, - "runtimeFlags": { - }, - "runtimeGlobalFlags": { - "initialSubscribedServices" : "etl,management" - }, - "server": { - "gpu": 0, - "port": 5000, - "cluster": "/home/rhendricks/raviga_database", - "licensePath": "/home/sqream/.sqream/license.enc" - } - } -.. code-block:: json - :caption: Workers #2, #3, #4 - :emphasize-lines: 7 + { + "cluster": "/home/rhendricks/raviga_database", + "cudaMemQuota": 25, + "gpu": 0, + "maxConnectionInactivitySeconds": 120, + "legacyConfigFilePath": "tzah_legacy.json", + "licensePath": "/home/sqream/.sqream/license.enc", + "metadataServerIp": "192.168.0.103", + "limitQueryMemoryGB": 250, + "machineIP": "192.168.0.103", + "metadataServerPort": 3105, + "port": 5000, + "useConfigIP": true + } - { - "compileFlags": { - }, - "runtimeFlags": { - }, - "runtimeGlobalFlags": { - "initialSubscribedServices" : "query,management" - }, - "server": { - "gpu": 1, - "port": 5001, - "cluster": "/home/rhendricks/raviga_database", - "licensePath": "/home/sqream/.sqream/license.enc" - } - } +.. code-block:: json + :caption: Legacy File + + + { + "debugNetworkSession": false, + "developerMode": true, + "diskSpaceMinFreePercent": 1, + "maxNumAutoCompressedChunksThreshold" : 1, + "insertMergeRowsThreshold":40000000, + "insertCompressors": 8, + "insertParsers": 8, + "nodeInfoLoggingSec": 60, + "reextentUse": true, + "separatedGatherThreads": 16, + "showFullExceptionInfo": true, + "spoolMemoryGB":200, + "useClientLog": true, + "useMetadataServer":true + } .. tip:: You can create this configuration temporarily (for the current session only) by using the :ref:`subscribe_service` and :ref:`unsubscribe_service` statements. From 0f4ca171da551ddf18c8e7d56cf6ca5a16ec9dec Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 08:12:57 +0300 Subject: [PATCH 0894/1892] Update retrieving_execution_plan_output_using_studio.rst --- .../retrieving_execution_plan_output_using_studio.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/troubleshooting/retrieving_execution_plan_output_using_studio.rst b/troubleshooting/retrieving_execution_plan_output_using_studio.rst index 80991669c..775991dbe 100644 --- a/troubleshooting/retrieving_execution_plan_output_using_studio.rst +++ b/troubleshooting/retrieving_execution_plan_output_using_studio.rst @@ -1,10 +1,10 @@ .. _retrieving_execution_plan_output_using_studio: -********************************************** -Retrieving Execution Plan Output Using Studio -********************************************** +******************************************************* +Retrieving Execution Plan Output Using SQreamDB Studio +******************************************************* -You may use SQreamDB Studio to create a query plan snapshot to be used for monitoring and troubleshooting slow running statements and for identifying long-running execution nodes (components that process data), etc. +You may use SQreamDB Studio to create a query plan snapshot to be used for monitoring and troubleshooting slow running statements and for identifying long-running execution nodes (components that process data), that may cause performance issues. Retrieving Execution Plan Output ================================ From 13d7eb4f64077b766c899c4d68870f3ed9b351a8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:16:20 +0300 Subject: [PATCH 0895/1892] Update deferred_gather.rst --- feature_guides/deferred_gather.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/deferred_gather.rst b/feature_guides/deferred_gather.rst index bf63790c5..c0f723756 100644 --- a/feature_guides/deferred_gather.rst +++ b/feature_guides/deferred_gather.rst @@ -20,7 +20,7 @@ The following example illustrates how the Deferred Gather optimization reduces e .. code-block:: - CREATE TABLE a (x int ,y int); + CREATE TABLE a (x int,y int); CREATE TABLE b (x int,y int); .. code-block:: From 1ae4f2e4906b21f2aa6289dd2e8e6256319145f4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 09:37:56 +0300 Subject: [PATCH 0896/1892] Update retrieving_execution_plan_output_using_studio.rst --- .../retrieving_execution_plan_output_using_studio.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/troubleshooting/retrieving_execution_plan_output_using_studio.rst b/troubleshooting/retrieving_execution_plan_output_using_studio.rst index 775991dbe..6dac66f74 100644 --- a/troubleshooting/retrieving_execution_plan_output_using_studio.rst +++ b/troubleshooting/retrieving_execution_plan_output_using_studio.rst @@ -4,7 +4,7 @@ Retrieving Execution Plan Output Using SQreamDB Studio ******************************************************* -You may use SQreamDB Studio to create a query plan snapshot to be used for monitoring and troubleshooting slow running statements and for identifying long-running execution nodes (components that process data), that may cause performance issues. +You may use SQreamDB Studio to create a query plan snapshot to be used for monitoring and troubleshooting slow running statements and for identifying long-running execution Workers (components that process data), that may cause performance issues. Retrieving Execution Plan Output ================================ From 69b50701b1cd3c4fbc87859e5324b5ceaf86528e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:10:39 +0300 Subject: [PATCH 0897/1892] Prepared Statement --- connecting_to_sqream/client_drivers/jdbc/index.rst | 7 ------- operational_guides/saved_queries.rst | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index daf0f13fe..ef56dc1c6 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -180,13 +180,6 @@ Prepared Statements ==================== Prepared statements, also known as parameterized queries, are a feature of JDBC that enable the use of parameters to optimize query execution, enhance security, and enable query template reuse with different parameter values in Java applications. - -Saving a Prepared Statement ----------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); Prepared Statement Sample --------------------------- diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index 3386a4bad..54456edab 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -14,7 +14,7 @@ How saved queries work Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. -Parameters support +Parameter support ----------------------- Query parameters can be used as substitutes for constants expressions in queries. From 28ddf77fd2844cbcb0a2a796c9f9a2f7eea92522 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 11:22:25 +0300 Subject: [PATCH 0898/1892] Update saved_queries.rst --- operational_guides/saved_queries.rst | 66 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index 54456edab..f1a9d4ee3 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -4,18 +4,20 @@ Saved Queries *********************** + + Using the ``save_query`` command will both generate and save an execution plan. This allows you to save time when running frequently used complex queries. Note that the saved execution plan is tightly coupled with the structure of its underlying tables, which means that if one or more of the objects mentioned in the query is modified, the saved query must be re-created. -How saved queries work -======================= +How Saved Queries Work +========================== Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. -Parameter support ------------------------ +Parameter Support +=========================== Query parameters can be used as substitutes for constants expressions in queries. @@ -23,24 +25,38 @@ Query parameters can be used as substitutes for constants expressions in queries * Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) -Creating a saved query +Creating a Saved Query ====================== A saved query is created using the :ref:`save_query` utility command. +Saving a Simple Query +--------------------------- + .. code-block:: psql - t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); + SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); executed -Executing saved queries +Saving a Parameterized Query +------------------------------------------ + +Parameterized queries, also known as prepared statements, enable the usage of parameters which may be replaced by actual values when executing the query. They are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. + +.. code-block:: psql + + SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); + + + +Executing Saved Queries ======================= -Executing a saved query requires calling it by it's name using a :ref:`execute_saved_query` statement. A saved query with no parameters is called without parameters. +Executing a saved query requires calling it by it's name in a :ref:`execute_saved_query` statement. A saved query with no parameter is called without parameters. .. code-block:: psql - t=> SELECT EXECUTE_SAVED_QUERY('select_all'); + SELECT EXECUTE_SAVED_QUERY('select_all'); Name | Team | Number | Position | Age | Height | Weight | College | Salary -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 @@ -53,7 +69,7 @@ Executing a saved query with parameters requires specifying the parameters in th .. code-block:: psql - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); Name | Team | Number | Position | Age | Height | Weight | College | Salary ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 @@ -61,7 +77,7 @@ Executing a saved query with parameters requires specifying the parameters in th Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 -Listing saved queries +Listing Saved Queries ======================= Saved queries are saved as a database objects. They can be listed in one of two ways: @@ -70,7 +86,7 @@ Using the :ref:`catalog<catalog_reference>`: .. code-block:: psql - t=> SELECT * FROM sqream_catalog.savedqueries; + SELECT * FROM sqream_catalog.savedqueries; name | num_parameters --------------------------+--------------- select_all | 0 @@ -81,7 +97,7 @@ Using the :ref:`list_saved_queries` utility function: .. code-block:: psql - t=> SELECT LIST_SAVED_QUERIES(); + SELECT LIST_SAVED_QUERIES(); saved_query ------------------------- select_all @@ -89,33 +105,19 @@ Using the :ref:`list_saved_queries` utility function: select_by_weight_and_team -Dropping a saved query +Dropping a Saved Query ============================= When you're done with a saved query, or would like to replace it with another, you can drop it with :ref:`drop_saved_query`: .. code-block:: psql - t=> SELECT DROP_SAVED_QUERY('select_all'); + SELECT DROP_SAVED_QUERY('select_all'); executed - t=> SELECT DROP_SAVED_QUERY('select_by_weight_and_team'); + SELECT DROP_SAVED_QUERY('select_by_weight_and_team'); executed - t=> SELECT LIST_SAVED_QUERIES(); + SELECT LIST_SAVED_QUERIES(); saved_query ------------------------- - select_by_weight - -Prepared Statements -==================== - -Prepared statements, also known as parameterized queries, enable the usage of parameters which may be replaced by actual values when executing the query. They are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. - -Saving a Prepared Statement ----------------------------- - -.. code-block:: psql - - t=> SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - - + select_by_weight \ No newline at end of file From ec6d4495603fe8873c6a4877473ceef808b54974 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:09:55 +0300 Subject: [PATCH 0899/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 5d3fde038..5c8ef369a 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -133,7 +133,7 @@ Elements - No error log - - - When used, the ``COPY`` process will write error information from unparsable rows to the file specified by this parameter. + When used, the ``COPY`` process will write error information from unparsable rows to the file specified by this parameter. ``ERROR_LOG`` requires ``CONTINUE_ON_ERROR`` to be set to ``true`` * If an existing file path is specified, it will be overwritten. @@ -565,20 +565,26 @@ Saving Rejected Rows to a File .. code-block:: postgres - COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.csv', - ,continue_on_error = true - ,error_log = '/temp/load_error.log' - ); + COPY table_name FROM WRAPPER csv_fdw + OPTIONS + ( + location = '/tmp/file.csv' + ,continue_on_error = true + ,error_log = '/temp/load_error.log' + ); .. code-block:: postgres - COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv' - ,delimiter '|' - ,error_log = '/temp/load_error.log' -- Save error log - ,rejected_data = '/temp/load_rejected.log' -- Only save rejected rows - ,limit = 100 -- Only load 100 rows - ,error_count = 5 -- Stop the load if 5 errors reached - ); + COPY table_name FROM WRAPPER csv_fdw + OPTIONS + ( + location = '/tmp/file.psv' + ,delimiter '|' + ,error_log = '/temp/load_error.log' -- Save error log + ,rejected_data = '/temp/load_rejected.log' -- Only save rejected rows + ,limit = 100 -- Only load 100 rows + ,error_count = 5 -- Stop the load if 5 errors reached + ); Loading CSV Files from a Set of Directories From 3ee04d6943b916b308d26ff0e70ec0798f11744b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Sep 2023 15:45:16 +0300 Subject: [PATCH 0900/1892] CentOS 7.x --- releases/4.3.rst | 10 +++++----- releases/4.4.rst | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 16e85c052..e496137ad 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -17,7 +17,7 @@ Compatibility Matrix | System Requirement | Details | +=========================+========================================================================+ | Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x | +| | * RHEL - 7.x / 8.x | +-------------------------+------------------------------------------------------------------------+ | Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ @@ -117,14 +117,14 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa * ``AwsEndpointOverride`` * ``AwsObjectAccessStyle`` -Deprecated Features +Deprecations ------------------- ► **CentOS Linux 7.x** -As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. - -**CentOS Linux 8.x** is now officially supported. +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. +* **CentOS Linux 8.x** is now officially supported. ► ``INT96`` diff --git a/releases/4.4.rst b/releases/4.4.rst index 2fcc8125e..73e22ac6d 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -89,14 +89,14 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa * ``AwsEndpointOverride`` * ``AwsObjectAccessStyle`` -Deprecated Features +Deprecations ------------------- ► **CentOS Linux 7.x** -As of June 2024, CentOS Linux 7.x will reach its End of Life. This announcement provides a one-year advance notice for our users to plan for this change. Due to the fact that CentOS will no longer support production deployments, we recommend users to explore migration to the Red Hat Enterprise Linux (RHEL) commercial Linux distribution developed by Red Hat. - -**CentOS Linux 8.x** is now officially supported. +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. +* **CentOS Linux 8.x** is now officially supported. ► ``INT96`` From 13f060374a44e15bc405b0492639fc59e7b12a1f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Sep 2023 08:00:28 +0300 Subject: [PATCH 0901/1892] Update compression.rst --- feature_guides/compression.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index cfe0917f7..4c0271e31 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -1,6 +1,6 @@ .. _compression: -*********************** +*********************** Compression *********************** From d449ff54bac854b6c2c69a74e633d2fa83962197 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:05:03 +0300 Subject: [PATCH 0902/1892] Update internals_architecture.rst --- architecture/internals_architecture.rst | 42 ++++++++++--------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index af5ec0acf..a47092fb6 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -4,50 +4,52 @@ Internals and Architecture ************************** -Get to know the SQreamDB key functions and system architecture components and the best practices and customization possibilities. +Get to know the SQreamDB key functions and system architecture components, best practices, customization possibilities, and optimizations. + +SQreamDB leverages GPU acceleration as an essential component of its core database operations, significantly enhancing columnar data processing. This integral GPU utilization isn't an optional feature but is fundamental to a wide range of data tasks such as ``GROUP BY``, scalar functions, ``JOIN``, ``ORDER BY``, and more. This approach harnesses the inherent parallelism of GPUs, effectively employing a single instruction to process multiple values, akin to the Single-Instruction, Multiple Data (SIMD) concept, tailored for high-throughput operations. .. figure:: /_static/images/sqream_db_internals.png :align: left :width: 75% :alt: SQreamDB internals -Key Functions and Components -============================ +Concurrency and Admission Control +================================== + +The SQreamDB execution engine employs thread workers and message passing for its foundation. This threading approach enables the concurrent execution of diverse operations, seamlessly integrating IO and GPU tasks with CPU operations while boosting the performance of CPU-intensive tasks. + +Learn more about :ref:`concurrency_and_scaling_in_sqream`. Statement Compiler ------------------- +============================ The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement execution plans. Building Blocks (GPU Workers) ------------------------------ +============================== In SQreamDB, the main workload is carried out by specialized C++/CUDA building blocks, also known as Workers, which intentionally lack inherent intelligence and require precise instructions for operation. Effectively assembling these components relies largely on the capabilities of the statement compiler. Storage Layer -------------- +================ The storage is split into the metadata layer and an append-only data layer. Metadata Layer -^^^^^^^^^^^^^^ +------------------ Utilizing RocksDB key/value data store, the metadata layer incorporates features such as snapshots and atomic writes within the transaction system, while working in conjunction with the append-only bulk data layer to maintain overall data consistency. Bulk Data Layer Optimization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +------------------------------------ -SQreamDB harnesses the power of its columnar storage architecture within the bulk data layer for performance optimization. This layer employs IO-optimized extents containing compression-enabled CPU and GPU-efficient chunks. Even during small insert operations, SQreamDB maintains efficiency by generating less optimized chunks and extents as needed. This is achieved through background transactional reorganization that doesn't disrupt Data Manipulation Language (DML) operations. The system initially writes small chunks via small inserts and subsequently reorganizes them, facilitating swift medium-sized insert transactions and rapid queries. This optimization strategy, coupled with SQreamDB's columnar storage, ensures peak performance across diverse data processing tasks. +SQreamDB harnesses the power of its columnar storage architecture within the bulk data layer for performance optimization. This layer employs IO-optimized extents containing compression-enabled CPU and GPU-efficient chunks. Even during small insert operations, SQreamDB maintains efficiency by generating less optimized chunks and extents as needed. This is achieved through background transactional reorganization, such as ``DeferredGather``, that doesn't disrupt Data Manipulation Language (DML) operations. Deferred Gather optimizes GPU processing by selectively gathering only the necessary columns after GPU execution, effectively conserving memory and enhancing query performance. -Concurrency and Admission Control ---------------------------------- +The system initially writes small chunks via small inserts and subsequently reorganizes them, facilitating swift medium-sized insert transactions and rapid queries. This optimization strategy, coupled with SQreamDB's columnar storage, ensures peak performance across diverse data processing tasks. -The SQreamDB execution engine employs thread workers and message passing for its foundation. This threading approach enables the concurrent execution of diverse operations, seamlessly integrating IO and GPU tasks with CPU operations while boosting the performance of CPU-intensive tasks. - -Learn more about :ref:`concurrency_and_scaling_in_sqream`. Transactions ------------- +============================ SQreamDB has serializable (auto commit) transactions, with these features: @@ -61,13 +63,3 @@ SQreamDB has serializable (auto commit) transactions, with these features: * Other operations such as :ref:`delete`, :ref:`truncate`, and DDL use :ref:`coarse-grained exclusive locking<concurrency_and_locks>`. -GPU Usage -========= - -SQreamDB uses GPUs for accelerating database operations. This acceleration brings additional benefits to columnar data processing. - -SQreamDB's GPU acceleration is integral to database operations. It is not an additional feature, but rather core to most data operations, e.g. ``GROUP BY``, scalar functions, ``JOIN``, ``ORDER BY``, and more. - -Using a GPU is an extended form of SIMD (Single-Instruction, Multiple Data) intended for high throughput operations. When GPU acceleration is used, SQreamDB uses special building blocks to take advantage of the high degree of parallelism of the GPU. This means that GPU operations use a single instruction that runs on multiple values. - - From 34dd9016eb4774e3548965d75354d942fa3464fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:12:51 +0300 Subject: [PATCH 0903/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 5c8ef369a..111949c83 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -102,9 +102,9 @@ Elements - - Table to copy data into * - ``QUOTE`` - - " + - ``"`` - - - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in **COPY FROM** and foreign tables. + - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. ``QUOTE`` can be used with ``csv_fdw`` in ``COPY FROM`` and foreign tables. The following characters cannot be an alternative quote character: ``"-.:\\0123456789abcdefghijklmnopqrstuvwxyzN"`` * - ``fdw_name`` - - ``csv_fdw``, ``orc_fdw``, ``parquet_fdw``, ``json_fdw``, or ``avro_fdw`` From 332537243eb1678916e09b329e9a30f6bec24138 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:48:07 +0300 Subject: [PATCH 0904/1892] Delete deferred_gather.rst --- feature_guides/deferred_gather.rst | 133 ----------------------------- 1 file changed, 133 deletions(-) delete mode 100644 feature_guides/deferred_gather.rst diff --git a/feature_guides/deferred_gather.rst b/feature_guides/deferred_gather.rst deleted file mode 100644 index c0f723756..000000000 --- a/feature_guides/deferred_gather.rst +++ /dev/null @@ -1,133 +0,0 @@ -.. _deferred_gather: - -*************** -Deferred Gather -*************** - -Deferred Gather is an optimization that prevents unnecessary chunk decompression when tables are joined. - -For example, Deferred Gather limits decompression to once for each join. It achieves this by merging cached GPU operation results with other result sets. - -The run-time of a deferred gather is based on the following: - -* The number of keys in the ``JOIN`` statement. -* The number of non-keys in the ``SELECT`` statement, such as the attributes or fields of a table. - -Example -========= - -The following example illustrates how the Deferred Gather optimization reduces extraneous compression, based on a ``SELECT`` ``JOIN`` query of table a that has 100 million rows and table a that has 1 million rows. - -.. code-block:: - - CREATE TABLE a (x int,y int); - CREATE TABLE b (x int,y int); - -.. code-block:: - - SELECT a.y,b.y - FROM a - INNER JOIN b on a.x = b.x; - -The following is the output result for table a: - -.. code-block:: - - ['column[1]_5','column[1]_9','column[1]_13'] - ['column[1]_17','column[1]_21','column[1]_25','column[1]_29'] - ['column[1]_33','column[1]_37','column[1]_41','column[1]_45'] - ['column[1]_49','column[1]_53','column[1]_57','column[1]_61','column[1]_65'] - ['column[1]_69','column[1]_73','column[1]_77','column[1]_81','column[1]_85'] - ['column[1]_89','column[1]_93','column[1]_97','column[1]_101','column[1]_105'] - ['column[1]_109','column[1]_113','column[1]_117','column[1]_121','column[1]_125'] - ['column[1]_129','column[1]_133','column[1]_137','column[1]_141'] - ['column[1]_145','column[1]_149','column[1]_153','column[1]_157'] - ['column[1]_161','column[1]_165','column[1]_169','column[1]_173','column[1]_177'] - ['column[1]_181','column[1]_185','column[1]_189','column[1]_193','column[1]_197'] - ['column[1]_201','column[1]_205','column[1]_209','column[1]_213','column[1]_217'] - ['column[1]_221','column[1]_225','column[1]_229','column[1]_233'] - ['column[1]_237','column[1]_241','column[1]_245','column[1]_249'] - ['column[1]_253','column[1]_257','column[1]_261','column[1]_265','column[1]_269'] - ['column[1]_273','column[1]_277','column[1]_281','column[1]_285','column[1]_289'] - ['column[1]_293','column[1]_297','column[1]_301','column[1]_305'] - ['column[1]_309','column[1]_313','column[1]_317','column[1]_321'] - ['column[1]_325','column[1]_329','column[1]_333','column[1]_337','column[1]_341'] - ['column[1]_345','column[1]_349','column[1]_353','column[1]_357','column[1]_361'] - ['column[1]_365','column[1]_369','column[1]_373','column[1]_377'] - ['column[1]_381','column[1]_385','column[1]_389','column[1]_393'] - ['column[1]_397','column[1]_401','column[1]_405','column[1]_409'] - ['column[1]_413','column[1]_417','column[1]_421','column[1]_425','column[1]_429'] - ['column[1]_433','column[1]_437','column[1]_441','column[1]_445','column[1]_449'] - ['column[1]_453','column[1]_457','column[1]_461','column[1]_465'] - ['column[1]_469','column[1]_473','column[1]_477','column[1]_481','column[1]_485'] - ['column[1]_489','column[1]_493','column[1]_497','column[1]_501','column[1]_505'] - ['column[1]_509','column[1]_513','column[1]_517','column[1]_521'] - ['column[1]_525','column[1]_529','column[1]_533','column[1]_537'] - ['column[1]_541','column[1]_545','column[1]_549','column[1]_553'] - ['column[1]_557','column[1]_561','column[1]_565','column[1]_569'] - ['column[1]_573','column[1]_577','column[1]_581','column[1]_585'] - ['column[1]_589','column[1]_593','column[1]_597','column[1]_601','column[1]_605'] - ['column[1]_609','column[1]_613','column[1]_617','column[1]_621','column[1]_625'] - ['column[1]_629','column[1]_633','column[1]_637','column[1]_641','column[1]_645'] - ['column[1]_649','column[1]_653','column[1]_657','column[1]_661','column[1]_665'] - ['column[1]_669','column[1]_673','column[1]_677','column[1]_681','column[1]_685'] - ['column[1]_689','column[1]_693','column[1]_697','column[1]_701'] - ['column[1]_705','column[1]_709','column[1]_713','column[1]_717'] - ['column[1]_721','column[1]_725','column[1]_729','column[1]_733'] - ['column[1]_737','column[1]_741','column[1]_745','column[1]_749'] - ['column[1]_753','column[1]_757','column[1]_761','column[1]_765'] - ['column[1]_769','column[1]_773','column[1]_777','column[1]_781'] - ['column[1]_785','column[1]_789','column[1]_793','column[1]_797'] - ['column[1]_801','column[1]_805','column[1]_809','column[1]_813'] - ['column[1]_817','column[1]_821','column[1]_825','column[1]_829','column[1]_833'] - ['column[1]_837','column[1]_841','column[1]_845'] - -The following is the output result for table b: - -.. code-block:: - - ['column[3]_7','column[3]_11','column[3]_15','column[3]_19','column[3]_23', - 'column[3]_27','column[3]_31','column[3]_35','column[3]_39','column[3]_43', - 'column[3]_47','column[3]_51','column[3]_55','column[3]_59','column[3]_63', - 'column[3]_67','column[3]_71','column[3]_75','column[3]_79','column[3]_83', - 'column[3]_87','column[3]_91','column[3]_95','column[3]_99','column[3]_103', - 'column[3]_107','column[3]_111','column[3]_115','column[3]_119','column[3]_123', - 'column[3]_127','column[3]_131','column[3]_135','column[3]_139','column[3]_143', - 'column[3]_147','column[3]_151','column[3]_155','column[3]_159','column[3]_163', - 'column[3]_167','column[3]_171','column[3]_175','column[3]_179','column[3]_183', - 'column[3]_187','column[3]_191','column[3]_195','column[3]_199','column[3]_203', - 'column[3]_207','column[3]_211','column[3]_215','column[3]_219','column[3]_223', - 'column[3]_227','column[3]_231','column[3]_235','column[3]_239','column[3]_243', - 'column[3]_247','column[3]_251','column[3]_255','column[3]_259','column[3]_263', - 'column[3]_267','column[3]_271','column[3]_275','column[3]_279','column[3]_283', - 'column[3]_287','column[3]_291','column[3]_295','column[3]_299','column[3]_303', - 'column[3]_307','column[3]_311','column[3]_315','column[3]_319','column[3]_323', - 'column[3]_327','column[3]_331','column[3]_335','column[3]_339','column[3]_343', - 'column[3]_347','column[3]_351','column[3]_355','column[3]_359','column[3]_363', - 'column[3]_367','column[3]_371','column[3]_375','column[3]_379','column[3]_383', - 'column[3]_387','column[3]_391','column[3]_395','column[3]_399','column[3]_403', - 'column[3]_407','column[3]_411','column[3]_415','column[3]_419','column[3]_423', - 'column[3]_427','column[3]_431','column[3]_435','column[3]_439','column[3]_443', - 'column[3]_447','column[3]_451','column[3]_455','column[3]_459','column[3]_463', - 'column[3]_467','column[3]_471','column[3]_475','column[3]_479','column[3]_483', - 'column[3]_487','column[3]_491','column[3]_495','column[3]_499','column[3]_503', - 'column[3]_507','column[3]_511','column[3]_515','column[3]_519','column[3]_523', - 'column[3]_527','column[3]_531','column[3]_535','column[3]_539','column[3]_543', - 'column[3]_547','column[3]_551','column[3]_555','column[3]_559','column[3]_563', - 'column[3]_567','column[3]_571','column[3]_575','column[3]_579','column[3]_583', - 'column[3]_587','column[3]_591','column[3]_595','column[3]_599','column[3]_603', - 'column[3]_607','column[3]_611','column[3]_615','column[3]_619','column[3]_623', - 'column[3]_627','column[3]_631','column[3]_635','column[3]_639','column[3]_643', - 'column[3]_647','column[3]_651','column[3]_655','column[3]_659','column[3]_663', - 'column[3]_667','column[3]_671','column[3]_675','column[3]_679','column[3]_683', - 'column[3]_687','column[3]_691','column[3]_695','column[3]_699','column[3]_703', - 'column[3]_707','column[3]_711','column[3]_715','column[3]_719','column[3]_723', - 'column[3]_727','column[3]_731','column[3]_735','column[3]_739','column[3]_743', - 'column[3]_747','column[3]_751','column[3]_755','column[3]_759','column[3]_763', - 'column[3]_767','column[3]_771','column[3]_775','column[3]_779','column[3]_783', - 'column[3]_787','column[3]_791','column[3]_795','column[3]_799','column[3]_803', - 'column[3]_807','column[3]_811','column[3]_815','column[3]_819','column[3]_823', - 'column[3]_827','column[3]_831','column[3]_835','column[3]_839','column[3]_843', - 'column[3]_847'] - -Joining the above tables decompresses table a 844 times and table b 211 times, including ``NULL`` and value columns for each table. Using the table in this example, the longest process was ``DeferredGather.GpuDecompress``, taking 6.7 seconds. \ No newline at end of file From 0aef8983d4be621cca143feb2c6527cd2a7f744d Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:45:07 +0300 Subject: [PATCH 0905/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index 3bfd4a004..00c6679a2 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -4,17 +4,21 @@ Server Picker ************************* -SQream DB's load balancer is called ``server_picker``. - -This page serves as a reference for the options and parameters. +SQreamDB's load balancer is called ``server_picker``. Positional command line arguments =================================== +Syntax +------- + .. code-block:: console $ server_picker [ <Metadata server address> <Metadata server port> [ <TCP listen port> [ <SSL listen port> ] ] +Parameters +------------ + .. list-table:: :widths: auto :header-rows: 1 @@ -34,6 +38,22 @@ Positional command line arguments * - ``SSL listen port`` - ``3109`` - SSL port for server picker to listen on + * - ``server picker services`` + - All services, unless specified otherwise + - Defines which Worker will accept a specific service compilation job. Accepts 1 or more services separated using a comma + * - ``refresh_interval`` + - 15 seconds + - Examines worker availability based on the specified time interval + * - ``logging configuration file`` + - + - Controls the format and destination of log output + +Example +--------- + +.. code-block:: console + + $ server_picker 127.0.0.1 3105 3118 3119 sqream23, sqream0 metadata_log_properties Starting server picker ============================ From c1d5e679331f22a1256911be3bd62a1c29bd6fcd Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:15:53 +0300 Subject: [PATCH 0906/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index 00c6679a2..bdc086c06 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -14,7 +14,7 @@ Syntax .. code-block:: console - $ server_picker [ <Metadata server address> <Metadata server port> [ <TCP listen port> [ <SSL listen port> ] ] + $ server_picker [ <Metadata server address> <Metadata server port> ] [ <TCP listen port> ] [ <SSL listen port> ] [ <server picker services> ] [ <refresh_interval> ] [ <logging configuration file> ] Parameters ------------ @@ -40,12 +40,12 @@ Parameters - SSL port for server picker to listen on * - ``server picker services`` - All services, unless specified otherwise - - Defines which Worker will accept a specific service compilation job. Accepts 1 or more services separated using a comma + - Defines which Worker will accept compilation jobs according to services. Accepts 1 or more services separated using a comma * - ``refresh_interval`` - 15 seconds - Examines worker availability based on the specified time interval * - ``logging configuration file`` - - + - ``log4`` logging to default log path(/tmp/logs) - Controls the format and destination of log output Example From 09f1e85388c7dae65ba251ce029bfcb15de01021 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:48:59 +0300 Subject: [PATCH 0907/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index d6324b517..5f401fa60 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``config/sqload-jdbc.properties`` - Defines the configuration file you wish to use * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 89876bef90d09fa894eaa2bc1b12f3e2b30a7a04 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:50:18 +0300 Subject: [PATCH 0908/1892] Remove Docker Mentions --- .../sqream_installer_cli_ref_admin.rst | 142 ----------------- getting_started/hardware_guide.rst | 2 +- ...mended_pre-installation_configurations.rst | 44 +++++- reference/cli/index.rst | 11 +- reference/cli/sqream_installer.rst | 144 ------------------ reference/cli/sqream_sql.rst | 1 - 6 files changed, 42 insertions(+), 302 deletions(-) delete mode 100644 feature_guides/sqream_installer_cli_ref_admin.rst delete mode 100644 reference/cli/sqream_installer.rst diff --git a/feature_guides/sqream_installer_cli_ref_admin.rst b/feature_guides/sqream_installer_cli_ref_admin.rst deleted file mode 100644 index fad8107b9..000000000 --- a/feature_guides/sqream_installer_cli_ref_admin.rst +++ /dev/null @@ -1,142 +0,0 @@ -.. _sqream_installer_cli_ref_admin: - -********************************* -SQream Installer -********************************* -``sqream-installer`` is an application that prepares and configures a dockerized SQream DB installation. - -This page serves as a reference for the options and parameters. - -.. contents:: In this topic: - :local: - - -Operations and flag reference -=============================== - -Command line flags ------------------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag - - Description - * - ``-i`` - - Loads the docker images for installation - * - ``-k`` - - Load new licenses from the ``license`` subdirectory - * - ``-K`` - - Validate licenses - * - ``-f`` - - Force overwrite any existing installation **and data directories currently in use** - * - ``-c <path to read configuration from>`` - - Specifies a path to read and store configuration files in. Defaults to ``/etc/sqream``. - * - ``-v <storage cluster path>`` - - Specifies a path to the storage cluster. The path is created if it does not exist. - * - ``-l <startup log path>`` - - Specifies a path to store system startup logs. Defaults to ``/var/log/sqream`` - * - ``-d <path>`` - - Specifies a path to expose to SQream DB workers. To expose several paths, repeat the usage of this flag. - * - ``-s`` - - Shows system settings - * - ``-r`` - - Reset the system configuration. This flag can't be combined with other flags. - -Usage -============= - -Install SQream DB for the first time ----------------------------------------- - -Assuming license package tarball has been placed in the ``license`` subfolder. - -* The path where SQream DB will store data is ``/home/rhendricks/sqream_storage``. - -* Logs will be stored in /var/log/sqream - -* Source CSV, Parquet, and ORC files can be accessed from ``/home/rhendricks/source_data``. All other directory paths are hidden from the Docker container. - -.. code-block:: console - - # ./sqream-install -i -k -v /home/rhendricks/sqream_storage -l /var/log/sqream -c /etc/sqream -d /home/rhendricks/source_data - -.. note:: Installation commands should be run with ``sudo`` or root access. - -Modify exposed directories -------------------------------- - -To expose more directory paths for SQream DB to read and write data from, re-run the installer with additional directory flags. - -.. code-block:: console - - # ./sqream-install -d /home/rhendricks/more_source_data - -There is no need to specify the initial installation flags - only the modified exposed directory paths flag. - - -Install a new license package ----------------------------------- - -Assuming license package tarball has been placed in the ``license`` subfolder. - -.. code-block:: console - - # ./sqream-install -k - -View system settings ----------------------------- - -This information may be useful to identify problems accessing directory paths, or locating where data is stored. - -.. code-block:: console - - # ./sqream-install -s - SQREAM_CONSOLE_TAG=1.7.4 - SQREAM_TAG=2020.1 - SQREAM_EDITOR_TAG=3.1.0 - license_worker_0=[...] - license_worker_1=[...] - license_worker_2=[...] - license_worker_3=[...] - SQREAM_VOLUME=/home/rhendricks/sqream_storage - SQREAM_DATA_INGEST=/home/rhendricks/source_data - SQREAM_CONFIG_DIR=/etc/sqream/ - LICENSE_VALID=true - SQREAM_LOG_DIR=/var/log/sqream/ - SQREAM_USER=sqream - SQREAM_HOME=/home/sqream - SQREAM_ENV_PATH=/home/sqream/.sqream/env_file - PROCESSOR=x86_64 - METADATA_PORT=3105 - PICKER_PORT=3108 - NUM_OF_GPUS=8 - CUDA_VERSION=10.1 - NVIDIA_SMI_PATH=/usr/bin/nvidia-smi - DOCKER_PATH=/usr/bin/docker - NVIDIA_DRIVER=418 - SQREAM_MODE=single_host - - -.. _upgrade_with_docker: - -Upgrading to a new version of SQream DB ----------------------------------------------- - -When upgrading to a new version with Docker, most settings don't need to be modified. - -The upgrade process replaces the existing docker images with new ones. - -#. Obtain the new tarball, and untar it to an accessible location. Enter the newly extracted directory. - -#. - Install the new images - - .. code-block:: console - - # ./sqream-install -i - -#. The upgrade process will check for running SQream DB processes. If any are found running, the installer will ask to stop them in order to continue the upgrade process. Once all services are stopped, the new version will be loaded. - -#. After the upgrade, open :ref:`sqream_console_cli_reference` and restart the desired services. \ No newline at end of file diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index ff611cecd..f0a1b2479 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -230,7 +230,7 @@ SQream can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7.9 * CentOS v7.9 * Amazon Linux 2018.03 - * Other Linux distributions may be supported via Nvidia-docker + Storage ------- diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 9e965e221..b1374d131 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -3,6 +3,7 @@ ********************************************* Recommended Pre-Installation Configuration ********************************************* + Before :ref:`installing SQream DB<installing_sqream_db_docker>`, SQream recommends you to tune your system for better performance and stability. This page provides recommendations for production deployments of SQream and describes the following: @@ -13,6 +14,7 @@ This page provides recommendations for production deployments of SQream and desc Recommended BIOS Settings ========================== + The first step when setting your pre-installation configurations is to use the recommended BIOS settings. The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. @@ -86,6 +88,7 @@ If any doubt arises, consult the documentation for your server or your hardware Installing the Operating System =================================================== + Once the BIOS settings have been set, you must install the operating system. Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database, by either the customer or a SQream representative. **To install the operating system:** @@ -120,10 +123,12 @@ The root user is created and the OS shell is booted up. Configuring the Operating System =================================================== + Once you've installted your operation system, you can configure it. When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Logging In to the Server -------------------------------- + You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. Automatically Creating a SQream User @@ -214,6 +219,7 @@ If needed, you can run the **timedatectl list-timezones** command to see your cu Installing the Required Packages -------------------------------- + You can install the required packages by running the following command: .. code-block:: console @@ -223,6 +229,7 @@ You can install the required packages by running the following command: Installing the Recommended Tools -------------------------------- + You can install the recommended tools by running the following command: .. code-block:: console @@ -232,6 +239,7 @@ You can install the recommended tools by running the following command: Installing Python 3.6.7 -------------------------------- + 1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: .. code-block:: console @@ -276,6 +284,7 @@ Installing Python 3.6.7 Installing NodeJS on CentOS -------------------------------- + **To install the node.js on CentOS:** 1. Download the `setup_12.x file <https://rpm.nodesource.com/setup_12.x>`__ as a root user logged in shell: @@ -304,6 +313,7 @@ Installing NodeJS on CentOS Installing NodeJS on Ubuntu -------------------------------- + **To install the node.js file on Ubuntu:** 1. Download the `setup_12.x file <https://deb.nodesource.com/setup_12.x>`__ as a root user logged in shell: @@ -326,6 +336,7 @@ Installing NodeJS on Ubuntu Installing NodeJS Offline ------------------------------------------- + **To install NodeJS Offline** 1. Download the NodeJS source code tarball file from the following URL into the **/home/sqream** directory: @@ -372,6 +383,7 @@ Installing NodeJS Offline Installing the pm2 Service Offline ------------------------------------------- + **To install the pm2 Service Offline** 1. On a machine with internet access, install the following: @@ -425,6 +437,7 @@ Installing the pm2 Service Offline Configuring the Network Time Protocol ------------------------------------------- + This section describes how to configure your **Network Time Protocol (NTP)**. If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. @@ -457,6 +470,7 @@ If you don't have internet access, see `Configure NTP Client to Synchronize with Configuring the Network Time Protocol Server -------------------------------------------- + If your organization has an NTP server, you can configure it. **To configure your NTP server:** @@ -500,6 +514,7 @@ If your organization has an NTP server, you can configure it. Configuring the Server to Boot Without the UI --------------------------------------------- + You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: .. code-block:: console @@ -510,6 +525,7 @@ Running this command activates the **NO-UI** server mode. Configuring the Security Limits -------------------------------- + The security limits refers to the number of open files, processes, etc. You can configure the security limits by running the **echo -e** command as a root user logged in shell: @@ -524,6 +540,7 @@ You can configure the security limits by running the **echo -e** command as a ro Configuring the Kernel Parameters --------------------------------- + **To configure the kernel parameters:** 1. Insert a new line after each kernel parameter: @@ -545,8 +562,6 @@ Configuring the Kernel Parameters .. code-block:: console $ echo "fs.file-max=2097152" >> /etc/sysctl.conf - - **IP4 forward** must be enabled for Docker and K8s installation only. 4. Run the following command: @@ -562,6 +577,7 @@ Configuring the Kernel Parameters Configuring the Firewall -------------------------------- + The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. **To configure the firewall:** @@ -603,6 +619,7 @@ The example in this section shows the open ports for four sqreamd sessions. If m Disabling selinux -------------------------------- + **To disable selinux:** 1. Show the status of **selinux**: @@ -629,6 +646,7 @@ Disabling selinux Configuring the /etc/hosts File -------------------------------- + **To configure the /etc/hosts file:** 1. Edit the **/etc/hosts** file: @@ -647,6 +665,7 @@ Configuring the /etc/hosts File Configuring the DNS -------------------------------- + **To configure the DNS:** 1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: @@ -664,12 +683,14 @@ Configuring the DNS Installing the Nvidia CUDA Driver =================================================== + After configuring your operating system, you must install the Nvidia CUDA driver. .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. CUDA Driver Prerequisites -------------------------------- + 1. Verify that the NVIDIA card has been installed and is detected by the system: .. code-block:: console @@ -698,6 +719,7 @@ CUDA Driver Prerequisites Updating the Kernel Headers -------------------------------- + **To update the kernel headers:** 1. Update the kernel headers on one of the following operating systems: @@ -730,6 +752,7 @@ Updating the Kernel Headers Disabling Nouveau -------------------------------- + You can disable Nouveau, which is the default driver. **To disable Nouveau:** @@ -767,6 +790,7 @@ You can disable Nouveau, which is the default driver. Installing the CUDA Driver -------------------------------- + This section describes how to install the CUDA driver. .. note:: The version of the driver installed on the customer's server must be equal or higher than the driver included in the Sqream release package. Contact a Sqream customer service representative to identify the correct version to install. @@ -779,6 +803,7 @@ The **Installing the CUDA Driver** section describes the following: Installing the CUDA Driver from the Repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Installing the CUDA driver from the Repository is the recommended installation method. .. warning:: For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQream package. For questions related to which driver to install, contact SQream Customer Support. @@ -922,6 +947,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo Tuning Up NVIDIA Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + This section describes how to tune up NVIDIA performance. .. note:: The procedures in this section are relevant to Intel only. @@ -931,7 +957,8 @@ This section describes how to tune up NVIDIA performance. :depth: 1 To Tune Up NVIDIA Performance when Driver Installed from the Repository -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **To tune up NVIDIA performance when the driver was installed from the repository:** 1. Check the service status: @@ -982,7 +1009,8 @@ To Tune Up NVIDIA Performance when Driver Installed from the Repository .. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. To Tune Up NVIDIA Performance when Driver Installed from the Runfile -~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + **To tune up NVIDIA performance when the driver was installed from the runfile:** 1. Change the permissions on the **rc.local** file to **executable**: @@ -1032,6 +1060,7 @@ To Tune Up NVIDIA Performance when Driver Installed from the Runfile Disabling Automatic Bug Reporting Tools ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + **To disable automatic bug reporting tools:** 1. Run the following **abort** commands: @@ -1090,6 +1119,7 @@ The server is ready for the SQream software installation. Enabling Core Dumps =================================================== + After installing the Nvidia CUDA driver, you can enable your core dumps. While SQream recommends enabling your core dumps, it is optional. The **Enabling Core Dumps** section describes the following: @@ -1100,6 +1130,7 @@ The **Enabling Core Dumps** section describes the following: Checking the abrtd Status --------------------------------------------------- + **To check the abrtd status:** 1. Check if **abrtd** is running: @@ -1121,6 +1152,7 @@ Checking the abrtd Status Setting the Limits --------------------------------------------------- + **To set the limits:** 1. Set the limits: @@ -1140,6 +1172,7 @@ Setting the Limits Creating the Core Dumps Directory --------------------------------------------------- + **To set the core dumps directory:** 1. Make the **/tmp/core_dumps** directory: @@ -1164,6 +1197,7 @@ Creating the Core Dumps Directory Setting the Output Directory of the /etc/sysctl.conf File ----------------------------------------------------------------- + **To set the output directory of the /etc/sysctl.conf file:** 1. Edit the **/etc/sysctl.conf** file: @@ -1206,6 +1240,7 @@ Setting the Output Directory of the /etc/sysctl.conf File Verifying that the Core Dumps Work --------------------------------------------------- + You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** **To verify that the core dumps work:** @@ -1222,6 +1257,7 @@ You can verify that the core dumps work only after installing and running SQream Troubleshooting Core Dumping --------------------------------------------------- + This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. **To troubleshoot core dumping:** diff --git a/reference/cli/index.rst b/reference/cli/index.rst index d892ffea6..542c6960b 100644 --- a/reference/cli/index.rst +++ b/reference/cli/index.rst @@ -41,16 +41,7 @@ This topic contains the reference for these programs, as well as flags and confi * - :ref:`upgrade_storage <upgrade_storage_cli_reference>` - Upgrade metadata schemas when upgrading between major versions -.. list-table:: Docker utilities - :widths: auto - :header-rows: 1 - - * - Command - - Usage - * - :ref:`sqream_console <sqream_console_cli_reference>` - - Dockerized convenience wrapper for operations - * - :ref:`sqream_installer <sqream_installer_cli_reference>` - - Dockerized installer + .. toctree:: :maxdepth: 1 diff --git a/reference/cli/sqream_installer.rst b/reference/cli/sqream_installer.rst deleted file mode 100644 index cdd9e801a..000000000 --- a/reference/cli/sqream_installer.rst +++ /dev/null @@ -1,144 +0,0 @@ -.. _sqream_installer_cli_reference: - -********************************* -sqream-installer -********************************* - -``sqream-installer`` is an application that prepares and configures a dockerized SQream DB installation. - - -This page serves as a reference for the options and parameters. - -.. contents:: In this topic: - :local: - - -Operations and flag reference -=============================== - -Command line flags ------------------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag - - Description - * - ``-i`` - - Loads the docker images for installation - * - ``-k`` - - Load new licenses from the ``license`` subdirectory - * - ``-K`` - - Validate licenses - * - ``-f`` - - Force overwrite any existing installation **and data directories currently in use** - * - ``-c <path to read configuration from>`` - - Specifies a path to read and store configuration files in. Defaults to ``/etc/sqream``. - * - ``-v <storage cluster path>`` - - Specifies a path to the storage cluster. The path is created if it does not exist. - * - ``-l <startup log path>`` - - Specifies a path to store system startup logs. Defaults to ``/var/log/sqream`` - * - ``-d <path>`` - - Specifies a path to expose to SQream DB workers. To expose several paths, repeat the usage of this flag. - * - ``-s`` - - Shows system settings - * - ``-r`` - - Reset the system configuration. This flag can't be combined with other flags. - -Usage -============= - -Install SQream DB for the first time ----------------------------------------- - -Assuming license package tarball has been placed in the ``license`` subfolder. - -* The path where SQream DB will store data is ``/home/rhendricks/sqream_storage``. - -* Logs will be stored in /var/log/sqream - -* Source CSV, Parquet, and ORC files can be accessed from ``/home/rhendricks/source_data``. All other directory paths are hidden from the Docker container. - -.. code-block:: console - - # ./sqream-install -i -k -v /home/rhendricks/sqream_storage -l /var/log/sqream -c /etc/sqream -d /home/rhendricks/source_data - -.. note:: Installation commands should be run with ``sudo`` or root access. - -Modify exposed directories -------------------------------- - -To expose more directory paths for SQream DB to read and write data from, re-run the installer with additional directory flags. - -.. code-block:: console - - # ./sqream-install -d /home/rhendricks/more_source_data - -There is no need to specify the initial installation flags - only the modified exposed directory paths flag. - - -Install a new license package ----------------------------------- - -Assuming license package tarball has been placed in the ``license`` subfolder. - -.. code-block:: console - - # ./sqream-install -k - -View system settings ----------------------------- - -This information may be useful to identify problems accessing directory paths, or locating where data is stored. - -.. code-block:: console - - # ./sqream-install -s - SQREAM_CONSOLE_TAG=1.7.4 - SQREAM_TAG=2020.1 - SQREAM_EDITOR_TAG=3.1.0 - license_worker_0=[...] - license_worker_1=[...] - license_worker_2=[...] - license_worker_3=[...] - SQREAM_VOLUME=/home/rhendricks/sqream_storage - SQREAM_DATA_INGEST=/home/rhendricks/source_data - SQREAM_CONFIG_DIR=/etc/sqream/ - LICENSE_VALID=true - SQREAM_LOG_DIR=/var/log/sqream/ - SQREAM_USER=sqream - SQREAM_HOME=/home/sqream - SQREAM_ENV_PATH=/home/sqream/.sqream/env_file - PROCESSOR=x86_64 - METADATA_PORT=3105 - PICKER_PORT=3108 - NUM_OF_GPUS=8 - CUDA_VERSION=10.1 - NVIDIA_SMI_PATH=/usr/bin/nvidia-smi - DOCKER_PATH=/usr/bin/docker - NVIDIA_DRIVER=418 - SQREAM_MODE=single_host - - -.. _upgrade_with_docker: - -Upgrading to a new version of SQream DB ----------------------------------------------- - -When upgrading to a new version with Docker, most settings don't need to be modified. - -The upgrade process replaces the existing docker images with new ones. - -#. Obtain the new tarball, and untar it to an accessible location. Enter the newly extracted directory. - -#. - Install the new images - - .. code-block:: console - - # ./sqream-install -i - -#. The upgrade process will check for running SQream DB processes. If any are found running, the installer will ask to stop them in order to continue the upgrade process. Once all services are stopped, the new version will be loaded. - -#. After the upgrade, open :ref:`sqream_console_cli_reference` and restart the desired services. \ No newline at end of file diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index b9feff992..132f9679c 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -16,7 +16,6 @@ Installing Sqream SQL If you have a SQream DB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. -.. note:: If you installed SQream DB via Docker, the command is named ``sqream-client sql``, and can be found in the same location as the console. .. versionchanged:: 2020.1 From 37f9be369dfaf444bfafa8c06d8a1be35c2c628d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:54:19 +0300 Subject: [PATCH 0909/1892] Update index.rst --- reference/cli/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/reference/cli/index.rst b/reference/cli/index.rst index 542c6960b..588e8d54a 100644 --- a/reference/cli/index.rst +++ b/reference/cli/index.rst @@ -50,7 +50,6 @@ This topic contains the reference for these programs, as well as flags and confi metadata_server sqreamd sqream_console - sqream_installer server_picker sqream_storage sqream sql<sqream_sql> From 90888583d5a0155f89b4a74c91d30da170c8c6bc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:37:14 +0300 Subject: [PATCH 0910/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 40f34d659..3a855c9f6 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **JDBC** - - `sqream-jdbc 4.5.9 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-4.5.9.jar>`_ + - `sqream-jdbc 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **Python** - - `pysqream v3.2.5 <https://github.com/SQream/pysqream/releases/tag/v3.2.5>`_ + - `pysqream v5.0.0 <https://github.com/SQream/pysqream/releases/tag/v5.0.0>`_ - :ref:`pysqream` - Recommended installation via ``pip`` - All From 1a2999fc6ee60114f9f7b1eae1747bd3e36216b5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:48:04 +0300 Subject: [PATCH 0911/1892] Update 4.4.rst --- releases/4.4.rst | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 73e22ac6d..411635f3e 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -23,11 +23,11 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 49 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 4.5.8 | +| Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | -| | * Pysqream 3.2.5 | +| | * Pysqream 5.0.0 | | | * Spark | +-------------------------+------------------------------------------------------------------------+ @@ -36,6 +36,19 @@ New Features and Enhancements :ref:`denodo` may now be used for data visualization and real-time visualization of various sources. +Newly Released Connector Drivers +--------------------------------- + +► **Pysqream 5.0.0** + +* `tar.file <https://github.com/SQream/pysqream/releases/tag/v5.0.0>`_ +* :ref:`Documentation<pysqream>` + +► **JDBC 5.0.0** + +* `jar.file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ +* :ref:`Documentation<java_jdbc>` + Known Issues ------------ From ffcc7eae7e54e47154b682d796d36de546568a38 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Sep 2023 14:52:09 +0300 Subject: [PATCH 0912/1892] 5.0.0 JDBC + Pysqream --- connecting_to_sqream/client_drivers/jdbc/index.rst | 6 +++--- connecting_to_sqream/client_drivers/python/index.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index ef56dc1c6..618d415b7 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -45,18 +45,18 @@ Setting Up the Class Path To use the driver, you must include the JAR named ``sqream-jdbc-<version>.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-4.3.0.jar``, the following command is used to run application: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-5.0.0.jar``, the following command is used to run application: .. code-block:: console - $ export CLASSPATH=/home/sqream/sqream-jdbc-4.3.0.jar:$CLASSPATH + $ export CLASSPATH=/home/sqream/sqream-jdbc-5.0.0.jar:$CLASSPATH $ java my_java_app Alternatively, you can pass ``-classpath`` to the Java executable file: .. code-block:: console - $ java -classpath .:/home/sqream/sqream-jdbc-4.3.0.jar my_java_app + $ java -classpath .:/home/sqream/sqream-jdbc-5.0.0.jar my_java_app Connecting to SQream Using a JDBC Application ============================================= diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 9ff4b7920..18d3489bd 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -105,11 +105,11 @@ Installing via PIP without an internet connection .. code-block:: console - tar -xf pysqream_connector_3.2.5.tar.gz - cd pysqream_connector_3.2.5 + tar -xf pysqream_connector_5.0.0.tar.gz + cd pysqream_connector_5.0.0 #Install all packages with --no-index --find-links . python3 -m pip install *.whl -U --no-index --find-links . - python3.9 -m pip install pysqream-3.2.5.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-5.0.0.zip -U --no-index --find-links . python3.9 -m pip install pysqream-sqlalchemy-0.8.zip -U --no-index --find-links . Upgrading an Existing Installation From 417d00e3d2f72b04ead829230691979cab406912 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Wed, 27 Sep 2023 15:26:04 +0300 Subject: [PATCH 0913/1892] Encryption --- feature_guides/data_encryption.rst | 40 ------------------- feature_guides/data_encryption_methods.rst | 17 -------- .../data_encryption_permissions.rst | 6 --- feature_guides/data_encryption_syntax.rst | 32 --------------- feature_guides/data_encryption_types.rst | 14 ------- feature_guides/index.rst | 1 - 6 files changed, 110 deletions(-) delete mode 100644 feature_guides/data_encryption.rst delete mode 100644 feature_guides/data_encryption_methods.rst delete mode 100644 feature_guides/data_encryption_permissions.rst delete mode 100644 feature_guides/data_encryption_syntax.rst delete mode 100644 feature_guides/data_encryption_types.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst deleted file mode 100644 index b05ad6cbd..000000000 --- a/feature_guides/data_encryption.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. _data_encryption: - -*************** -Data Encryption -*************** - -**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - -Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. - -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. - -Encryption can be used for the following: - -* Creating tables with up to three encrypted columns. - - :: - -* Joining encrypted columns with other tables. - - :: - -* Selecting data from an encrypted column. - -.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT`` or ``INSERT INTO TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. - -For more information on the encryption syntax, see :ref:`data_encryption_syntax`. - -For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. - -.. rubric:: In This Section: - -.. toctree:: - :maxdepth: 1 - :titlesonly: - - data_encryption_methods - data_encryption_types - data_encryption_syntax - data_encryption_permissions \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst deleted file mode 100644 index db789d02f..000000000 --- a/feature_guides/data_encryption_methods.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _data_encryption_methods: - -*********************** -Encryption Methods -*********************** -Data exists in one of following states and determines the encryption method: - - -Encrypting Data in Transit ----------------- -**Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. - -For more information, see `Use TLS/SSL When Possible <https://docs.sqream.com/en/v2022.1/operational_guides/security.html#use-tls-ssl-when-possible>`_. - -Encrypting Data at Rest ----------------- -**Data at rest** refers to data stored on your hard drive or on the cloud. Because this data can be potentially intercepted **physically**, it requires a form of encryption that protects your data wherever you store it. SQream faciliates encryption by letting you encrypt any columns located in your database that you want to keep private. \ No newline at end of file diff --git a/feature_guides/data_encryption_permissions.rst b/feature_guides/data_encryption_permissions.rst deleted file mode 100644 index ba51f2501..000000000 --- a/feature_guides/data_encryption_permissions.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. _data_encryption_permissions: - -*********************** -Permissions -*********************** -Because the Data Encryption feature does not require a role, users with **Read** and **Insert** permissions can read tables containing encrypted data. \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst deleted file mode 100644 index 56934378e..000000000 --- a/feature_guides/data_encryption_syntax.rst +++ /dev/null @@ -1,32 +0,0 @@ -.. _data_encryption_syntax: - -*********************** -Syntax -*********************** -The following is the syntax for encrypting a new table: - -.. code-block:: console - - CREATE TABLE <table name> ( - <column_name> NOT NULL ENCRYPT, - <column_name> <type_name> ENCRYPT, - <column_name> <type_name>, - <column_name> <type_name> ENCRYPT); - -The following is an example of encrypting a new table: - -.. code-block:: console - - CREATE TABLE client_name ( - id BIGINT NOT NULL ENCRYPT, - first_name TEXT ENCRYPT, - last_name TEXT, - salary INT ENCRYPT); - -.. note:: Because encryption is not associated with any role, users with **Read** or **Insert** permissions can read tables containing encrypted data. - -You cannot encrypt more than three columns. Attempting to encrypt more than three columns displays the following error message: - -.. code-block:: console - - Error preparing statement: Cannot create a table with more than three encrypted columns. diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst deleted file mode 100644 index ad6d96dc3..000000000 --- a/feature_guides/data_encryption_types.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _data_encryption_types: - -*********************** -Data Types -*********************** -Typically speaking, sensitive pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - -SQream's data encryption feature supports encrypting column-based data belonging to the following data types: - -* INT -* BIGINT -* TEXT - -For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index e1c1e5118..8f0a2fe3f 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -12,7 +12,6 @@ The **Feature Guides** section describes background processes that SQreamDB uses automatic_foreign_table_ddl_resolution query_healer - data_encryption compression python_functions workload_manager From b7b0e852b565332107eda3c7a77cd047bca6891e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 27 Sep 2023 15:30:32 +0300 Subject: [PATCH 0914/1892] Update pentaho.rst --- connecting_to_sqream/client_platforms/pentaho.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst index 7b3423afd..26ea788cb 100644 --- a/connecting_to_sqream/client_platforms/pentaho.rst +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -42,8 +42,6 @@ After installing Pentaho you must install and set up the JDBC driver. This secti You can install the driver by copying and pasting the SQream JDBC .jar file into your **<directory>/design-tools/data-integration/lib** directory. -**NOTE:** Contact your SQream license account manager for the JDBC .jar file. - :ref:`Back to Overview <pentaho_top>` .. _create_transformation: @@ -248,4 +246,4 @@ For more information about backing up users, permissions, or schedules, see `Bac The **Execution Results** are displayed. -:ref:`Back to Overview <pentaho_top>` \ No newline at end of file +:ref:`Back to Overview <pentaho_top>` From 650613efb5c66b5f45ad0b13ae12990e3856bea9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 28 Sep 2023 12:14:47 +0300 Subject: [PATCH 0915/1892] 4.4 RN --- releases/4.0_index.rst | 4 ++-- releases/4.4.rst | 18 ++++++++++-------- releases/index.rst | 7 ++++++- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 8b40fcbd6..396ca0d11 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -1,10 +1,10 @@ .. _4.0_index: ***************** -Release Notes 4.0 +4.0 Release Notes ***************** -The 4.0 Release Notes describe the following releases: + .. contents:: :local: diff --git a/releases/4.4.rst b/releases/4.4.rst index 411635f3e..7ca7f0c23 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -4,7 +4,7 @@ Release Notes 4.4 ***************** -The 4.4 release notes were released on xx/xx/xxxx and describe the following: +The 4.4 release notes were released on September 28th, 2023 .. contents:: :local: @@ -34,7 +34,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -:ref:`denodo` may now be used for data visualization and real-time visualization of various sources. +► The newly supported :ref:`sql_data_type_array` data type enables you to simplify queries and optimize space utilization. + +► :ref:`denodo` may now be used for real-time data visualization of various sources. Newly Released Connector Drivers --------------------------------- @@ -113,7 +115,7 @@ Deprecations ► ``INT96`` -Due to Parquet's lack of support of the ``INT96`` data type, SQream has decided to deprecate this data type. +Due to Parquet's lack of support of the ``INT96`` data type, SQreamDB has decided to deprecate this data type. ► Square Brackets ``[]`` @@ -133,17 +135,17 @@ Upgrading to Version 4.4 $ select backup_metadata('out_path'); - .. tip:: SQream recommends storing the generated back-up locally in case needed. + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. - SQream runs the Garbage Collector and creates a clean backup tarball package. + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. -2. Shut down all SQream services. +2. Shut down all SQreamDB services. 3. Copy the recently created back-up file. 4. Replace your current metadata with the metadata you stored in the back-up file. -5. Navigate to the new SQream package bin folder. +5. Navigate to the new SQreamDB package bin folder. 6. Run the following command: @@ -159,5 +161,5 @@ There are two methods of granting back access to services: * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. diff --git a/releases/index.rst b/releases/index.rst index 2e13d5e85..ff2f162da 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,9 +4,14 @@ Release Notes ************* +:ref:`Version 4.4 - September 28, 2023<4.4>` + +* `Enhancing storage efficiency and performance with the newly supported ARRAY data type <https://docs.sqream.com/en/latest/releases/4.4.html#new-features-and-enhancements>`_ +* `New integration with Denodo Platform <https://docs.sqream.com/en/latest/releases/4.4.html#new-features-and-enhancements>`_ + :ref:`Version 4.3 - June 11, 2023<4.3>` -* `Access Control Permissions Expansion <https://docs.sqream.com/en/latest/releases/4.3.html#new-features-and-enhancements>`_ +* `Access Control Permission Expansion <https://docs.sqream.com/en/latest/releases/4.3.html#new-features-and-enhancements>`_ * `New AWS S3 Access Configurations <https://docs.sqream.com/en/latest/releases/4.3.html#configuration-adjustments>`_ :ref:`Version 4.2 - April 23, 2023<4.2>` From 6c7f1b3f5806f8d39cf6b9135cecc6ce91aff485 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:06:26 +0300 Subject: [PATCH 0916/1892] 4.4 RN --- releases/4.4.rst | 32 ++++---- releases/4.5 | 191 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 14 deletions(-) create mode 100644 releases/4.5 diff --git a/releases/4.4.rst b/releases/4.4.rst index 7ca7f0c23..76607f31f 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -65,35 +65,37 @@ Version 4.4 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+================================================================================================+ -| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | +| SQ-12965 | ``ReadParquet`` chunk producer issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13112 | ``GRANT`` query queue issue | +| SQ-13461 | ``LEFT JOIN`` in the ``WHERE`` clause with different date values results in missing filters | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | +| SQ-13772 | Foreign table ``JOIN`` operation issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13210, SQ-13426 | Slow query execution time | +| SQ-13805 | Different table structures provide different query times when using Parquet files | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13322 | Cleanup operation case-sensitivity issue | +| SQ-13947 | Unicode character issue when using Tableau | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | +| SQ-13954 | Runtime error when granting role multiple permissions using the web interface | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13453 | Metadata performance issue | +| SQ-13971 | Parquet file data loading issue when columns contain over 100,000 digits | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | +| SQ-14136 | Query deceleration due to metadata server issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13587 | Large number of worker connections failure | +| SQ-14268 | ``TEXT`` column length calculation CUDA memory issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13467 | Snapshot issue causes metadata failure | +| SQ-14399 | Figment snapshot recognition issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-11804 | Slow metadata optimization | +| SQ-14400 | Healer configuration flag unavailability | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | +| SQ-14556 | Object store path issue when using S3 API | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12799 | Catalog queries may not be terminated | +| SQ-14724 | Aliases error when using ``DELETE`` statement | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | +| SQ-15074 | Web interface login issue for non-``SUPERUSER`` roles | +--------------------+------------------------------------------------------------------------------------------------+ + + Configuration Adjustments ------------------------- @@ -104,6 +106,8 @@ Visit :ref:`s3` to learn more about how and when you should use these two new pa * ``AwsEndpointOverride`` * ``AwsObjectAccessStyle`` +► New :ref:`server_picker_cli_reference` parameters enable you to direct services to specific Workers and examine Worker availability. + Deprecations ------------------- diff --git a/releases/4.5 b/releases/4.5 new file mode 100644 index 000000000..6d129d0e6 --- /dev/null +++ b/releases/4.5 @@ -0,0 +1,191 @@ +.. _4.5: + +***************** +Release Notes 4.5 +***************** + +The 4.5 release notes were released on XXXXXXXXXXX + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 49 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.0.0 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 5.0.0 | +| | * Spark | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- + +► The newly supported :ref:`sql_data_type_array` data type enables you to simplify queries and optimize space utilization. + +► :ref:`denodo` may now be used for real-time data visualization of various sources. + +Newly Released Connector Drivers +--------------------------------- + +► **Pysqream 5.0.0** + +* `tar.file <https://github.com/SQream/pysqream/releases/tag/v5.0.0>`_ +* :ref:`Documentation<pysqream>` + +► **JDBC 5.0.0** + +* `jar.file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ +* :ref:`Documentation<java_jdbc>` + +Known Issues +------------ + +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. + +* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression + + +Version 4.4 resolved Issues +--------------------------- + ++--------------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+================================================================================================+ +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-11804 | Slow metadata optimization | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12799 | Catalog queries may not be terminated | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12965 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13210, SQ-13426 | Slow query execution time | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation case-sensitivity issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13453 | Metadata performance issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13461 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number of worker connections failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13772 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13805 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13947 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13954 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13971 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-14094 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-14136 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-14268 +| SQ-14399 +| SQ-14400 +| SQ-14556 +| SQ-14724 +| SQ-15074 + + + +Configuration Adjustments +------------------------- + +► You may now configure the object access style and your endpoint URL with Virtual Private Cloud (VPC) when using AWS S3. + +Visit :ref:`s3` to learn more about how and when you should use these two new parameters: + +* ``AwsEndpointOverride`` +* ``AwsObjectAccessStyle`` + +Deprecations +------------------- + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. +* **CentOS Linux 8.x** is now officially supported. + +► ``INT96`` + +Due to Parquet's lack of support of the ``INT96`` data type, SQreamDB has decided to deprecate this data type. + + +► Square Brackets ``[]`` + +The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, are officially deprecated to facilitate the use of the ``ARRAY`` data type. To delimit database object identifiers, use double quotes ``""``. + + +► ``VARCHAR`` + +With the improvement of the core functionalities of the platform and to align with the constantly evolving ecosystem requirements, the ``VARCHAR`` data type is deprecated and may not be used. The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. + +Upgrading to Version 4.4 +------------------------- +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 95e3bc1ef97fd825a601dad19c3b2462d2db8bcf Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:02:26 +0300 Subject: [PATCH 0917/1892] Update 4.4.rst --- releases/4.4.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 76607f31f..2cd761e4a 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -56,8 +56,6 @@ Known Issues * :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. -* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression - Version 4.4 resolved Issues --------------------------- @@ -114,8 +112,8 @@ Deprecations ► **CentOS Linux 7.x** * As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. -* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. -* **CentOS Linux 8.x** is now officially supported. +* All new SQreamDB installations must use RHEL 8.X as the required operating system platform. +* **RHEL 8.x** is now officially supported. ► ``INT96`` From b298f78a5eb9b1e722d513990707a87216d8c4ff Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:29:40 +0300 Subject: [PATCH 0918/1892] Update index.rst --- data_type_guides/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/index.rst b/data_type_guides/index.rst index 910ad0afb..84678b7dc 100644 --- a/data_type_guides/index.rst +++ b/data_type_guides/index.rst @@ -10,6 +10,6 @@ This section describes the following: :maxdepth: 1 :glob: - converting_and_casting_types supported_data_types - supported_casts \ No newline at end of file + converting_and_casting_types + supported_casts From 3399528b76b494caefe85eca376fcd4424eead44 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:31:39 +0300 Subject: [PATCH 0919/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 09c7656b4..10a34aaec 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -11,7 +11,7 @@ Supported Data Types sql_data_type_array -The following table shows the supported data types. +SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. .. list-table:: :widths: 20 15 20 30 20 @@ -82,5 +82,3 @@ The following table shows the supported data types. - Variable - ``[1,2,3]`` - NA - -.. note:: SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. From c70c39d3f748facf7b9e6c6db0ac294faaf60413 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:35:46 +0300 Subject: [PATCH 0920/1892] Create sql_data_types_primitives.rst --- .../sql_data_types_primitives.rst | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 data_type_guides/sql_data_types_primitives.rst diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst new file mode 100644 index 000000000..44aed3378 --- /dev/null +++ b/data_type_guides/sql_data_types_primitives.rst @@ -0,0 +1,69 @@ +.. list-table:: + :widths: 20 15 20 30 20 + :header-rows: 1 + + * - Name + - Description + - Data Size (Not Null, Uncompressed) + - Example + - Alias + * - ``BOOL`` + - Boolean values (``true``, ``false``) + - 1 byte + - ``true`` + - ``BIT`` + * - ``TINYINT`` + - Unsigned integer (0 - 255) + - 1 byte + - ``5`` + - NA + * - ``SMALLINT`` + - Integer (-32,768 - 32,767) + - 2 bytes + - ``-155`` + - NA + * - ``INT`` + - Integer (-2,147,483,648 - 2,147,483,647) + - 4 bytes + - ``1648813`` + - ``INTEGER`` + * - ``BIGINT`` + - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) + - 8 bytes + - ``36124441255243`` + - ``NUMBER`` + * - ``REAL`` + - Floating point (inexact) + - 4 bytes + - ``3.141`` + - NA + * - ``DOUBLE`` + - Floating point (inexact) + - 8 bytes + - ``0.000003`` + - ``FLOAT``/``DOUBLE PRECISION`` + * - ``TEXT (n)`` + - Variable length string - UTF-8 unicode + - Up to ``4`` bytes + - ``'Kiwis have tiny wings, but cannot fly.'`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING`` + * - ``NUMERIC`` + - 38 digits + - 16 bytes + - ``0.12324567890123456789012345678901234567`` + - ``DECIMAL`` + * - ``DATE`` + - Date + - 4 bytes + - ``'1955-11-05'`` + - NA + * - ``DATETIME`` + - Date and time pairing in UTC + - 8 bytes + - ``'1955-11-05 01:24:00.000'`` + - ``TIMESTAMP``, ``DATETIME2`` + * - ``ARRAY`` + - Array of values + - Variable + - ``[1,2,3]`` + - NA From f503da850036ce538b8f5c1ae0465a8d571e0a91 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:36:08 +0300 Subject: [PATCH 0921/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 74 +---------------------- 1 file changed, 3 insertions(+), 71 deletions(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 10a34aaec..03ac1755e 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -7,78 +7,10 @@ Supported Data Types .. toctree:: :maxdepth: 1 :glob: - :hidden: - + + + sql_data_types_primitives sql_data_type_array SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. -.. list-table:: - :widths: 20 15 20 30 20 - :header-rows: 1 - - * - Name - - Description - - Data Size (Not Null, Uncompressed) - - Example - - Alias - * - ``BOOL`` - - Boolean values (``true``, ``false``) - - 1 byte - - ``true`` - - ``BIT`` - * - ``TINYINT`` - - Unsigned integer (0 - 255) - - 1 byte - - ``5`` - - NA - * - ``SMALLINT`` - - Integer (-32,768 - 32,767) - - 2 bytes - - ``-155`` - - NA - * - ``INT`` - - Integer (-2,147,483,648 - 2,147,483,647) - - 4 bytes - - ``1648813`` - - ``INTEGER`` - * - ``BIGINT`` - - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - - 8 bytes - - ``36124441255243`` - - ``NUMBER`` - * - ``REAL`` - - Floating point (inexact) - - 4 bytes - - ``3.141`` - - NA - * - ``DOUBLE`` - - Floating point (inexact) - - 8 bytes - - ``0.000003`` - - ``FLOAT``/``DOUBLE PRECISION`` - * - ``TEXT (n)`` - - Variable length string - UTF-8 unicode - - Up to ``4`` bytes - - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING`` - * - ``NUMERIC`` - - 38 digits - - 16 bytes - - ``0.12324567890123456789012345678901234567`` - - ``DECIMAL`` - * - ``DATE`` - - Date - - 4 bytes - - ``'1955-11-05'`` - - NA - * - ``DATETIME`` - - Date and time pairing in UTC - - 8 bytes - - ``'1955-11-05 01:24:00.000'`` - - ``TIMESTAMP``, ``DATETIME2`` - * - ``ARRAY`` - - Array of values - - Variable - - ``[1,2,3]`` - - NA From 72d455af3e29cb985cea1fb908ee72be4d8eeba4 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:41:41 +0300 Subject: [PATCH 0922/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 03ac1755e..efbc58243 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -4,6 +4,10 @@ Supported Data Types ******************** + + +SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. + .. toctree:: :maxdepth: 1 :glob: @@ -11,6 +15,3 @@ Supported Data Types sql_data_types_primitives sql_data_type_array - -SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. - From 0e9400d536b941348ac82c58b72fed0f9d1a43e3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:50:32 +0300 Subject: [PATCH 0923/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index efbc58243..31a4ef821 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -6,7 +6,7 @@ Supported Data Types -SQream compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. +SQreamDB compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. .. toctree:: :maxdepth: 1 From 8c3f483b2ffad8a9508b30ba7ac88543d393ea19 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:52:09 +0300 Subject: [PATCH 0924/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index 44aed3378..68496cb86 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -1,3 +1,9 @@ +.. _sql_data_type_primitives: + +******************** +Primitive Data Types +******************** + .. list-table:: :widths: 20 15 20 30 20 :header-rows: 1 From b69fbfc9eaac691aa2ff0ecd722726f7fc0b6a6c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 09:57:17 +0300 Subject: [PATCH 0925/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index 68496cb86..f5fa85354 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -1,4 +1,4 @@ -.. _sql_data_type_primitives: +.. _sql_data_types_primitives: ******************** Primitive Data Types From 32a36cb2b1a47de47ffd40feace3d2c09f1876d5 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:04:17 +0300 Subject: [PATCH 0926/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index f5fa85354..58c1716d4 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -68,8 +68,4 @@ Primitive Data Types - 8 bytes - ``'1955-11-05 01:24:00.000'`` - ``TIMESTAMP``, ``DATETIME2`` - * - ``ARRAY`` - - Array of values - - Variable - - ``[1,2,3]`` - - NA + From e6d0e732d3757599b3fee1c87fb3bea4e3a5d861 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:10:24 +0300 Subject: [PATCH 0927/1892] Update supported_data_types.rst --- data_type_guides/supported_data_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/supported_data_types.rst b/data_type_guides/supported_data_types.rst index 31a4ef821..26951cee9 100644 --- a/data_type_guides/supported_data_types.rst +++ b/data_type_guides/supported_data_types.rst @@ -4,9 +4,9 @@ Supported Data Types ******************** +Data types define the type of data that a column can hold in a table. They ensure that data is handled accurately and efficiently. Common data types include integers, decimals, characters, and dates. For example, an ``INT`` data type is used for whole numbers, ``TEXT`` for variable-length character strings, and ``DATE`` for date values. -SQreamDB compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. .. toctree:: :maxdepth: 1 From 3dfb99f137b54cb08508a13e279827f0b513c942 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:10:37 +0300 Subject: [PATCH 0928/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index 58c1716d4..7a76dbe8e 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -4,6 +4,8 @@ Primitive Data Types ******************** +SQreamDB compresses all columns and types. The data size noted is the maximum data size allocation for uncompressed data. + .. list-table:: :widths: 20 15 20 30 20 :header-rows: 1 From a7c74038555f16b6b4702e41897b5c8d40aa4dbc Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Oct 2023 11:25:53 +0300 Subject: [PATCH 0929/1892] remove sqream_catalog.sequences --- reference/catalog_reference_catalog_tables.rst | 12 ------------ reference/catalog_reference_schema_information.rst | 2 -- 2 files changed, 14 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index e771b9697..4ad9a916f 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -364,18 +364,6 @@ The ``schemas`` data object identifies all the database's schemas, as shown belo * - ``rechunker_ignore`` - Reserved for internal use. -.. _sequences: - -Sequences ----------------- - -The ``sequences`` data object is used for displaying identity key information, as shown below: - -Identity Key -************* - -**Comment** - *No content.* - .. _tables: Tables diff --git a/reference/catalog_reference_schema_information.rst b/reference/catalog_reference_schema_information.rst index f91607dfa..be669999d 100644 --- a/reference/catalog_reference_schema_information.rst +++ b/reference/catalog_reference_schema_information.rst @@ -35,8 +35,6 @@ The following table shows the data objects contained in the ``sqream_catalog`` s - ``roles``, ``roles_memeberships`` * - :ref:`Schemas<schemas>` - ``schemas`` - * - :ref:`Sequences<sequences>` - - ``identity_key`` * - :ref:`Tables<tables>` - ``tables``, ``external_tables`` * - :ref:`Views<views>` From 90af6b592aaf9bcca66a90f44afd6b3964e6da03 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Oct 2023 08:25:51 +0300 Subject: [PATCH 0930/1892] Remove Kubernetes --- getting_started/installing_sqream.rst | 6 +----- .../installing_studio_on_stand_alone_server.rst | 4 +--- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/getting_started/installing_sqream.rst b/getting_started/installing_sqream.rst index fef12ab36..09eefed8b 100644 --- a/getting_started/installing_sqream.rst +++ b/getting_started/installing_sqream.rst @@ -4,8 +4,6 @@ Installing SQreamDB ******************* -You may choose one of the following installation methods: - .. list-table:: :widths: auto :header-rows: 1 @@ -13,6 +11,4 @@ You may choose one of the following installation methods: * - Method - Description * - :ref:`Installing SQreamDB natively <installing_sqream_with_binary>` - - Describes installing SQreamDB using binary packages provided by SQreamDB - * - :ref:`Installing SQreamDB with Kubernetes <installing_sqream_with_kubernetes>` - - Describes installing SQreamDB using the Kubernetes open source platform + - Describes installing SQreamDB using binary packages provided by SQreamDB \ No newline at end of file diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 6c6c2e05a..ad7802732 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -5,9 +5,7 @@ *********************** Installing Studio on a Stand-Alone Server *********************** -A stand-alone server is a server that does not run SQream based on binary files or Kubernetes. - -The Installing Studio on a Stand-Alone Server guide includes the following sections: +A stand-alone server is a server that does not run SQreamDB based on binary files. .. contents:: :local: From aad7763d0db37c1f858c78a5114ebb1f6d86e92d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Oct 2023 09:05:56 +0300 Subject: [PATCH 0931/1892] S3 page alignment --- external_storage_platforms/hdfs.rst | 2 +- external_storage_platforms/s3.rst | 76 ++++++++--------------------- 2 files changed, 20 insertions(+), 58 deletions(-) diff --git a/external_storage_platforms/hdfs.rst b/external_storage_platforms/hdfs.rst index a6ffe0ead..99bb465ea 100644 --- a/external_storage_platforms/hdfs.rst +++ b/external_storage_platforms/hdfs.rst @@ -2,7 +2,7 @@ .. _back_to_top_hdfs: -Using SQream in an HDFS Environment +HDFS Environment ======================================= .. _configuring_an_hdfs_environment_for_the_user_sqream: diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index 2314170cf..e986ee10a 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -1,35 +1,26 @@ .. _s3: *********************** -Inserting Data Using Amazon S3 +Amazon Web Services *********************** -SQream uses a native S3 connector for inserting data. The ``s3://`` URI specifies an external file path on an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. -.. contents:: - :local: - :depth: 1 +SQreamDB uses a native Amazon Simple Storage Services (S3) connector for inserting data. The ``s3://`` URI specifies an external file path to an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. -S3 Configuration -================ - -A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. - - S3 URI Format ============= + With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. The following is an example of the general S3 syntax: .. code-block:: console - s3://bucket_name/path - - -Authentication -============== -SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. + s3://bucket_name/path + +Granting Access to S3 +====================== +A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. Connecting to S3 Using SQreamDB Legacy Configuration File ========================================================= @@ -67,46 +58,19 @@ You may use the following parameters within your SQreamDB legacy configuration f "AwsObjectAccessStyle": "path" } +Authentication +============== + +SQreamDB supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. + Examples ======== Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. -.. contents:: - :local: - :depth: 1 - -Planning for Data Staging -------------------------- -The examples in this section are based on the following table: - -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Name | Team | Number | Position | Age | Height | Weight | College | Salary | -+===============+================+========+==========+=====+========+========+===================+===========+ -| Avery Bradley | Boston Celtics | 0 | PG | 25 | 2-Jun | 180 | Texas | 7730337 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-Jun | 235 | Marquette | 6796117 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| John Holland | Boston Celtics | 30 | SG | 27 | 5-Jun | 205 | Boston University | | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| R.J. Hunter | Boston Celtics | 28 | SG | 22 | 5-Jun | 185 | Georgia State | 1148640 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 10-Jun | 231 | | 5000000 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Amir Johnson | Boston Celtics | 90 | PF | 29 | 9-Jun | 240 | | 12000000 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Jordan Mickey | Boston Celtics | 55 | PF | 21 | 8-Jun | 235 | LSU | 1170960 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Kelly Olynyk | Boston Celtics | 41 | C | 25 | Jul-00 | 238 | Gonzaga | 2165160 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ -| Terry Rozier | Boston Celtics | 12 | PG | 22 | 2-Jun | 190 | Louisville | 1824360 | -+---------------+----------------+--------+----------+-----+--------+--------+-------------------+-----------+ - - -The file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make note of the file structure. - Creating a Foreign Table ------------------------ + Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: .. code-block:: postgres @@ -135,11 +99,12 @@ In the example above the file format is CSV, and it is stored as an S3 object. I For more information, see the following: -* :ref:`create a foreign table<create_foreign_table>` +* :ref:`Creating a foreign table<create_foreign_table>` * :ref:`hdfs` Querying Foreign Tables ----------------------- + The following shows the data in the foreign table: .. code-block:: psql @@ -160,21 +125,18 @@ The following shows the data in the foreign table: Bulk Loading a File from a Public S3 Bucket ------------------------------------------- -The ``COPY FROM`` command can also be used to load data without staging it first. -.. note:: The bucket must be publicly available and objects can be listed. +The ``COPY FROM`` command can also be used to load data without staging it first. -The following is an example of bulk loading a file from a public S3 bucket: +The bucket must be publicly available and objects must be listed. .. code-block:: postgres COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; - -For more information on the ``COPY FROM`` command, see :ref:`copy_from`. + Loading Files from an Authenticated S3 Bucket --------------------------------------------------- -The following is an example of loading fles from an authenticated S3 bucket: .. code-block:: postgres From 408e4c4b1dfa9756239167499b2148202386d4ed Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Oct 2023 15:22:37 +0300 Subject: [PATCH 0932/1892] New gpu and read metrics --- reference/cli/sqream_console.rst | 5 +- reference/sql/sql_statements/index.rst | 4 ++ .../utility_commands/get_license_info.rst | 17 +++-- .../get_total_chunks_size.rst | 12 ++-- .../select_data_read_metrics.rst | 69 +++++++++++++++++++ .../utility_commands/select_gpu_metrics.rst | 66 ++++++++++++++++++ releases/4.4.rst | 4 ++ 7 files changed, 158 insertions(+), 19 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst create mode 100644 reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst diff --git a/reference/cli/sqream_console.rst b/reference/cli/sqream_console.rst index 0fda5cfdc..10c4e05bf 100644 --- a/reference/cli/sqream_console.rst +++ b/reference/cli/sqream_console.rst @@ -8,10 +8,9 @@ sqream-console The console itself is a dockerized application. -This page serves as a reference for the options and parameters. - -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 Starting the console ====================== diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 47a26b0a9..28060acd2 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -131,6 +131,10 @@ The following table shows the Utility commands: - Shows the total size of all data chunks saved in the system in both compressed and uncompressed formats * - :ref:`SELECT GET_VIEW_DDL<get_view_ddl>` - View the ``CREATE VIEW`` statement for a view + * - :ref:`SELECT DATA_READ_METRICS<select_data_read_metrics>` + - Monitor license quota usage by reviewing monthly or daily data read usage + * - :ref:`SELECT GPU_METRICS<select_gpu_metrics>` + - Monitor license quota usage by reviewing monthly or daily GPU usage * - :ref:`SELECT RECOMPILE_VIEW<recompile_view>` - Recreate a view after schema changes * - :ref:`SELECT DUMP_DATABASE_DDL<dump_database_ddl>` diff --git a/reference/sql/sql_statements/utility_commands/get_license_info.rst b/reference/sql/sql_statements/utility_commands/get_license_info.rst index 8c28c0ea4..b9622804d 100644 --- a/reference/sql/sql_statements/utility_commands/get_license_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_license_info.rst @@ -3,14 +3,17 @@ ******************** GET_LICENSE_INFO ******************** + ``GET_LICENSE_INFO`` displays information related to data size limitations, expiration date, and type of license currently used by the SQream cluster. Permissions ============= + No special permissions are required. Syntax ========== + The following is the correct syntax for running the ``GET LICENSE INFO`` statement: .. code-block:: postgres @@ -21,6 +24,7 @@ The following is the correct syntax for running the ``GET LICENSE INFO`` stateme Returns ========== + The following table shows the ``GET_LICENSE_INFO`` license information in the order that it is returned: .. list-table:: @@ -59,14 +63,9 @@ Example =========== The following is an example of the returned license information described in the **Returns** section above: -.. code-block:: psql +.. code-block:: console - 10,100,compressed,20,2045-03-18,0,0,10 - -Parameters -============ -The ``GET_LICENSE_INFO`` command has no parameters. + compressed_cluster_size | uncompressed_cluster_size | compress_type | cluster_size_limit | expiration_date | is_date_expired | is_size_exceeded | cluster_size_left + ------------------------+---------------------------+---------------+--------------------+-----------------+-----------------+------------------+------------------ + 10 | 100 | compressed | 20 | 2045-03-18 | 0 | 0 | 10 -Notes -========= -If the license expires or exceeds quotas, contact a SQream representative to extend the license. diff --git a/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst index cd2c213f4..daf241a16 100644 --- a/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst +++ b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst @@ -1,13 +1,10 @@ .. _get_total_chunks_size: -******************** +********************** GET TOTAL CHUNKS SIZE -******************** -The ``get_total_chunks_size`` function returns the total size of all data chunks saved in the system in both compressed and uncompressed formats. +********************** -.. contents:: - :local: - :depth: 1 +The ``get_total_chunks_size`` function returns the total size of all data chunks saved in the system in both compressed and uncompressed formats. Syntax ========== @@ -18,6 +15,7 @@ Syntax Parameters ============ + The following table shows the ``SELECT get_total_chunks_size`` parameters: .. list-table:: @@ -51,7 +49,7 @@ Output ========== -.. code-block:: postgres +.. code-block:: console compression-type | value | size | -------------------------+--------------------------------+-------+ diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst new file mode 100644 index 000000000..745b7c83a --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst @@ -0,0 +1,69 @@ +.. _select_data_read_metrics: + +************************* +SELECT DATA READ METRICS +************************* + +The ``SELECT data_read_metrics`` utility function enables you to examine your cluster's data read during a specified time period, ensuring adherence to license limits. + +The data read result is presented in this format: Year-Month-Day, showcasing data read on each specified date, along with the total data read according to your license plan. + +Syntax +========== + +.. code-block:: postgres + + SELECT data_read_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Description + * - ``monthly`` or ``daily`` + - Mandatory + - Specifies the time frame within which data was read + * - ``start-date`` + - Mandatory + - The starting date for the data retrieval period + * - ``end-date`` + - Mandatory + - The ending date for the data retrieval period + +Examples +=========== + +Daily data reads are cumulative. For a comprehensive view of your data read usage, execute a monthly data read. + +.. code-block:: console + + master=> SELECT data_read_metrics('daily','2023-05-01', '2023-05-05); + 2023-May-01, 20GB, 5000GB + 2023-May-02, 50GB, 5000GB + 2023-May-03, 10GB, 5000GB + 2023-May-04, 5GB, 5000GB + 2023-May-05, 4GB, 5000GB + 2 rows + time: 0.103436s + +Monthly data reads: + +.. code-block:: console + + master=> SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05); + 2023 May, 20GB, 5000GB + 2023 June, 50GB, 5000GB + 2 rows + time: 0.103436s + + + +Permissions +============= + +Using the ``get_total_chunks_size`` command requires no special permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst new file mode 100644 index 000000000..0bcd12d52 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst @@ -0,0 +1,66 @@ +.. _select_gpu_metrics: + +************************* +SELECT GPU METRICS +************************* + +The ``SELECT gpu_metrics`` utility function allows you to check your cluster's GPU usage within a specific time frame. This is useful to ensure that GPU usage stays within the allowed license limits. + +An empty result indicates no usage deviation during the specified time. If the GPU usage exceeds the quota, the result will show the highest deviation in this format: Year-Month-Day, GPU deviated usage, and GPU quota limit as per your license plan. + +Syntax +========== + +.. code-block:: postgres + + SELECT gpu_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Description + * - ``monthly`` or ``daily`` + - Mandatory + - Specifies the time frame within which data was read + * - ``start-date`` + - Mandatory + - The starting date for the data retrieval period + * - ``end-date`` + - Mandatory + - The ending date for the data retrieval period + +Examples +=========== + +Daily GPU usage: + +.. code-block:: console + + master=> SELECT gpu_metrics('daily','2023-05-01', '2023-05-05); + 2023-May-01, 2,1 + 2023-May-02, 3,1 + 2023-May-03, 3,1 + 2 rows + time: 0.103436s + +Monthly GPU usage: + +.. code-block:: console + + master=> SELECT gpu_metrics('monthly', '2023-04-01', '2023-06-05'); + 2023 Apr, 2,1 + 1 rows + time: 0.155396s + + + +Permissions +============= + +Using the ``SELECT gpu_metrics`` command requires no special permissions. \ No newline at end of file diff --git a/releases/4.4.rst b/releases/4.4.rst index 2cd761e4a..4be3df47f 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -38,6 +38,10 @@ New Features and Enhancements ► :ref:`denodo` may now be used for real-time data visualization of various sources. +► Introducing :ref:`select_data_read_metrics` utility function, facilitating easy monitoring of cluster data read within specified timeframes, ensuring adherence to license limits. + +► New :ref:`select_gpu_metrics` utility function now available, providing insights into cluster GPU usage over defined periods, crucial for maintaining compliance with license limits. + Newly Released Connector Drivers --------------------------------- From 09ee3a1c3fd944782e8e4125f356d8eef56aa3fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:11:15 +0300 Subject: [PATCH 0933/1892] OK --- .../access_control_permissions.rst | 69 ++++++++++++++++--- .../select_data_read_metrics.rst | 2 +- .../utility_commands/select_gpu_metrics.rst | 2 +- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 276b969c5..b8b7b3d25 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -98,7 +98,6 @@ GRANT Syntax -- Grant permissions at the instance/ storage cluster level: GRANT - { SUPERUSER | LOGIN | PASSWORD '<password>' @@ -106,33 +105,81 @@ GRANT Syntax TO <role> [, ...] -- Grant permissions at the database level: - GRANT {{CREATE | CONNECT| DDL | SUPERUSER | CREATE FUNCTION} [, ...] | ALL [PERMISSIONS]} - + GRANT + { + { CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION} [, ...] + | ALL [PERMISSIONS] + } ON DATABASE <database> [, ...] TO <role> [, ...] -- Grant permissions at the schema level: - GRANT {{ CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [ - PERMISSIONS ]} + GRANT + { + { CREATE + | DDL + | USAGE + | SUPERUSER} [, ...] + | ALL [PERMISSIONS] + } ON SCHEMA <schema> [, ...] TO <role> [, ...] -- Grant permissions at the object level: - GRANT {{SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL [PERMISSIONS]} - ON { TABLE <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...] | VIEW <view_name> [, ...] | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] | CATALOG <catalog_name> [, ...] } + GRANT + { + { SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + } + ON + { + TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...] + | VIEW <schema_name.view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] + | CATALOG <catalog_name> [, ...] + } TO <role> [, ...]; -- Grant execute function permission: - GRANT {ALL | EXECUTE | DDL} ON FUNCTION function_name + GRANT + { ALL + | EXECUTE + | DDL + } + ON FUNCTION function_name TO role; -- Grant permissions at the column level: - GRANT {{SELECT | DDL } [, ...] | ALL [PERMISSIONS]} - ON { COLUMN <column_name> [, ...] | ALL COLUMNS IN TABLE <table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] | ALL COLUMNS IN VIEW <view_name> [, ...] | ALL COLUMNS IN CATALOG <catalog_name> [, ...]} + GRANT + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] + } + ON { COLUMN <column_name> [, ...] + | ALL COLUMNS IN TABLE <table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + | ALL COLUMNS IN VIEW <view_name> [, ...] + | ALL COLUMNS IN CATALOG <catalog_name> [, ...] + } TO <role> [, ...]; -- Grant permissions at the Service level: - GRANT {{USAGE} [PERMISSIONS]} + GRANT + { + { USAGE } [PERMISSIONS] + } ON { SERVICE <service_name> } TO <role> [, ...] diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst index 745b7c83a..4a3e9ac98 100644 --- a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst @@ -66,4 +66,4 @@ Monthly data reads: Permissions ============= -Using the ``get_total_chunks_size`` command requires no special permissions. \ No newline at end of file +Using the ``SELECT data_read_metrics`` command requires ``SUPERUSER`` permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst index 0bcd12d52..a355318f7 100644 --- a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst @@ -63,4 +63,4 @@ Monthly GPU usage: Permissions ============= -Using the ``SELECT gpu_metrics`` command requires no special permissions. \ No newline at end of file +Using the ``SELECT gpu_metrics`` command requires ``SUPERUSER`` permissions. \ No newline at end of file From 261f7d60dda0e91e251aabeba53dbb45bdc31b6c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Oct 2023 08:57:27 +0300 Subject: [PATCH 0934/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 179 ++++++++++++------ 1 file changed, 120 insertions(+), 59 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index b8b7b3d25..d270e0501 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -98,21 +98,22 @@ GRANT Syntax -- Grant permissions at the instance/ storage cluster level: GRANT - { SUPERUSER - | LOGIN - | PASSWORD '<password>' + { + SUPERUSER + | LOGIN + | PASSWORD '<password>' } TO <role> [, ...] -- Grant permissions at the database level: GRANT { - { CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION} [, ...] - | ALL [PERMISSIONS] + { CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] } ON DATABASE <database> [, ...] TO <role> [, ...] @@ -120,11 +121,11 @@ GRANT Syntax -- Grant permissions at the schema level: GRANT { - { CREATE - | DDL - | USAGE - | SUPERUSER} [, ...] - | ALL [PERMISSIONS] + { CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] } ON SCHEMA <schema> [, ...] TO <role> [, ...] @@ -132,30 +133,31 @@ GRANT Syntax -- Grant permissions at the object level: GRANT { - { SELECT - | INSERT - | DELETE - | DDL - | UPDATE } [, ...] - | ALL [PERMISSIONS] + { SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] } ON { TABLE <table_name> [, ...] - | ALL TABLES IN SCHEMA <schema_name> [, ...] - | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS IN SCHEMA <schema_name> [, ...] - | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] - | CATALOG <catalog_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...] + | VIEW <schema_name.view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] + | CATALOG <catalog_name> [, ...] } TO <role> [, ...]; -- Grant execute function permission: GRANT - { ALL - | EXECUTE - | DDL + { + ALL + | EXECUTE + | DDL } ON FUNCTION function_name TO role; @@ -163,15 +165,17 @@ GRANT Syntax -- Grant permissions at the column level: GRANT { - { SELECT - | DDL } [, ...] - | ALL [PERMISSIONS] + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } - ON { COLUMN <column_name> [, ...] - | ALL COLUMNS IN TABLE <table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] - | ALL COLUMNS IN VIEW <view_name> [, ...] - | ALL COLUMNS IN CATALOG <catalog_name> [, ...] + ON + { + COLUMN <column_name> [, ...] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + | ALL COLUMNS IN VIEW <schema_name.view_name> [, ...] + | ALL COLUMNS IN CATALOG <catalog_name> [, ...] } TO <role> [, ...]; @@ -201,35 +205,83 @@ REVOKE Syntax -- Revoke permissions at the instance/ storage cluster level: REVOKE - { SUPERUSER - | LOGIN - | PASSWORD + { + SUPERUSER + | LOGIN + | PASSWORD } FROM <role> [, ...] -- Revoke permissions at the database level: - REVOKE {{CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION}[, ...] |ALL [PERMISSIONS]} + REVOKE + { + { CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION }[, ...] + | ALL [PERMISSIONS] + } ON DATABASE <database> [, ...] FROM <role> [, ...] -- Revoke permissions at the schema level: - REVOKE { { CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS]} + REVOKE + { + { CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + } ON SCHEMA <schema> [, ...] FROM <role> [, ...] -- Revoke permissions at the object level: - REVOKE { { SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL } - ON { [ TABLE ] <table_name> [, ...] | ALL TABLES IN SCHEMA <schema_name> [, ...] | VIEW <view_name> [, ...] | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] | CATALOG <catalog_name> [, ...] } + REVOKE + { + { SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL + } + ON + { + [ TABLE ] <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...] + | VIEW <schema_name.view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + | CATALOG <catalog_name> [, ...] + } FROM <role> [, ...]; -- Revoke permissions at the column level: - REVOKE {{SELECT | DDL } [, ...] | ALL [PERMISSIONS]} - ON { COLUMN <column_name> [, ...] | ALL COLUMNS IN TABLE <table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] | ALL COLUMNS IN VIEW <view_name> [, ...] | ALL COLUMNS IN CATALOG <catalog_name> [, ...]} + REVOKE + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS]} + ON + { + COLUMN <column_name> [, ...] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] + | ALL COLUMNS IN VIEW <schema_name.view_name> [, ...] + | ALL COLUMNS IN CATALOG <catalog_name> [, ...] + } FROM <role> [, ...]; -- Revoke permissions at the service level: - REVOKE {{USAGE} [, ...] | ALL [PERMISSIONS]} + REVOKE + { + { USAGE } [, ...] + | ALL [PERMISSIONS] + } ON { SERVICE <service_name> } FROM <role> [, ...] @@ -255,9 +307,18 @@ schema statement is run. .. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { SCHEMAS | TABLES | FOREIGN TABLE | VIEWS | COLUMN | SERVICES | CATALOG } - { grant_clause | DROP grant_clause} + [IN schema_name, ...] + FOR { + SCHEMAS + | TABLES + | FOREIGN TABLE + | VIEWS + | COLUMN + | SERVICES + | CATALOG + } + { grant_clause + | DROP grant_clause } TO ROLE { role_name | public }; grant_clause ::= @@ -304,7 +365,7 @@ Grant permissions on specific objects (table, view, foreign table, or catalog) t .. code-block:: postgres - GRANT SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE table_name TO role_name; + GRANT SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE table_name IN SCHEMA schema_name TO role_name; Grant execute function permission to a role: @@ -316,7 +377,7 @@ Grant column-level permissions to a role: .. code-block:: postgres - GRANT SELECT, DDL ON COLUMN column_name TO role_name; + GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; Grant usage permissions on a service to a role: @@ -350,42 +411,42 @@ Revoke specific permissions on a database from a role: .. code-block:: postgres - REVOKE CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION FROM role_name; + REVOKE CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION ON DATABASE <database_name> FROM role_name; Revoke permissions on a schema from a role: .. code-block:: postgres - REVOKE CREATE, DDL, USAGE, SUPERUSER FROM role_name; + REVOKE CREATE, DDL, USAGE, SUPERUSER ON SCHEMA <schema_name> FROM role_name; Revoke permissions on specific objects (table, view, foreign table, or catalog) from a role: .. code-block:: postgres - REVOKE SELECT, INSERT, DELETE, DDL, UPDATE FROM TABLE table_name; + REVOKE SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE schema_name.table_name FROM role_name; Revoke column-level permissions from a role: .. code-block:: postgres - REVOKE SELECT, DDL FROM COLUMN column_name; + REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE <schema_name.table_name> FROM role_name; Revoke usage permissions on a service from a role: .. code-block:: postgres - REVOKE USAGE FROM SERVICE service_name; + REVOKE USAGE ON SERVICE service_name FROM role_name; Remove access to permissions in role1 by role2: .. code-block:: postgres - REVOKE role1 FROM role2 WITH ADMIN OPTION; + REVOKE role1 FROM role2 ; Remove permissions to grant role1 to additional roles from role2: .. code-block:: postgres - REVOKE role1 FROM role2 WITH ADMIN OPTION; + REVOKE role1 FROM role2 ; From 5438628964acbfb747ec3ba931254305bac38f55 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:40:07 +0300 Subject: [PATCH 0935/1892] 5.6.0 --- index.rst | 19 +++++----- releases/4.3.rst | 36 ++++++++++--------- .../configuring_your_instance_of_sqream.rst | 0 ...ing_and_managing_roles_and_permissions.rst | 0 ...ts_and_running_queries_from_the_editor.rst | 0 .../getting_started.rst | 17 +++++---- .../index.rst | 0 ...orkers_and_services_from_the_dashboard.rst | 0 .../viewing_logs.rst | 0 9 files changed, 37 insertions(+), 35 deletions(-) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/configuring_your_instance_of_sqream.rst (100%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/creating_assigning_and_managing_roles_and_permissions.rst (100%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/executing_statements_and_running_queries_from_the_editor.rst (100%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/getting_started.rst (89%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/index.rst (100%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/monitoring_workers_and_services_from_the_dashboard.rst (100%) rename {sqream_studio_5.4.7 => sqream_studio_5.6.0}/viewing_logs.rst (100%) diff --git a/index.rst b/index.rst index 796e5b230..f3cbf51c3 100644 --- a/index.rst +++ b/index.rst @@ -1,8 +1,8 @@ .. _index: -********************** -SQreamDB Documentation -********************** +************************* +SQream DB Documentation +************************* SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQream DB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. @@ -65,14 +65,15 @@ If you couldn't find what you're looking for, we're always happy to help. Visit getting_started/index installation_guides/index - architecture/index - configuration_guides/index - operational_guides/index - connecting_to_sqream/index - sqream_studio_5.4.7/index - feature_guides/index data_ingestion/index + connecting_to_sqream/index external_storage_platforms/index + loading_and_unloading_data/index + feature_guides/index + operational_guides/index + sqream_studio_5.6.0/index + architecture/index + configuration_guides/index reference/index data_type_guides/index releases/index diff --git a/releases/4.3.rst b/releases/4.3.rst index e496137ad..b1fa79f64 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -13,23 +13,25 @@ The 4.3 release notes were released on 11/06/2023 and describe the following: Compatibility Matrix -------------------- -+-------------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=========================+========================================================================+ -| Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x / 8.x | -+-------------------------+------------------------------------------------------------------------+ -| Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | -+-------------------------+------------------------------------------------------------------------+ -| Storage version | 49 | -+-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 4.5.8 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | -| | * Pysqream 3.2.5 | -| | * Spark | -+-------------------------+------------------------------------------------------------------------+ ++---------------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=================================+========================================================================+ +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | ++---------------------------------+------------------------------------------------------------------------+ +| Supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++---------------------------------+------------------------------------------------------------------------+ +| Storage version | 49 | ++---------------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 4.5.8 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 3.2.5 | +| | * Spark | ++---------------------------------+------------------------------------------------------------------------+ +| SQream Acceleration Studio | Version 5.6.0 | ++---------------------------------+------------------------------------------------------------------------+ New Features and Enhancements ----------------------------- diff --git a/sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst b/sqream_studio_5.6.0/configuring_your_instance_of_sqream.rst similarity index 100% rename from sqream_studio_5.4.7/configuring_your_instance_of_sqream.rst rename to sqream_studio_5.6.0/configuring_your_instance_of_sqream.rst diff --git a/sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.6.0/creating_assigning_and_managing_roles_and_permissions.rst similarity index 100% rename from sqream_studio_5.4.7/creating_assigning_and_managing_roles_and_permissions.rst rename to sqream_studio_5.6.0/creating_assigning_and_managing_roles_and_permissions.rst diff --git a/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.6.0/executing_statements_and_running_queries_from_the_editor.rst similarity index 100% rename from sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.rst rename to sqream_studio_5.6.0/executing_statements_and_running_queries_from_the_editor.rst diff --git a/sqream_studio_5.4.7/getting_started.rst b/sqream_studio_5.6.0/getting_started.rst similarity index 89% rename from sqream_studio_5.4.7/getting_started.rst rename to sqream_studio_5.6.0/getting_started.rst index 8771e5545..f6e4d5fbc 100644 --- a/sqream_studio_5.4.7/getting_started.rst +++ b/sqream_studio_5.6.0/getting_started.rst @@ -1,15 +1,17 @@ .. _getting_started: -**************************** -Getting Started with SQream Acceleration Studio 5.4.7 -**************************** +****************************************************** +Getting Started with SQream Acceleration Studio 5.6.0 +****************************************************** + Setting Up and Starting Studio ------------------------------ When starting Studio, it listens on the local machine on port 8080. Logging In to Studio ---------------- +----------------------- + **To log in to SQream Studio:** 1. Open a browser to the host on **port 8080**. @@ -25,7 +27,8 @@ Logging In to Studio When you sign in, the License Warning is displayed. Navigating Studio's Main Features -------------- +----------------------------------- + When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. From here you can navigate between the main areas of the Studio: @@ -56,7 +59,3 @@ By clicking the user icon, you can also use it for logging out and viewing the f * License expiration date * License storage capacity * Log out - -.. _back_to_dashboard_5.4.7: - -.. _studio_dashboard_5.4.7: diff --git a/sqream_studio_5.4.7/index.rst b/sqream_studio_5.6.0/index.rst similarity index 100% rename from sqream_studio_5.4.7/index.rst rename to sqream_studio_5.6.0/index.rst diff --git a/sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.6.0/monitoring_workers_and_services_from_the_dashboard.rst similarity index 100% rename from sqream_studio_5.4.7/monitoring_workers_and_services_from_the_dashboard.rst rename to sqream_studio_5.6.0/monitoring_workers_and_services_from_the_dashboard.rst diff --git a/sqream_studio_5.4.7/viewing_logs.rst b/sqream_studio_5.6.0/viewing_logs.rst similarity index 100% rename from sqream_studio_5.4.7/viewing_logs.rst rename to sqream_studio_5.6.0/viewing_logs.rst From a3923d751e6a7f744dab092319f5710f5b8558a8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:43:18 +0300 Subject: [PATCH 0936/1892] 5.6.0 --- releases/4.4.rst | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 4be3df47f..6a6308042 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -13,23 +13,25 @@ The 4.4 release notes were released on September 28th, 2023 Compatibility Matrix -------------------- -+-------------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=========================+========================================================================+ -| Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x / 8.x | -+-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | -+-------------------------+------------------------------------------------------------------------+ -| Storage version | 49 | -+-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.0.0 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | -| | * Pysqream 5.0.0 | -| | * Spark | -+-------------------------+------------------------------------------------------------------------+ ++---------------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=================================+========================================================================+ +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | ++---------------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++---------------------------------+------------------------------------------------------------------------+ +| Storage version | 49 | ++---------------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.0.0 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 5.0.0 | +| | * Spark | ++---------------------------------+------------------------------------------------------------------------+ +| SQream Acceleration Studio | Version 5.6.0 | ++---------------------------------+------------------------------------------------------------------------+ New Features and Enhancements ----------------------------- From b1b2680f4e73805d202477210d1405715a6bcc93 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Oct 2023 14:57:15 +0300 Subject: [PATCH 0937/1892] Update index.rst --- sqream_studio_5.6.0/index.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sqream_studio_5.6.0/index.rst b/sqream_studio_5.6.0/index.rst index de8138b89..385a6e446 100644 --- a/sqream_studio_5.6.0/index.rst +++ b/sqream_studio_5.6.0/index.rst @@ -1,12 +1,10 @@ .. _sqream_studio_: ******************************** -SQream Acceleration Studio 5.4.7 +SQream Acceleration Studio 5.6.0 ******************************** -The SQreamDB Acceleration Studio 5.4.7 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. - -This section describes how to use the SQream Accleration Studio version 5.4.7: +The SQreamDB Acceleration Studio 5.6.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. .. toctree:: :maxdepth: 1 From dce6fd6d86927cb581495009bb9d57464aa660a2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:01:43 +0300 Subject: [PATCH 0938/1892] Update round.rst --- .../sql_functions/scalar_functions/numeric/round.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index 462ec606f..e9d0fd906 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -1,8 +1,8 @@ .. _round: -************************** +********** ROUND -************************** +********** Rounds a numeric expression to the nearest precision. @@ -37,7 +37,7 @@ When using the ``ROUND`` floating point number scalar function, ``real`` argumen Notes ======= -* If the input value is NULL, the result is NULL. +If the input value is ``NULL``, the result is ``NULL``. Examples =========== @@ -47,7 +47,7 @@ Rounding to the nearest integer .. code-block:: psql - numbers=> SELECT ROUND(x) FROM (VALUES (0.0001), (PI()), (-2.718281), (500.1234), (0.5), (1.5)) as t(x); + SELECT ROUND(x) FROM (VALUES (0.0001), (PI()), (-2.718281), (500.1234), (0.5), (1.5)) as t(x); round ------ 0 @@ -62,7 +62,7 @@ Rounding to 2 digits after the decimal point .. code-block:: psql - numbers=> SELECT ROUND(x,2) FROM (VALUES (0.0001), (PI()), (-2.718281), (500.1234)) as t(x); + SELECT ROUND(x,2) FROM (VALUES (0.0001), (PI()), (-2.718281), (500.1234)) as t(x); round ------- 0 @@ -75,7 +75,7 @@ Rounding to 2 digits after the decimal point .. code-block:: psql - numbers=> SELECT FLOOR(x), CEIL(x), ROUND(x) + SELECT FLOOR(x), CEIL(x), ROUND(x) . FROM (VALUES (0.0001), (-0.0001) . , (PI()), (-2.718281), (500.1234)) as t(x); floor | ceil | round From 428bc92134a0a16577bab44301278a916442fe20 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 4 Oct 2023 09:51:33 +0300 Subject: [PATCH 0939/1892] permissions introductory text --- .../access_control_permissions.rst | 28 +++++++++---------- .../access_control_commands/grant.rst | 10 ++++++- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index d270e0501..fdfa5477f 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -4,16 +4,16 @@ Permissions ************** -.. contents:: - :local: - :depth: 1 +SQreamDB’s primary permission object is a role. The role operates in a dual capacity as both a user and a group. In its user role, it may execute operations like creating tables, querying data, and administering the database, depending on its permissions. The role’s group attribute allows it to extend its permissions to roles defined as its group members. Information about permissions for all roles is stored in the metadata. -The following table displays the access control permissions: +There are two main types of permissions: global and object-level. Global permissions belong to ``SUPERUSER`` roles, allowing unrestricted access to all system and database activities. Object-level permissions apply to non-``SUPERUSER`` roles and can be assigned to databases, schemas, tables, functions, views, foreign tables, columns, catalogs, and services. +The following tables describe the required permissions for performing and executing operations on various SQreamDB objects. + +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Permission** | **Description** | +====================+=========================================================================================================================+ -| **Object/Layer: All Databases** | +|**All Databases** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``LOGIN`` | Use role to log into the system (the role also needs connect permission on the database it is connecting to) | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -21,7 +21,7 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SUPERUSER`` | No permission restrictions on any activity | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Database** | +| **Database** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SUPERUSER`` | No permission restrictions on any activity within that database (this does not include modifying roles or permissions) | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -31,13 +31,13 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE FUNCTION``| Create and drop functions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Schema** | +| **Schema** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Grants access to schema objects | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create tables in the schema | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Table** | +| **Table** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | :ref:`select` from the table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -51,7 +51,7 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All the table permissions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Function** | +| **Function** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``EXECUTE`` | Use the function | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -59,31 +59,31 @@ The following table displays the access control permissions: +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All function permissions | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: View** | +| **View** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from view | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | DDL operations of view results | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Foreign Table** | +| **Foreign Table** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from foreign table | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Foreign table DDL operations | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Column** | +| **Column** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Column DDL operations | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Layer: Catalog** | +| **Catalog** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Catalog DDL operations | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Object/Services** | +| **Services** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Using a specific service | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index d86522900..282d268e7 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -17,7 +17,6 @@ See also :ref:`revoke`, :ref:`create_role`. Syntax ========== -The following is the syntax for the ``GRANT` statement: .. code-block:: postgres @@ -101,6 +100,7 @@ The following is the syntax for the ``GRANT` statement: Parameters ============ + The following table describes the ``GRANT`` parameters: .. list-table:: @@ -125,6 +125,7 @@ The following table describes the ``GRANT`` parameters: Supported Permissions ======================= + The following table describes the supported permissions: .. list-table:: @@ -182,6 +183,7 @@ The following table describes the supported permissions: Examples =========== + This section includes the following examples: .. contents:: @@ -190,6 +192,7 @@ This section includes the following examples: Creating a User Role with Log-in Permissions ---------------------------------------------- + The following example shows how to convert a role to a user by granting password and log-in permissions: .. code-block:: postgres @@ -201,6 +204,7 @@ The following example shows how to convert a role to a user by granting password Promoting a User to a Superuser ------------------------------------- + The following is the syntax for promoting a user to a superuser: .. code-block:: postgres @@ -213,6 +217,7 @@ The following is the syntax for promoting a user to a superuser: Creating a New Role for a Group of Users -------------------------------------------- + The following example shows how to create a new role for a group of users: .. code-block:: postgres @@ -229,6 +234,7 @@ The following example shows how to create a new role for a group of users: Granting with Admin Option ------------------------------ + If ``WITH ADMIN OPTION`` is specified, the role with the **admin** option can grant membership in the role to others and revoke membership, as shown below: .. code-block:: postgres @@ -240,6 +246,7 @@ If ``WITH ADMIN OPTION`` is specified, the role with the **admin** option can gr Changing Password for User Role -------------------------------------- + The following is an example of changing a password for a user role. This is done by granting the user a new password: .. code-block:: postgres @@ -250,4 +257,5 @@ The following is an example of changing a password for a user role. This is done Permissions ============= + To grant permissions, the current role must have the ``SUPERUSER`` permission, or have the ``ADMIN OPTION``. \ No newline at end of file From 1cdb4092f55a67b1240a861a7d0921ec5a74e9c2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 4 Oct 2023 10:02:10 +0300 Subject: [PATCH 0940/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index fdfa5477f..8e97c30c1 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -306,35 +306,35 @@ schema statement is run. .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR target_role_name - [IN schema_name, ...] - FOR { - SCHEMAS - | TABLES - | FOREIGN TABLE - | VIEWS - | COLUMN - | SERVICES - | CATALOG + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { + SCHEMAS + | TABLES + | FOREIGN TABLE + | VIEWS + | COLUMN + | SERVICES + | CATALOG } - { grant_clause - | DROP grant_clause } - TO ROLE { role_name | public }; + { grant_clause + | DROP grant_clause } + TO ROLE { role_name | public }; - grant_clause ::= + grant_clause ::= GRANT { CREATE FUNCTION - | SUPERUSER - | CONNECT - | CREATE - | USAGE - | SELECT - | INSERT - | DELETE - | DDL - | UPDATE - | EXECUTE - | ALL + | SUPERUSER + | CONNECT + | CREATE + | USAGE + | SELECT + | INSERT + | DELETE + | DDL + | UPDATE + | EXECUTE + | ALL } Examples From 86d8943cc35330082d84aecd9128bc88f46a7fb4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:50:03 +0300 Subject: [PATCH 0941/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 5f401fa60..97590401c 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ...") * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From c3c843b42043e99d956b350875677c21b4f2a0fd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:09:40 +0300 Subject: [PATCH 0942/1892] Update round.rst --- .../sql/sql_functions/scalar_functions/numeric/round.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index e9d0fd906..e1047dadd 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -4,7 +4,9 @@ ROUND ********** -Rounds a numeric expression to the nearest precision. +Rounds a numeric expression to the nearest precision. + +Supported data types: ``INT``, ``TINYINT``, ``SMALLINT``, ``BIGINT``, ``REAL``, ``DOUBLE``, ``NUMERIC`` See also :ref:`ceiling`, :ref:`floor`. @@ -32,7 +34,7 @@ Arguments Returns ============ -When using the ``ROUND`` floating point number scalar function, ``real`` arguments are automatically cast to ``double`` precision. +``REAL`` arguments are automatically cast to double precision, while all other supported data types retain the supplied data type. Notes ======= From f3e35c6684d29b4b1c3d382f20bd0410c23151f3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:16:52 +0300 Subject: [PATCH 0943/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 26575ea28..beb7d00bb 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '4.4' +release = '4.5' From 5576a94a546fbfe11eba5e55f149ff088fdae65f Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Oct 2023 09:38:26 +0300 Subject: [PATCH 0944/1892] Permissions --- operational_guides/access_control_permissions.rst | 10 ++++++---- .../sql_statements/access_control_commands/grant.rst | 2 +- .../sql_statements/access_control_commands/revoke.rst | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 8e97c30c1..29922fafa 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -193,7 +193,7 @@ GRANT Syntax -- Also allows the role2 to grant role1 to other roles: GRANT <role1> [, ...] - TO <role2> + TO <role2> [,...] [WITH ADMIN OPTION] REVOKE Syntax @@ -286,10 +286,12 @@ REVOKE Syntax FROM <role> [, ...] -- Removes access to permissions in role1 by role 2 - REVOKE <role1> [, ...] FROM <role2> [, ...] + REVOKE [ADMIN OPTION FOR] <role1> [, ...] + FROM <role2> [, ...] -- Removes permissions to grant role1 to additional roles from role2 - REVOKE <role1> [, ...] FROM <role2> [, ...] + REVOKE [ADMIN OPTION FOR] <role1> [, ...] + FROM <role2> [, ...] Altering Default Permissions ============================ @@ -447,6 +449,6 @@ Remove permissions to grant role1 to additional roles from role2: .. code-block:: postgres - REVOKE role1 FROM role2 ; + REVOKE ADMIN OPTION FOR role1 FROM role2 ; diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 282d268e7..b987e4bfc 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -83,7 +83,7 @@ Syntax -- Pass permissions between roles by granting one role to another: | GRANT role_name [, ...] - TO role_name_2 + TO role_name_2 [, ...] [ WITH ADMIN OPTION ] ; diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index 3e61d9e87..ade121815 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -82,9 +82,9 @@ Syntax -- Remove permissions between roles by revoking role membership: - | REVOKE role_name [, ...] + | REVOKE [ WITH ADMIN OPTION ] role_name [, ...] FROM role_name_2 - [ WITH ADMIN OPTION ] + ; From 0f47b88b4e28ad318bd3ed049a73c933e2c2314a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:03:56 +0300 Subject: [PATCH 0945/1892] Studio 5.7.0 --- index.rst | 2 +- .../configuring_your_instance_of_sqream.rst | 0 .../creating_assigning_and_managing_roles_and_permissions.rst | 0 ...ecuting_statements_and_running_queries_from_the_editor.rst | 0 .../getting_started.rst | 2 +- {sqream_studio_5.6.0 => sqream_studio_5.7.0}/index.rst | 4 ++-- .../monitoring_workers_and_services_from_the_dashboard.rst | 0 {sqream_studio_5.6.0 => sqream_studio_5.7.0}/viewing_logs.rst | 0 8 files changed, 4 insertions(+), 4 deletions(-) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/configuring_your_instance_of_sqream.rst (100%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/creating_assigning_and_managing_roles_and_permissions.rst (100%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/executing_statements_and_running_queries_from_the_editor.rst (100%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/getting_started.rst (97%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/index.rst (86%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/monitoring_workers_and_services_from_the_dashboard.rst (100%) rename {sqream_studio_5.6.0 => sqream_studio_5.7.0}/viewing_logs.rst (100%) diff --git a/index.rst b/index.rst index f3cbf51c3..9ff692492 100644 --- a/index.rst +++ b/index.rst @@ -71,7 +71,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit loading_and_unloading_data/index feature_guides/index operational_guides/index - sqream_studio_5.6.0/index + sqream_studio_5.7.0/index architecture/index configuration_guides/index reference/index diff --git a/sqream_studio_5.6.0/configuring_your_instance_of_sqream.rst b/sqream_studio_5.7.0/configuring_your_instance_of_sqream.rst similarity index 100% rename from sqream_studio_5.6.0/configuring_your_instance_of_sqream.rst rename to sqream_studio_5.7.0/configuring_your_instance_of_sqream.rst diff --git a/sqream_studio_5.6.0/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio_5.7.0/creating_assigning_and_managing_roles_and_permissions.rst similarity index 100% rename from sqream_studio_5.6.0/creating_assigning_and_managing_roles_and_permissions.rst rename to sqream_studio_5.7.0/creating_assigning_and_managing_roles_and_permissions.rst diff --git a/sqream_studio_5.6.0/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio_5.7.0/executing_statements_and_running_queries_from_the_editor.rst similarity index 100% rename from sqream_studio_5.6.0/executing_statements_and_running_queries_from_the_editor.rst rename to sqream_studio_5.7.0/executing_statements_and_running_queries_from_the_editor.rst diff --git a/sqream_studio_5.6.0/getting_started.rst b/sqream_studio_5.7.0/getting_started.rst similarity index 97% rename from sqream_studio_5.6.0/getting_started.rst rename to sqream_studio_5.7.0/getting_started.rst index f6e4d5fbc..dad6e613b 100644 --- a/sqream_studio_5.6.0/getting_started.rst +++ b/sqream_studio_5.7.0/getting_started.rst @@ -1,7 +1,7 @@ .. _getting_started: ****************************************************** -Getting Started with SQream Acceleration Studio 5.6.0 +Getting Started with SQream Acceleration Studio 5.7.0 ****************************************************** Setting Up and Starting Studio diff --git a/sqream_studio_5.6.0/index.rst b/sqream_studio_5.7.0/index.rst similarity index 86% rename from sqream_studio_5.6.0/index.rst rename to sqream_studio_5.7.0/index.rst index 385a6e446..96e25eaac 100644 --- a/sqream_studio_5.6.0/index.rst +++ b/sqream_studio_5.7.0/index.rst @@ -1,10 +1,10 @@ .. _sqream_studio_: ******************************** -SQream Acceleration Studio 5.6.0 +SQream Acceleration Studio 5.7.0 ******************************** -The SQreamDB Acceleration Studio 5.6.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. +The SQreamDB Acceleration Studio 5.7.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. .. toctree:: :maxdepth: 1 diff --git a/sqream_studio_5.6.0/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio_5.7.0/monitoring_workers_and_services_from_the_dashboard.rst similarity index 100% rename from sqream_studio_5.6.0/monitoring_workers_and_services_from_the_dashboard.rst rename to sqream_studio_5.7.0/monitoring_workers_and_services_from_the_dashboard.rst diff --git a/sqream_studio_5.6.0/viewing_logs.rst b/sqream_studio_5.7.0/viewing_logs.rst similarity index 100% rename from sqream_studio_5.6.0/viewing_logs.rst rename to sqream_studio_5.7.0/viewing_logs.rst From 0522aeb9a1423786ca8767ad8b74589efbacdfba Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:14:40 +0300 Subject: [PATCH 0946/1892] Update round.rst --- reference/sql/sql_functions/scalar_functions/numeric/round.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/numeric/round.rst b/reference/sql/sql_functions/scalar_functions/numeric/round.rst index e1047dadd..b45549309 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/round.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/round.rst @@ -6,7 +6,7 @@ ROUND Rounds a numeric expression to the nearest precision. -Supported data types: ``INT``, ``TINYINT``, ``SMALLINT``, ``BIGINT``, ``REAL``, ``DOUBLE``, ``NUMERIC`` +Supported data types: ``INT``, ``TINYINT``, ``SMALLINT``, ``BIGINT``, ``REAL``, ``DOUBLE``, ``NUMERIC``. See also :ref:`ceiling`, :ref:`floor`. From e49e93e937ad7b3221a7b64b48c9a6a53c88dd87 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Oct 2023 12:29:25 +0300 Subject: [PATCH 0947/1892] Studio version --- releases/4.3.rst | 5 +++++ releases/4.4.rst | 7 ++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index b1fa79f64..0a705f640 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -50,6 +50,11 @@ To learn more about how and when you should use this new capability, visit :ref: ► RocksDB's metadata scale-up improvements have been implemented. +SQreamDB Studio Updates and Improvements +----------------------------------------- + +SQream Studio version 5.6.0 has been released. + Known Issues ------------ diff --git a/releases/4.4.rst b/releases/4.4.rst index 6a6308042..e240bdaf3 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -30,7 +30,7 @@ Compatibility Matrix | | * Pysqream 5.0.0 | | | * Spark | +---------------------------------+------------------------------------------------------------------------+ -| SQream Acceleration Studio | Version 5.6.0 | +| SQream Acceleration Studio | Version 5.7.0 | +---------------------------------+------------------------------------------------------------------------+ New Features and Enhancements @@ -57,6 +57,11 @@ Newly Released Connector Drivers * `jar.file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ * :ref:`Documentation<java_jdbc>` +SQreamDB Studio Updates and Improvements +----------------------------------------- + +SQream Studio version 5.7.0 has been released. + Known Issues ------------ From f8060440a524e4029bb7fc918a3defb418cf9f56 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:05:03 +0300 Subject: [PATCH 0948/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 53 +++++++++++++------ 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 29922fafa..2b8a239b1 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -79,9 +79,7 @@ The following tables describe the required permissions for performing and execut +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Catalog** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from catalog | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Catalog DDL operations | +| ``SELECT`` | Select from catalog | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Services** | +--------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -147,7 +145,20 @@ GRANT Syntax | VIEW <schema_name.view_name> [, ...] | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...] + | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + } + TO <role> [, ...]; + + GRANT + { + { SELECT + | INSERT + | DELETE + | UPDATE } [, ...] + | ALL [PERMISSIONS] + } + ON + { | CATALOG <catalog_name> [, ...] } TO <role> [, ...]; @@ -171,11 +182,9 @@ GRANT Syntax } ON { - COLUMN <column_name> [, ...] + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] - | ALL COLUMNS IN VIEW <schema_name.view_name> [, ...] - | ALL COLUMNS IN CATALOG <catalog_name> [, ...] } TO <role> [, ...]; @@ -255,6 +264,19 @@ REVOKE Syntax | ALL VIEWS IN SCHEMA <schema_name> [, ...] | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + } + FROM <role> [, ...]; + + REVOKE + { + { SELECT + | INSERT + | DELETE + | UPDATE } [, ...] + | ALL + } + ON + { | CATALOG <catalog_name> [, ...] } FROM <role> [, ...]; @@ -267,11 +289,9 @@ REVOKE Syntax | ALL [PERMISSIONS]} ON { - COLUMN <column_name> [, ...] + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] - | ALL COLUMNS IN VIEW <schema_name.view_name> [, ...] - | ALL COLUMNS IN CATALOG <catalog_name> [, ...] } FROM <role> [, ...]; @@ -315,9 +335,8 @@ schema statement is run. | TABLES | FOREIGN TABLE | VIEWS - | COLUMN - | SERVICES - | CATALOG + | COLUMNS + | SAVED_QUERIES } { grant_clause | DROP grant_clause } @@ -367,7 +386,7 @@ Grant permissions on specific objects (table, view, foreign table, or catalog) t .. code-block:: postgres - GRANT SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE table_name IN SCHEMA schema_name TO role_name; + GRANT SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE schema_name.table_name TO role_name; Grant execute function permission to a role: @@ -413,13 +432,13 @@ Revoke specific permissions on a database from a role: .. code-block:: postgres - REVOKE CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION ON DATABASE <database_name> FROM role_name; + REVOKE CREATE, CONNECT, DDL, SUPERUSER, CREATE FUNCTION ON DATABASE database_name FROM role_name; Revoke permissions on a schema from a role: .. code-block:: postgres - REVOKE CREATE, DDL, USAGE, SUPERUSER ON SCHEMA <schema_name> FROM role_name; + REVOKE CREATE, DDL, USAGE, SUPERUSER ON SCHEMA schema_name FROM role_name; Revoke permissions on specific objects (table, view, foreign table, or catalog) from a role: @@ -431,7 +450,7 @@ Revoke column-level permissions from a role: .. code-block:: postgres - REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE <schema_name.table_name> FROM role_name; + REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE schema_name.table_name FROM role_name; Revoke usage permissions on a service from a role: From b9a0d27bd8a51c7c65743de7fc05665d15ea43b6 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 8 Oct 2023 10:34:11 +0300 Subject: [PATCH 0949/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 153 +++++++++--------- 1 file changed, 77 insertions(+), 76 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 2b8a239b1..2fecc0ac5 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -10,81 +10,81 @@ There are two main types of permissions: global and object-level. Global permiss The following tables describe the required permissions for performing and executing operations on various SQreamDB objects. -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Permission** | **Description** | -+====================+=========================================================================================================================+ -|**All Databases** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``LOGIN`` | Use role to log into the system (the role also needs connect permission on the database it is connecting to) | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``PASSWORD`` | The password used for logging into the system | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SUPERUSER`` | No permission restrictions on any activity | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Database** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SUPERUSER`` | No permission restrictions on any activity within that database (this does not include modifying roles or permissions) | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CONNECT`` | Connect to the database | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | Create schemas in the database | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE FUNCTION``| Create and drop functions | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Schema** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``USAGE`` | Grants access to schema objects | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | Create tables in the schema | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Table** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | :ref:`select` from the table | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``INSERT`` | :ref:`insert` into the table | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter on the table | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | All the table permissions | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Function** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``EXECUTE`` | Use the function | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter on the function | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | All function permissions | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **View** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from view | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | DDL operations of view results | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Foreign Table** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from foreign table | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Foreign table DDL operations | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Column** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from catalog | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Column DDL operations | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Catalog** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from catalog | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Services** | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``USAGE`` | Using a specific service | -+--------------------+-------------------------------------------------------------------------------------------------------------------------+ ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Permission** | **Description** | ++======================+=========================================================================================================================+ +|**All Databases** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``LOGIN`` | Use role to log into the system (the role also needs connect permission on the database it is connecting to) | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``PASSWORD`` | The password used for logging into the system | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | No permission restrictions on any activity | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Database** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | No permission restrictions on any activity within that database (this does not include modifying roles or permissions) | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CONNECT`` | Connect to the database | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | Create schemas in the database | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE FUNCTION`` | Create and drop functions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Schema** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | Grants access to schema objects | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``CREATE`` | Create tables in the schema | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Table** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | :ref:`select` from the table | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``INSERT`` | :ref:`insert` into the table | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter on the table | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All the table permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Function** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``EXECUTE`` | Use the function | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter on the function | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All function permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **View** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from view | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | DDL operations of view results | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Foreign Table** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from foreign table | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Foreign table DDL operations | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Column** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from catalog | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Column DDL operations | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Catalog** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from catalog | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Services** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | Using a specific service | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ GRANT Syntax @@ -182,7 +182,8 @@ GRANT Syntax } ON { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] + | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] } From 2ce99ec8cb0e347f5805f568903db78adc5d2636 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 9 Oct 2023 14:26:03 +0300 Subject: [PATCH 0950/1892] Upgrade Guide --- index.rst | 1 + releases/4.0_index.rst | 2 - releases/{4.5 => 4.5.rst} | 0 releases/index.rst | 1 + upgrade_guide/index.rst | 279 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 2 deletions(-) rename releases/{4.5 => 4.5.rst} (100%) create mode 100644 upgrade_guide/index.rst diff --git a/index.rst b/index.rst index 9ff692492..cab1acf8b 100644 --- a/index.rst +++ b/index.rst @@ -65,6 +65,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit getting_started/index installation_guides/index + upgrade_guide/index data_ingestion/index connecting_to_sqream/index external_storage_platforms/index diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 396ca0d11..6dfb60bd1 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -4,8 +4,6 @@ 4.0 Release Notes ***************** - - .. contents:: :local: :depth: 1 diff --git a/releases/4.5 b/releases/4.5.rst similarity index 100% rename from releases/4.5 rename to releases/4.5.rst diff --git a/releases/index.rst b/releases/index.rst index ff2f162da..57599c192 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -41,4 +41,5 @@ Release Notes 4.0_index 2022.1_index 2021.2_index + diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst new file mode 100644 index 000000000..c8032728d --- /dev/null +++ b/upgrade_guide/index.rst @@ -0,0 +1,279 @@ +.. _upgrade_guide: + +***************** +Upgrade Guide +***************** + + + +Version 2022.1.7 +---------------------- + +Version 2022.1.7 uses storage version 43. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <RocksDB path> + +Upgrading to v2022.1.6 +---------------------- + +Version 2022.1.6 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <RocksDB path> + +Version 2022.1.5 +---------------------- + +Version 2022.1.5 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <RocksDB path> + +Version 2022.1.4 +---------------------- + +Version 2022.1.4 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +Version 2022.1.3 +---------------------- + +Version 2022.1.3 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +In SQream version 2022.1.3 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +Version 2022.1.2 +---------------------- + +Version 2022.1.2 uses storage version 41. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +Version 2022.1.1 +---------------------- + +Operation and Configuration Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Version 2022.1.1 uses storage version 40. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +In compliance with GDPR standards, version 2022.1.1 requires a strong password policy when accessing the CLI and Studio. For more information, see :ref:`Password Policy<access_control_password_policy>`. + +The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. For more information, see :ref:`Adjusting the Permitted Log-In Attempts<login_max_retries>`. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +Version 2022.1 +----------------------- + +Operation and Configuration Changes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Version 2022.1 uses storage version 40. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. + +In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. + +If you are using an earlier version of SQreamDB, see the :ref:`Using Legacy String Literals<use_legacy_string_literals>` configuration flag. + +Upgrade Procedure +^^^^^^^^^^^^^^^^^^ + +1. Generate a backup of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path', 'single_file'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQream services. + +3. Extract the recently created backup file. + +4. Replace your current metadata with the metadata you stored in the backup file. + +5. Navigate to the new SQream package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> \ No newline at end of file From 98181cffa9c7659fbc419a445c7aea1c968fbfc2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 10 Oct 2023 13:16:36 +0300 Subject: [PATCH 0951/1892] cross database queries --- .../sql/sql_syntax/cross_database_query.rst | 88 +++++++++++++++++++ reference/sql/sql_syntax/index.rst | 56 +++++++++--- upgrade_guide/index.rst | 32 +++---- 3 files changed, 147 insertions(+), 29 deletions(-) create mode 100644 reference/sql/sql_syntax/cross_database_query.rst diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst new file mode 100644 index 000000000..be2743078 --- /dev/null +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -0,0 +1,88 @@ +.. _cross_database_query: + +*************************** +Cross Database Query +*************************** + +Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. + +Syntax +========== + +.. code-block:: sql + + SELECT + <column_name2> [,column_name_2] [, ...] + FROM + <database_name>.<schema_name>.<table_name> + JOIN + <database_name>.<schema_name>.<table_name> + ON + <database_name>.<schema_name>.<table_name>.<column_name> =<database_name>.<schema_name>.<table_name>.<column_name> + WHERE + <condition> + +Parameters +=========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``column_name`` + - The column to perform a ``JOIN`` operation on + * - ``database_name`` + - The SQreamDB database to perform a ``JOIN`` operation on + * - ``schema_name`` + - The schema name of the database to perform a ``JOIN`` operation on + * - ``table_name`` + - The table to perform a ``JOIN`` operation on + * - ``condition`` + - The condition for performing a ``JOIN`` operation + +Examples +========= + +Querying data from two tables in different databases: + +.. code-block:: sql + + SELECT * + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; + +Querying data from two tables in different schemas and databases: + +.. code-block:: sql + + SELECT * + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; + +Querying data from two tables in different databases with a where clause: + +.. code-block:: sql + + SELECT t1.*, t2.* + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; + +Querying data from three tables in different databases: + +.. code-block:: sql + + SELECT t1.*, t2.*, t3.* + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + JOIN database3.schema3.table3 t3 + ON t2.id = t3.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; \ No newline at end of file diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 9e0422db4..b8ce4d329 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -4,16 +4,46 @@ SQL Syntax Features ********************** -SQream DB supports SQL from the ANSI 92 syntax and describes the following: - -.. hlist:: - :columns: 1 - - * :ref:`keywords_and_identifiers` - * :ref:`literals` - * :ref:`scalar_expressions` - * :ref:`joins` - * :ref:`common_table_expressions` - * :ref:`window_functions` - * :ref:`subqueries` - * :ref:`null_handling` \ No newline at end of file +SQreamDB supports SQL from the ANSI 92 syntax. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Features + - Description + * - :ref:`keywords_and_identifiers` + - Keywords are reserved words with specific meanings, while identifiers are used to name database objects like tables and columns. + * - :ref:`literals` + - Literals are fixed values representing specific data types, such as numbers or strings, used directly in SQL statements. + * - :ref:`scalar_expressions` + - Scalar expressions are single-value computations that operate on one or more values to produce a single result. + * - :ref:`cross_database_query` + - Cross-database queries involve accessing and manipulating data from multiple databases within a single SQL statement or operation. + * - :ref:`joins` + - Joins combine rows from two or more tables based on a related column to retrieve data from multiple sources in a single result set. + * - :ref:`common_table_expressions` + - Common Table Expressions (CTEs) are named temporary result sets that simplify complex queries by allowing the definition of subqueries for better readability and reusability. + * - :ref:`window_functions` + - Window Functions perform calculations across a specified range of rows related to the current row, offering advanced analytics and aggregation within result sets. + * - :ref:`subqueries` + - Subqueries are nested queries that are embedded within a larger query to retrieve data, perform calculations, or filter results based on the outcome of the inner query. + * - :ref:`null_handling` + - Null handling involves managing and evaluating the presence of null values, representing unknown or undefined data, to avoid unexpected results in queries and expressions. + + + + + + + + + + + + + + + + + diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index c8032728d..948861820 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -6,8 +6,8 @@ Upgrade Guide -Version 2022.1.7 ----------------------- +Upgrading to Version 2022.1.7 +------------------------------ Version 2022.1.7 uses storage version 43. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -38,8 +38,8 @@ Upgrade Procedure $ ./upgrade_storage <RocksDB path> -Upgrading to v2022.1.6 ----------------------- +Upgrading to Version 2022.1.6 +--------------------------------- Version 2022.1.6 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -70,8 +70,8 @@ Upgrade Procedure $ ./upgrade_storage <RocksDB path> -Version 2022.1.5 ----------------------- +Upgrading to Version 2022.1.5 +------------------------------- Version 2022.1.5 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -102,8 +102,8 @@ Upgrade Procedure $ ./upgrade_storage <RocksDB path> -Version 2022.1.4 ----------------------- +Upgrading to Version 2022.1.4 +------------------------------ Version 2022.1.4 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -134,8 +134,8 @@ Upgrade Procedure $ ./upgrade_storage <levelDB path> -Version 2022.1.3 ----------------------- +Upgrading to Version 2022.1.3 +--------------------------------- Version 2022.1.3 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -168,8 +168,8 @@ Upgrade Procedure $ ./upgrade_storage <levelDB path> -Version 2022.1.2 ----------------------- +Upgrading to Version 2022.1.2 +------------------------------- Version 2022.1.2 uses storage version 41. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. @@ -200,8 +200,8 @@ Upgrade Procedure $ ./upgrade_storage <levelDB path> -Version 2022.1.1 ----------------------- +Upgrading to Version 2022.1.1 +------------------------------ Operation and Configuration Changes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -239,8 +239,8 @@ Upgrade Procedure $ ./upgrade_storage <levelDB path> -Version 2022.1 ------------------------ +Upgrading to Version 2022.1 +----------------------------- Operation and Configuration Changes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From fb99ba4ce97439d502ba52192b8977fa017778d6 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:51:31 +0300 Subject: [PATCH 0952/1892] Update cross_database_query.rst --- reference/sql/sql_syntax/cross_database_query.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index be2743078..98bcd699b 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -15,12 +15,18 @@ Syntax <column_name2> [,column_name_2] [, ...] FROM <database_name>.<schema_name>.<table_name> + AS + <table_name> JOIN <database_name>.<schema_name>.<table_name> + AS + <table_name> ON - <database_name>.<schema_name>.<table_name>.<column_name> =<database_name>.<schema_name>.<table_name>.<column_name> + <database_name>.<schema_name>.<table_name>.<column_name> = <database_name>.<schema_name>.<table_name>.<column_name> WHERE <condition> + AND + <condition2> Parameters =========== From 648c0acc74354796daf7189ae923c665d27ab5c5 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 11 Oct 2023 14:53:26 +0300 Subject: [PATCH 0953/1892] utility commands and cross-database --- reference/.DS_Store | Bin 0 -> 6148 bytes .../select_data_read_metrics.rst | 2 +- .../utility_commands/select_gpu_metrics.rst | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 reference/.DS_Store diff --git a/reference/.DS_Store b/reference/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..bed65e952775ee7e5a3d35b9f66011749755b34c GIT binary patch literal 6148 zcmeH~J8r{33`B>q3j=9Xy4=PG$PE^TeF9$~g@H7N13O6SJ$i<pCUWXP2!;STORfk> zuh5DBZ2x(F0VV(&x+``bW@gM+_`nU9uhac{dB47~;#J@&VrHyNnC;iLL<B@Y1Vlgt zL|{P#@)XDBc|p&lM-c%LSOx+AJ~X;(FCD4z>0pQvfVyTmjO&;ssLc!1UOG})p;=82 zR;?Ceh}WZ?+UmMqI#RP8R>OzYoz15hnq@nzF`-!xQ4j$Um=RcIKKc27r2jVm&svm< zfC&6E0=7P!4tu^-ovjbA=k?dB`g+i*aXG_}p8zI)6mRKa+;6_1_R^8c3Qa!(fk8n8 H{*=Hs1&|S$ literal 0 HcmV?d00001 diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst index 4a3e9ac98..9a732b3b9 100644 --- a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst @@ -11,7 +11,7 @@ The data read result is presented in this format: Year-Month-Day, showcasing dat Syntax ========== -.. code-block:: postgres +.. code-block:: console SELECT data_read_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) diff --git a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst index a355318f7..863f2b59a 100644 --- a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst @@ -11,7 +11,7 @@ An empty result indicates no usage deviation during the specified time. If the G Syntax ========== -.. code-block:: postgres +.. code-block:: console SELECT gpu_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) From de214e8f9f09b5e999ba4c9b391137e2197e25a6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:44:57 +0300 Subject: [PATCH 0954/1892] Update current_method_modification_methods.rst --- .../current_method_modification_methods.rst | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index be12a9b4c..9c56fb6ea 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -4,7 +4,6 @@ Modification Methods ************************** - .. contents:: :local: :depth: 1 @@ -15,18 +14,18 @@ You can modify your configuration using the **worker configuration file (config. The following is an example of a worker configuration file: -.. code-block:: postgres +.. code-block:: json { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” + "cluster": "/home/test_user/sqream_testing_temp/sqreamdb", + "gpu": 0, + "licensePath": "home/test_user/SQream/tests/license.enc", + "machineIP": "127.0.0.1", + "metadataServerIp": "127.0.0.1", + "metadataServerPort": 3105, + "port": 5000, + "useConfigIP": true, + "legacyConfigFilePath": "home/SQream_develop/SqrmRT/utils/json/legacy_congif.json" } You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. @@ -39,11 +38,11 @@ The Legacy configuration file provides access to the read/write flags. A link to The following is an example of the legacy configuration file: -.. code-block:: postgres +.. code-block:: json { - “developerMode”: true, - “reextentUse”: false, - “useClientLog”: true, - “useMetadataServer”” false + "developerMode": true, + "reextentUse": false, + "useClientLog": true, + "useMetadataServer": false } \ No newline at end of file From 75f8910f628fe40c7b531602e6f4f9a9c1b03cc9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 16 Oct 2023 17:03:39 +0300 Subject: [PATCH 0955/1892] REHL --- releases/4.3.rst | 4 ++-- releases/4.4.rst | 4 ++-- releases/4.5.rst | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index 0a705f640..b56a89964 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -130,8 +130,8 @@ Deprecations ► **CentOS Linux 7.x** * As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. -* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. -* **CentOS Linux 8.x** is now officially supported. + +* **REHL 8.x** is now officially supported. ► ``INT96`` diff --git a/releases/4.4.rst b/releases/4.4.rst index e240bdaf3..f7c1b8243 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -123,8 +123,8 @@ Deprecations ► **CentOS Linux 7.x** * As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. -* All new SQreamDB installations must use RHEL 8.X as the required operating system platform. -* **RHEL 8.x** is now officially supported. + +* **REHL 8.x** is now officially supported. ► ``INT96`` diff --git a/releases/4.5.rst b/releases/4.5.rst index 6d129d0e6..617b5e456 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -136,8 +136,8 @@ Deprecations ► **CentOS Linux 7.x** * As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. -* All new SQreamDB installations must use CentOS 8.X as the required operating system platform. -* **CentOS Linux 8.x** is now officially supported. + +* **REHL 8.x** is now officially supported. ► ``INT96`` From 8d76cdba0b30a5aefb8f1773e297ea31350cf5b1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Oct 2023 09:22:28 +0300 Subject: [PATCH 0956/1892] Update avro.rst --- data_ingestion/avro.rst | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index f471830af..eff3eb951 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -4,23 +4,16 @@ Avro **** -The **Ingesting Data from Avro** page describes ingesting data from Avro into SQream and includes the following: - - +**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. Avro files are represented using the **Object Container File** format, in which the Avro schema is encoded alongside binary data. Multiple files loaded in the same transaction are serialized using the same schema. If they are not serialized using the same schema, an error message is displayed. SQream uses the **.avro** extension for ingested Avro files. .. contents:: :local: :depth: 1 - -Overview -======== - -**Avro** is a well-known data serialization system that relies on schemas. Due to its flexibility as an efficient data storage method, SQream supports the Avro binary data format as an alternative to JSON. Avro files are represented using the **Object Container File** format, in which the Avro schema is encoded alongside binary data. Multiple files loaded in the same transaction are serialized using the same schema. If they are not serialized using the same schema, an error message is displayed. SQream uses the **.avro** extension for ingested Avro files. Making Avro Files Accessible to Workers ======================================= -To give workers access to files every node must have the same view of the storage being used. +To give workers access to files, every node must have the same view of the storage being used. The following apply for Avro files to be accessible to workers: @@ -225,8 +218,6 @@ When mapping objects to rows, each Avro object or message must contain one ``rec Ingesting Data into SQream ========================== -This section includes the following: - .. contents:: :local: :depth: 1 @@ -292,7 +283,7 @@ The following table shows the Avro parameter: Best Practices ============== -Because external tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Avro files into SQream. This lets you determine if your table output is identical to your originally inserted table. +Because foreign tables do not automatically verify the file integrity or structure, SQream recommends manually verifying your table output when ingesting Avro files into SQream. This lets you determine if your table output is identical to your originally inserted table. The following is an example of the output based on the **nba.avro** table: @@ -312,7 +303,7 @@ The following is an example of the output based on the **nba.avro** table: Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 -.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the external table structure that you created. +.. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the foreign table structure that you created. .. _additional_examples: @@ -328,7 +319,7 @@ This section includes the following additional examples of loading data into SQr Omitting Unsupported Column Types --------------------------------- -When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access external tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. +When loading data, you can omit columns using the ``NULL as`` argument. You can use this argument to omit unsupported columns from queries that access foreign tables. By omitting them, these columns will not be called and will avoid generating a "type mismatch" error. In the example below, the ``Position`` column is not supported due its type. @@ -340,7 +331,7 @@ In the example below, the ``Position`` column is not supported due its type. Modifying Data Before Loading ----------------------------- -One of the main reasons for staging data using the ``EXTERNAL TABLE`` argument is to examine and modify table contents before loading it into SQream. +One of the main reasons for staging data using the ``FOREIGN TABLE`` argument is to examine and modify table contents before loading it into SQream. For example, we can replace pounds with kilograms using the :ref:`create_table_as` statement @@ -348,7 +339,7 @@ In the example below, the ``Position`` column is set to the default ``NULL``. .. code-block:: postgres - CREATE TABLE nba AS + CREATE FOREIGN TABLE nba AS SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary FROM ext_nba ORDER BY weight; From fb10d6b439beaf2062fa7e2277f937a717acad24 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Oct 2023 11:26:35 +0300 Subject: [PATCH 0957/1892] SQLoader --- data_ingestion/ingesting_from_databases.rst | 2 +- .../sql/sql_syntax/cross_database_query.rst | 22 +++++-------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 97590401c..654796f9b 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.0.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index 98bcd699b..6df795df5 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -11,22 +11,12 @@ Syntax .. code-block:: sql - SELECT - <column_name2> [,column_name_2] [, ...] - FROM - <database_name>.<schema_name>.<table_name> - AS - <table_name> - JOIN - <database_name>.<schema_name>.<table_name> - AS - <table_name> - ON - <database_name>.<schema_name>.<table_name>.<column_name> = <database_name>.<schema_name>.<table_name>.<column_name> - WHERE - <condition> - AND - <condition2> + SELECT <column_name2> [,column_name_2] [, ...] + FROM <database_name>.<schema_name>.<table_name> AS <table_name> + JOIN <database_name>.<schema_name>.<table_name> AS <table_name> + ON <database_name>.<schema_name>.<table_name>.<column_name> = <database_name>.<schema_name>.<table_name>.<column_name> + [ WHERE <condition> ] + [ AND <condition2> ] Parameters =========== From 7e9053ccc22cced7cdba7af9a4738f99d14c141a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:54:02 +0300 Subject: [PATCH 0958/1892] Update cross_database_query.rst --- .../sql/sql_syntax/cross_database_query.rst | 123 ++++++++++++++++-- 1 file changed, 115 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index 6df795df5..4b29fa14d 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -1,7 +1,7 @@ .. _cross_database_query: *************************** -Cross Database Query +Cross-Database Query *************************** Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. @@ -11,13 +11,114 @@ Syntax .. code-block:: sql - SELECT <column_name2> [,column_name_2] [, ...] - FROM <database_name>.<schema_name>.<table_name> AS <table_name> - JOIN <database_name>.<schema_name>.<table_name> AS <table_name> - ON <database_name>.<schema_name>.<table_name>.<column_name> = <database_name>.<schema_name>.<table_name>.<column_name> - [ WHERE <condition> ] - [ AND <condition2> ] + -- SELECT statement + SELECT + <column_name1>, + <column_name2>, + ... + FROM + <database_name>.<schema_name>.<table_name> AS <alias1> + JOIN + <database_name>.<schema_name>.<table_name> AS <alias2> + ON + <alias1>.<join_column> = <alias2>.<join_column> + WHERE + <condition1> + AND <condition2> + + -- CREATE TABLE statement + CREATE TABLE + <database_name>.<schema_name>.<table_name> ( + <column_name1> <data_type1>, + <column_name2> <data_type2>, + ... + ) + + -- CREATE FOREIGN TABLE statement + CREATE FOREIGN TABLE + <foreign_schema_name>.<foreign_table_name> ( + <column_name1> <data_type1>, + <column_name2> <data_type2>, + ... + ) + SERVER <foreign_server_name> + OPTIONS ( + <option_name1> '<option_value1>', + <option_name2> '<option_value2>' + ) + + -- ALTER TABLE statement + ALTER TABLE + <database_name>.<schema_name>.<table_name> + ADD COLUMN + <new_column_name> <new_column_data_type> + + -- CREATE VIEW statement + CREATE VIEW + <database_name>.<schema_name>.<view_name> (<column_name1>, <column_name2>, ...) + AS + SELECT + <alias1>.<column_name1>, + <alias1>.<column_name2>, + ... + FROM + <database_name1>.<schema_name1>.<table_name1> AS <alias1> + JOIN + <database_name2>.<schema_name2>.<table_name2> AS <alias2> + ON + <alias1>.<join_column> = <alias2>.<join_column> + WHERE + <condition1> + AND <condition2> + + -- INSERT INTO statement + INSERT INTO + <database_name>.<schema_name>.<table_name> (<column_name1>, <column_name2>, ...) + VALUES + (<value1>, <value2>, ...) + + -- UPDATE statement + UPDATE + <database_name>.<schema_name>.<table_name> + SET + <column_name1> = <new_value1>, + <column_name2> = <new_value2> + WHERE + <condition> + + -- DELETE statement + DELETE FROM + <database_name>.<schema_name>.<table_name> + WHERE + <condition> + + -- TRUNCATE TABLE statement + TRUNCATE TABLE + <database_name>.<schema_name>.<table_name> + + -- DROP TABLE statement + DROP TABLE + <database_name>.<schema_name>.<table_name> + + -- ALTER DEFAULT SCHEMA statement + ALTER USER + <user_name> + SET SCHEMA + <new_default_schema> + + -- DROP SCHEMA statement + DROP SCHEMA + <schema_name> + + + -- DROP DATABASE statement + DROP DATABASE + <database_name> + + + + Parameters =========== @@ -81,4 +182,10 @@ Querying data from three tables in different databases: ON t1.id = t2.id JOIN database3.schema3.table3 t3 ON t2.id = t3.id - WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; \ No newline at end of file + WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; + +Set default schema: + +.. code-block:: sql + +ALTER DEFAULT SCHEMA \ No newline at end of file From 484560dff2b1e9f0158b7d65ea99f26662db4033 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 17 Oct 2023 14:59:08 +0300 Subject: [PATCH 0959/1892] Update cross_database_query.rst --- reference/sql/sql_syntax/cross_database_query.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index 4b29fa14d..3376ad75b 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -110,7 +110,6 @@ Syntax DROP SCHEMA <schema_name> - -- DROP DATABASE statement DROP DATABASE <database_name> From 96eab72a12a8543e1df1e371c9c3475964891c73 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:45:54 +0300 Subject: [PATCH 0960/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 2fecc0ac5..2d0bb751d 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -31,12 +31,18 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE FUNCTION`` | Create and drop functions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter database | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Schema** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | No permission restrictions on any activity within that schema | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Grants access to schema objects | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create tables in the schema | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter schema | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Table** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | :ref:`select` from the table | @@ -47,7 +53,7 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter on the table | +| ``DDL`` | Drop and alter table | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All the table permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -55,7 +61,7 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``EXECUTE`` | Use the function | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter on the function | +| ``DDL`` | Drop and alter function | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All function permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -177,6 +183,8 @@ GRANT Syntax GRANT { { SELECT + | INSERT + | UPDATE | DDL } [, ...] | ALL [PERMISSIONS] } @@ -192,7 +200,7 @@ GRANT Syntax -- Grant permissions at the Service level: GRANT { - { USAGE } [PERMISSIONS] + { USAGE } } ON { SERVICE <service_name> } TO <role> [, ...] @@ -286,6 +294,8 @@ REVOKE Syntax REVOKE { { SELECT + | INSERT + | UPDATE | DDL } [, ...] | ALL [PERMISSIONS]} ON @@ -399,7 +409,7 @@ Grant column-level permissions to a role: .. code-block:: postgres - GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; + GRANT SELECT, INSERT, UPDATE, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; Grant usage permissions on a service to a role: From 05dcd04f218548f124d47ce1810d0c486488b081 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 18 Oct 2023 12:52:09 +0300 Subject: [PATCH 0961/1892] Update cross_database_query.rst --- .../sql/sql_syntax/cross_database_query.rst | 36 +++++++------------ 1 file changed, 12 insertions(+), 24 deletions(-) diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index 3376ad75b..b86ddbb5f 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -12,6 +12,7 @@ Syntax .. code-block:: sql -- SELECT statement + SELECT <column_name1>, <column_name2>, @@ -27,6 +28,7 @@ Syntax AND <condition2> -- CREATE TABLE statement + CREATE TABLE <database_name>.<schema_name>.<table_name> ( <column_name1> <data_type1>, @@ -35,25 +37,23 @@ Syntax ) -- CREATE FOREIGN TABLE statement + CREATE FOREIGN TABLE - <foreign_schema_name>.<foreign_table_name> ( + <foreign_database_name>.<foreign_schema_name>.<foreign_table_name> ( <column_name1> <data_type1>, <column_name2> <data_type2>, ... - ) - SERVER <foreign_server_name> - OPTIONS ( - <option_name1> '<option_value1>', - <option_name2> '<option_value2>' - ) + ) -- ALTER TABLE statement + ALTER TABLE <database_name>.<schema_name>.<table_name> ADD COLUMN <new_column_name> <new_column_data_type> -- CREATE VIEW statement + CREATE VIEW <database_name>.<schema_name>.<view_name> (<column_name1>, <column_name2>, ...) AS @@ -72,12 +72,14 @@ Syntax AND <condition2> -- INSERT INTO statement + INSERT INTO <database_name>.<schema_name>.<table_name> (<column_name1>, <column_name2>, ...) VALUES (<value1>, <value2>, ...) -- UPDATE statement + UPDATE <database_name>.<schema_name>.<table_name> SET @@ -87,37 +89,23 @@ Syntax <condition> -- DELETE statement + DELETE FROM <database_name>.<schema_name>.<table_name> WHERE <condition> -- TRUNCATE TABLE statement + TRUNCATE TABLE <database_name>.<schema_name>.<table_name> -- DROP TABLE statement + DROP TABLE <database_name>.<schema_name>.<table_name> - -- ALTER DEFAULT SCHEMA statement - ALTER USER - <user_name> - SET SCHEMA - <new_default_schema> - - -- DROP SCHEMA statement - DROP SCHEMA - <schema_name> - -- DROP DATABASE statement - DROP DATABASE - <database_name> - - - - - Parameters =========== From 2e2418933551372d42ac4de7c3fa7e60e274dd34 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 18 Oct 2023 13:21:42 +0300 Subject: [PATCH 0962/1892] Update cross_database_query.rst --- reference/sql/sql_syntax/cross_database_query.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index b86ddbb5f..c5fbe346d 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -6,6 +6,9 @@ Cross-Database Query Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. +To ensure optimal performance, it is advised to refrain from querying more than 10 databases in a single query. + + Syntax ========== @@ -170,9 +173,4 @@ Querying data from three tables in different databases: JOIN database3.schema3.table3 t3 ON t2.id = t3.id WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; - -Set default schema: - -.. code-block:: sql -ALTER DEFAULT SCHEMA \ No newline at end of file From f574e269be8c71001829f791ad4a360931c1a253 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 18 Oct 2023 15:33:45 +0300 Subject: [PATCH 0963/1892] Update workload_manager.rst --- feature_guides/workload_manager.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/feature_guides/workload_manager.rst b/feature_guides/workload_manager.rst index 484980532..aa18c4823 100644 --- a/feature_guides/workload_manager.rst +++ b/feature_guides/workload_manager.rst @@ -86,7 +86,6 @@ Creating the Configuration { "debugNetworkSession": false, - "developerMode": true, "diskSpaceMinFreePercent": 1, "maxNumAutoCompressedChunksThreshold" : 1, "insertMergeRowsThreshold":40000000, From a4a732ad24bd1a087017b99515466c82908620f7 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:25:56 +0300 Subject: [PATCH 0964/1892] Update index.rst --- upgrade_guide/index.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index 948861820..d9c8b76f8 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -19,10 +19,12 @@ Upgrade Procedure .. code-block:: console $ select backup_metadata('out_path'); + + SQream runs the Garbage Collector and creates a clean backup tarball package. SQream recommends storing the generated back-up locally in case needed. - SQream runs the Garbage Collector and creates a clean backup tarball package. + 2. Shut down all SQream services. From d3601ef909d3c4ccfa270888da95de10bef4e09d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:22:34 +0300 Subject: [PATCH 0965/1892] Various --- .../installing_sqream_with_binary.rst | 6 +- .../access_control_permissions.rst | 62 ++++++++----------- .../sql/sql_syntax/cross_database_query.rst | 14 ++--- upgrade_guide/index.rst | 6 +- 4 files changed, 36 insertions(+), 52 deletions(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index bb26a8180..c11b36584 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -3,6 +3,7 @@ ********************************************* Installing SQream Using Binary Packages ********************************************* + This procedure describes how to install SQream using Binary packages and must be done on all servers. **To install SQream using Binary packages:** @@ -170,12 +171,9 @@ It would be same on server running metadataserver and different on other server If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream <hdfs>`. - - - - Upgrading SQream Version ------------------------- + Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. **To upgrade your version of SQream:** diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 2d0bb751d..23d28b031 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -4,11 +4,11 @@ Permissions ************** -SQreamDB’s primary permission object is a role. The role operates in a dual capacity as both a user and a group. In its user role, it may execute operations like creating tables, querying data, and administering the database, depending on its permissions. The role’s group attribute allows it to extend its permissions to roles defined as its group members. Information about permissions for all roles is stored in the metadata. +SQreamDB’s primary permission object is a role. The role operates in a dual capacity as both a user and a group. As a user, a role may have permissions to execute operations like creating tables, querying data, and administering the database. The group attribute may be thought of as a membership. As a group, a role may extend its permissions to other roles defined as its group members. This becomes handy when privileged roles wish to extend their permissions and grant multiple permissions to multiple roles. The information about all system role permissions is stored in the metadata. -There are two main types of permissions: global and object-level. Global permissions belong to ``SUPERUSER`` roles, allowing unrestricted access to all system and database activities. Object-level permissions apply to non-``SUPERUSER`` roles and can be assigned to databases, schemas, tables, functions, views, foreign tables, columns, catalogs, and services. +There are two types of permissions: global and object-level. Global permissions belong to ``SUPERUSER`` roles, allowing unrestricted access to all system and database activities. Object-level permissions apply to non-``SUPERUSER`` roles and can be assigned to databases, schemas, tables, functions, views, foreign tables, columns, catalogs, and services. -The following tables describe the required permissions for performing and executing operations on various SQreamDB objects. +The following table describe the required permissions for performing and executing operations on various SQreamDB objects. +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Permission** | **Description** | @@ -31,18 +31,12 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE FUNCTION`` | Create and drop functions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter database | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Schema** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SUPERUSER`` | No permission restrictions on any activity within that schema | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Grants access to schema objects | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create tables in the schema | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter schema | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Table** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | :ref:`select` from the table | @@ -53,7 +47,7 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DELETE`` | :ref:`delete` and :ref:`truncate` on the table | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter table | +| ``DDL`` | Drop and alter on the table | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All the table permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -61,7 +55,7 @@ The following tables describe the required permissions for performing and execut +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``EXECUTE`` | Use the function | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Drop and alter function | +| ``DDL`` | Drop and alter on the function | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All function permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -92,11 +86,13 @@ The following tables describe the required permissions for performing and execut | ``USAGE`` | Using a specific service | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +Syntax +====== -GRANT Syntax -============ +Permissions may be granted or revoked using the following syntax. -:ref:`grant` gives permissions to a role. +GRANT +------ .. code-block:: postgres @@ -153,7 +149,7 @@ GRANT Syntax | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] } - TO <role> [, ...]; + TO <role> [, ...] GRANT { @@ -167,7 +163,7 @@ GRANT Syntax { | CATALOG <catalog_name> [, ...] } - TO <role> [, ...]; + TO <role> [, ...] -- Grant execute function permission: GRANT @@ -183,8 +179,6 @@ GRANT Syntax GRANT { { SELECT - | INSERT - | UPDATE | DDL } [, ...] | ALL [PERMISSIONS] } @@ -195,12 +189,12 @@ GRANT Syntax | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] } - TO <role> [, ...]; + TO <role> [, ...] -- Grant permissions at the Service level: GRANT { - { USAGE } + { USAGE } [PERMISSIONS] } ON { SERVICE <service_name> } TO <role> [, ...] @@ -214,10 +208,8 @@ GRANT Syntax TO <role2> [,...] [WITH ADMIN OPTION] -REVOKE Syntax -============= - -:ref:`revoke` removes permissions from a role. +REVOKE +------- .. code-block:: postgres @@ -274,7 +266,7 @@ REVOKE Syntax | FOREIGN TABLE <table_name> [, ...] | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] } - FROM <role> [, ...]; + FROM <role> [, ...] REVOKE { @@ -288,14 +280,12 @@ REVOKE Syntax { | CATALOG <catalog_name> [, ...] } - FROM <role> [, ...]; + FROM <role> [, ...] -- Revoke permissions at the column level: REVOKE { { SELECT - | INSERT - | UPDATE | DDL } [, ...] | ALL [PERMISSIONS]} ON @@ -304,9 +294,8 @@ REVOKE Syntax | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] } - FROM <role> [, ...]; + FROM <role> [, ...] - -- Revoke permissions at the service level: REVOKE { @@ -325,7 +314,7 @@ REVOKE Syntax FROM <role2> [, ...] Altering Default Permissions -============================ +----------------------------- The default permissions system (See :ref:`alter_default_permissions`) can be used to automatically grant permissions to newly @@ -351,7 +340,8 @@ schema statement is run. } { grant_clause | DROP grant_clause } - TO ROLE { role_name | public }; + TO ROLE { role_name | public + } grant_clause ::= GRANT @@ -372,12 +362,12 @@ schema statement is run. Examples ======== -GRANT Examples +GRANT -------------- Grant superuser privileges and login capability to a role: -.. code-block:: postgres +.. code-block:: sql GRANT SUPERUSER, LOGIN TO role_name; @@ -409,7 +399,7 @@ Grant column-level permissions to a role: .. code-block:: postgres - GRANT SELECT, INSERT, UPDATE, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; + GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; Grant usage permissions on a service to a role: @@ -430,7 +420,7 @@ Grant role2 the ability to grant role1 to other roles: GRANT role1 TO role2 WITH ADMIN OPTION; -REVOKE Examples +REVOKE --------------- Revoke superuser privileges or login capability from a role: diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index c5fbe346d..8b525d386 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -4,7 +4,7 @@ Cross-Database Query *************************** -Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. +Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQreamDB cluster, through the execution of a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. To ensure optimal performance, it is advised to refrain from querying more than 10 databases in a single query. @@ -42,7 +42,7 @@ Syntax -- CREATE FOREIGN TABLE statement CREATE FOREIGN TABLE - <foreign_database_name>.<foreign_schema_name>.<foreign_table_name> ( + <database_name>.<schema_name>.<table_name> ( <column_name1> <data_type1>, <column_name2> <data_type2>, ... @@ -119,15 +119,15 @@ Parameters * - Parameter - Description * - ``column_name`` - - The column to perform a ``JOIN`` operation on + - The name of a specific column to read or write data from * - ``database_name`` - - The SQreamDB database to perform a ``JOIN`` operation on + - The name of a specific database to read or write data from * - ``schema_name`` - - The schema name of the database to perform a ``JOIN`` operation on + - The name of a specific schema to read or write data within * - ``table_name`` - - The table to perform a ``JOIN`` operation on + - The name of a specific table to read or write data from * - ``condition`` - - The condition for performing a ``JOIN`` operation + - The condition for performing a specific operation Examples ========= diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index d9c8b76f8..e287be3e8 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -4,8 +4,6 @@ Upgrade Guide ***************** - - Upgrading to Version 2022.1.7 ------------------------------ @@ -19,12 +17,10 @@ Upgrade Procedure .. code-block:: console $ select backup_metadata('out_path'); - - SQream runs the Garbage Collector and creates a clean backup tarball package. SQream recommends storing the generated back-up locally in case needed. - + SQream runs the Garbage Collector and creates a clean backup tarball package. 2. Shut down all SQream services. From 29862828bedb01ad0dcb0e7f54a8456c69abf294 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:31:33 +0300 Subject: [PATCH 0966/1892] GRANT and REVOKE --- .../access_control_commands/grant.rst | 190 +++++++++++------- .../access_control_commands/revoke.rst | 186 +++++++++-------- 2 files changed, 213 insertions(+), 163 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index b987e4bfc..283ce3f3a 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -20,83 +20,117 @@ Syntax .. code-block:: postgres - grant_statement ::= - { - -- Grant permissions at the cluster level: - GRANT - { SUPERUSER - | LOGIN - | PASSWORD 'password' - } - TO role_name [, ...] - - -- Grant permissions at the database level: - | GRANT - { - { CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION - } [, ...] - | ALL [PERMISSIONS] - } - ON DATABASE database_name [, ...] - TO role_name [, ...] - - -- Grant permissions at the schema level: - | GRANT - { - { CREATE - | DDL - | USAGE - | SUPERUSER - } [, ...] - | ALL [PERMISSIONS ] - } - ON SCHEMA schema_name [, ...] - TO role_name [, ...] - - -- Grant permissions at the object level: - | GRANT - { - { SELECT - | INSERT - | DELETE - | DDL - } [, ...] - | ALL [PERMISSIONS] - } - ON { TABLE table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...]} - TO role_name [, ...] - - - -- Grant execute function permission: - | GRANT - { ALL - | EXECUTE - | DDL - } - ON FUNCTION function_name - TO role_name [, ...] - - - -- Pass permissions between roles by granting one role to another: - | GRANT role_name [, ...] - TO role_name_2 [, ...] - [ WITH ADMIN OPTION ] - - ; - - role_name ::= identifier - - role_name2 ::= identifier - - database_name ::= identifier - - table_name ::= identifier - - schema_name ::= identifier + -- Grant permissions at the instance/ storage cluster level: + GRANT + { + SUPERUSER + | LOGIN + | PASSWORD '<password>' + } + TO <role> [, ...] + + -- Grant permissions at the database level: + GRANT + { + { CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] + } + ON DATABASE <database> [, ...] + TO <role> [, ...] + + -- Grant permissions at the schema level: + GRANT + { + { CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + } + ON SCHEMA <schema> [, ...] + TO <role> [, ...] + + -- Grant permissions at the object level: + GRANT + { + { SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + } + ON + { + TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...] + | VIEW <schema_name.view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + } + TO <role> [, ...] + + GRANT + { + { SELECT + | INSERT + | DELETE + | UPDATE } [, ...] + | ALL [PERMISSIONS] + } + ON + { + | CATALOG <catalog_name> [, ...] + } + TO <role> [, ...] + + -- Grant execute function permission: + GRANT + { + ALL + | EXECUTE + | DDL + } + ON FUNCTION function_name + TO role; + + -- Grant permissions at the column level: + GRANT + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] + } + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] + | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + } + TO <role> [, ...] + + -- Grant permissions at the Service level: + GRANT + { + { USAGE } [PERMISSIONS] + } + ON { SERVICE <service_name> } + TO <role> [, ...] + + -- Allows role2 to use permissions granted to role1 + GRANT <role1> [, ...] + TO <role2> + + -- Also allows the role2 to grant role1 to other roles: + GRANT <role1> [, ...] + TO <role2> [,...] [WITH ADMIN OPTION] + Parameters ============ @@ -111,7 +145,7 @@ The following table describes the ``GRANT`` parameters: - Description * - ``role_name`` - The name of the role to grant permissions to - * - ``table_name``, ``database_name``, ``schema_name``, ``function_name`` + * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name`` - Object to grant permissions on. * - ``WITH ADMIN OPTION`` - diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index ade121815..8491911e9 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -20,83 +20,105 @@ Syntax .. code-block:: postgres - grant_statement ::= - { - -- revoke permissions at the cluster level: - REVOKE - { SUPERUSER - | LOGIN - | PASSWORD 'password' - } - FROM role_name [, ...] - - -- Revoke permissions at the database level: - | REVOKE - { - { CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION - } [, ...] - | ALL [PERMISSIONS] - } - ON DATABASE database_name [, ...] - FROM role_name [, ...] - - -- Revoke permissions at the schema level: - | REVOKE - { - { CREATE - | DDL - | USAGE - | SUPERUSER - } [, ...] - | ALL [PERMISSIONS ] - } - ON SCHEMA schema_name [, ...] - FROM role_name [, ...] - - -- Revoke permissions at the object level: - | REVOKE - { - { SELECT - | INSERT - | DELETE - | DDL - } [, ...] - | ALL [PERMISSIONS] - } - ON { TABLE table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...]} - FROM role_name [, ...] - - - -- Revoke execute function permission: - | REVOKE - { ALL - | EXECUTE - | DDL - } - ON FUNCTION function_name - FROM role_name [, ...] - - - -- Remove permissions between roles by revoking role membership: - | REVOKE [ WITH ADMIN OPTION ] role_name [, ...] - FROM role_name_2 - - - ; - - role_name ::= identifier - - role_name2 ::= identifier - - database_name ::= identifier - - table_name ::= identifier - - schema_name ::= identifier + -- Revoke permissions at the instance/ storage cluster level: + REVOKE + { + SUPERUSER + | LOGIN + | PASSWORD + } + FROM <role> [, ...] + + -- Revoke permissions at the database level: + REVOKE + { + { CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION }[, ...] + | ALL [PERMISSIONS] + } + ON DATABASE <database> [, ...] + FROM <role> [, ...] + + -- Revoke permissions at the schema level: + REVOKE + { + { CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + } + ON SCHEMA <schema> [, ...] + FROM <role> [, ...] + + -- Revoke permissions at the object level: + REVOKE + { + { SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL + } + ON + { + [ TABLE ] <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...] + | VIEW <schema_name.view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + } + FROM <role> [, ...] + + REVOKE + { + { SELECT + | INSERT + | DELETE + | UPDATE } [, ...] + | ALL + } + ON + { + | CATALOG <catalog_name> [, ...] + } + FROM <role> [, ...] + + -- Revoke permissions at the column level: + REVOKE + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS]} + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] + } + FROM <role> [, ...] + + -- Revoke permissions at the service level: + REVOKE + { + { USAGE } [, ...] + | ALL [PERMISSIONS] + } + ON { SERVICE <service_name> } + FROM <role> [, ...] + + -- Removes access to permissions in role1 by role 2 + REVOKE [ADMIN OPTION FOR] <role1> [, ...] + FROM <role2> [, ...] + + -- Removes permissions to grant role1 to additional roles from role2 + REVOKE [ADMIN OPTION FOR] <role1> [, ...] + FROM <role2> [, ...] Parameters ========== @@ -109,19 +131,13 @@ Parameters - Description * - ``role_name`` - The name of the role to revoke permissions from - * - ``table_name``, ``database_name``, ``schema_name``, ``function_name`` - - Object to revoke permissions on. + * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name`` + - Object to revoke permissions from * - ``WITH ADMIN OPTION`` - If ``WITH ADMIN OPTION`` is specified, the role that has the admin option can in turn grant membership in the role to others, and revoke membership in the role as well. Specifying ``WITH ADMIN OPTION`` for revocation will return the role to an ordinary role. An ordinary role cannot grant or revoke membership. - - - -.. include:: grant.rst - :start-line: 127 - :end-line: 180 Examples From ee12546cbb6d5086b13d16722f0a02f688ffa453 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Oct 2023 11:45:54 +0300 Subject: [PATCH 0967/1892] Update alter_default_permissions.rst --- .../alter_default_permissions.rst | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 6d5208e98..c2de52db5 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -22,35 +22,38 @@ The ``SUPERUSER`` permission is required to alter default permissions. Syntax ====== -The following is the syntax for altering default permissions: - .. code-block:: postgres - alter_default_permissions_statement ::= - ALTER DEFAULT PERMISSIONS FOR { target_role_name | ALL ROLES } - [IN schema_name, ...] - FOR { TABLES | SCHEMAS } - { grant_clause [, ...] | DROP grant_clause[, ...]} - TO { role_name [, ...] | public }; - - grant_clause ::= - GRANT - { SUPERUSER + ALTER DEFAULT PERMISSIONS FOR target_role_name + [IN schema_name, ...] + FOR { + SCHEMAS + | TABLES + | FOREIGN TABLE + | VIEWS + | COLUMNS + | SAVED_QUERIES + } + { grant_clause + | DROP grant_clause } + TO ROLE { role_name | public + } + + grant_clause ::= + GRANT + { CREATE FUNCTION + | SUPERUSER + | CONNECT | CREATE | USAGE | SELECT | INSERT - | UPDATE | DELETE | DDL + | UPDATE + | EXECUTE | ALL - } [, ...] - - target_role_name ::= identifier - - role_name ::= identifier - - schema_name ::= identifier + } Supported Permissions From bf7b264cad842d7bd0c45f7f8a32549f431edb2a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Oct 2023 15:07:25 +0300 Subject: [PATCH 0968/1892] Upgrade guide --- .../installing_sqream_with_binary.rst | 103 ---------------- upgrade_guide/index.rst | 116 ++++++++++++++++++ 2 files changed, 116 insertions(+), 103 deletions(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index c11b36584..be2502534 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -171,106 +171,3 @@ It would be same on server running metadataserver and different on other server If you have an HDFS environment, see :ref:`Configuring an HDFS Environment for the User sqream <hdfs>`. -Upgrading SQream Version -------------------------- - -Upgrading your SQream version requires stopping all running services while you manually upgrade SQream. - -**To upgrade your version of SQream:** - -1. Stop all actively running SQream services. - -.. note:: All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. - -For an example of stopping actively running SQream services, see :ref:`Launching SQream with Monit <launching_sqream_with_monit>`. - -2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: - - .. code-block:: console - - $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. - -3. Replace the old version ``sqream-db-v2021.1``, with the new version ``sqream-db-v2021.1``: - - .. code-block:: console - - $ cd /home/sqream - $ mkdir tempfolder - $ mv sqream-db-v2021.1.tar.gz tempfolder/ - $ cd tempfolder/ - $ tar -xf sqream-db-v2021.1.tar.gz - $ sudo mv sqream /usr/local/sqream-db-v2021.1 - $ cd /usr/local - $ sudo chown -R sqream:sqream sqream-db-v2021.1 - -4. Remove the symbolic link: - - .. code-block:: console - - $ sudo rm sqream - -5. Create a new symbolic link named "sqream" pointing to the new version: - - .. code-block:: console - - $ sudo ln -s sqream-db-v2021.1 sqream - -6. Verify that the symbolic SQream link points to the real folder: - - .. code-block:: console - - $ ls -l - - The following is an example of the correct output: - - .. code-block:: console - - $ sqream -> sqream-db-v2021.1 - -7. **Optional-** (for major versions) Upgrade your version of SQream storage cluster, as shown in the following example: - - .. code-block:: console - - $ cat /etc/sqream/sqream1_config.json |grep cluster - $ ./upgrade_storage <cluster path> - - The following is an example of the correct output: - - .. code-block:: console - - get_leveldb_version path{<cluster path>} - current storage version 23 - upgrade_v24 - upgrade_storage to 24 - upgrade_storage to 24 - Done - upgrade_v25 - upgrade_storage to 25 - upgrade_storage to 25 - Done - upgrade_v26 - upgrade_storage to 26 - upgrade_storage to 26 - Done - validate_leveldb - ... - upgrade_v37 - upgrade_storage to 37 - upgrade_storage to 37 - Done - validate_leveldb - storage has been upgraded successfully to version 37 - -8. Verify that the latest version has been installed: - - .. code-block:: console - - $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" - - The following is an example of the correct output: - - .. code-block:: console - - v2021.1 - 1 row - time: 0.050603s - -For more information, see the :ref:`upgrade_storage<upgrade_storage_cli_reference>` command line program. - -For more information about installing Studio on a stand-alone server, see :ref:`Installing Studio on a Stand-Alone Server<installing_studio_on_stand_alone_server>`. \ No newline at end of file diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index e287be3e8..2f86d7311 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -4,6 +4,122 @@ Upgrade Guide ***************** +Upgrading your SQream version requires stopping all running services. + +1. Stop all actively running SQream services. + + All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. + +2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: + +.. code-block:: console + + $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. + +3. Replace the old version ``sqream-db-v2021.1``, with the new version ``sqream-db-v2021.1``: + +.. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ cd tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + +.. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + +.. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQream link points to the real folder: + +.. code-block:: console + + $ ls -l + + -- Output example: + + $ sqream -> sqream-db-v2021.1 + +7. Upgrade your version of SQream storage. + + a. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQream recommends storing the generated back-up locally in case needed. + + SQream runs the Garbage Collector and creates a clean backup tarball package. + + b. Shut down all SQream services. + + c. Extract the recently created back-up file. + + d. Replace your current metadata with the metadata you stored in the back-up file. + + e. Navigate to the new SQream package bin folder. + + f. Get the cluster path + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + + g. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <RocksDB path> + + -- Output example: + + get_leveldb_version path{<cluster path>} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + +.. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + -- Output example: + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the :ref:`upgrade_storage<upgrade_storage_cli_reference>` command line program. + + + Upgrading to Version 2022.1.7 ------------------------------ From f900ff8904e143a775d5709a20dc66cfc0f69ab2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 19 Oct 2023 16:38:37 +0300 Subject: [PATCH 0969/1892] SELECT data read and GPU --- .../select_data_read_metrics.rst | 60 +++++++++++++------ .../utility_commands/select_gpu_metrics.rst | 52 ++++++++++++---- 2 files changed, 82 insertions(+), 30 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst index 9a732b3b9..e2fb55acb 100644 --- a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst @@ -11,7 +11,7 @@ The data read result is presented in this format: Year-Month-Day, showcasing dat Syntax ========== -.. code-block:: console +.. code-block:: sql SELECT data_read_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) @@ -35,33 +35,59 @@ Parameters - Mandatory - The ending date for the data retrieval period +Output +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``date`` + - Date of data read + * - ``actual_data_read`` + - Total data read within the specified date + * - ``data_read_limit_license_value`` + - Data read quota limit as per license plan + + Examples =========== Daily data reads are cumulative. For a comprehensive view of your data read usage, execute a monthly data read. -.. code-block:: console +.. code-block:: postgres - master=> SELECT data_read_metrics('daily','2023-05-01', '2023-05-05); - 2023-May-01, 20GB, 5000GB - 2023-May-02, 50GB, 5000GB - 2023-May-03, 10GB, 5000GB - 2023-May-04, 5GB, 5000GB - 2023-May-05, 4GB, 5000GB - 2 rows - time: 0.103436s + SELECT data_read_metrics('daily','2023-05-01', '2023-05-05); + +Output: + +.. code-block:: console + date | actual_data_read | data_read_limit_license_value + ------------+--------------------+------------------------------ + 2023-May-01 | 20GB | 5000GB + 2023-May-02 | 50GB | 5000GB + 2023-May-03 | 10GB | 5000GB + 2023-May-04 | 5GB | 5000GB + 2023-May-05 | 4GB | 5000GB + + Monthly data reads: -.. code-block:: console +.. code-block:: postgres - master=> SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05); - 2023 May, 20GB, 5000GB - 2023 June, 50GB, 5000GB - 2 rows - time: 0.103436s - + SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05); + +Output: +.. code-block:: console + + date | actual_data_read | data_read_limit_license_value + ------------+--------------------+------------------------------ + 2023 May, | 20GB | 5000GB + 2023 June | 50GB | 5000GB Permissions ============= diff --git a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst index 863f2b59a..8a89d6195 100644 --- a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst @@ -11,7 +11,7 @@ An empty result indicates no usage deviation during the specified time. If the G Syntax ========== -.. code-block:: console +.. code-block:: sql SELECT gpu_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) @@ -35,30 +35,56 @@ Parameters - Mandatory - The ending date for the data retrieval period +Output +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``date`` + - Date and time of highest GPU usage deviation + * - ``actual_number_of_gpus`` + - GPU usage deviation + * - ``data_read_limit_license_value`` + - GPU quota limit as per license plan + Examples =========== Daily GPU usage: +.. code-block:: postgres + + SELECT gpu_metrics('daily','2023-05-01', '2023-05-05); + +Output + .. code-block:: console - master=> SELECT gpu_metrics('daily','2023-05-01', '2023-05-05); - 2023-May-01, 2,1 - 2023-May-02, 3,1 - 2023-May-03, 3,1 - 2 rows - time: 0.103436s + date | actual_number_of_gpus | data_read_limit_license_value + --------------+-------------------------+--------------------------------- + 2023-May-01 | 2 | 1 + 2023-May-02 | 3 | 1 + 2023-May-03 | 3 | 1 + Monthly GPU usage: -.. code-block:: console +.. code-block:: sql - master=> SELECT gpu_metrics('monthly', '2023-04-01', '2023-06-05'); - 2023 Apr, 2,1 - 1 rows - time: 0.155396s - + SELECT gpu_metrics('monthly', '2023-04-01', '2023-06-05'); + +Output + +.. code-block:: console + date | actual_number_of_gpus | data_read_limit_license_value + --------------+-------------------------+--------------------------------- + 2023 Apr | 2 | 1 + Permissions ============= From 015e534a0e5769520cdca4f0297c7b28fb6b3b8c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 23 Oct 2023 16:15:56 +0300 Subject: [PATCH 0970/1892] Upgrade Guides --- feature_guides/compression.rst | 2 +- upgrade_guide/index.rst | 395 +----------------- upgrade_guide/version_upgrade.rst | 120 ++++++ .../version_upgrade_configurations.rst | 43 ++ 4 files changed, 171 insertions(+), 389 deletions(-) create mode 100644 upgrade_guide/version_upgrade.rst create mode 100644 upgrade_guide/version_upgrade_configurations.rst diff --git a/feature_guides/compression.rst b/feature_guides/compression.rst index 4c0271e31..21e39b082 100644 --- a/feature_guides/compression.rst +++ b/feature_guides/compression.rst @@ -80,7 +80,7 @@ The following table shows the supported compression methods: - General purpose compression, used for texts - CPU * - ``RLE`` - - Integer types, dates and timestamps + - ``integer`` types, ``dates``, ``timestamps``, and ``text`` - Run-Length Encoding. This replaces sequences of values with a single pair. It is best for low cardinality columns that are used to sort data (``ORDER BY``). - GPU * - ``SEQUENCE`` diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index 2f86d7311..a523f3363 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -1,393 +1,12 @@ -.. _upgrade_guide: +.. _upgrade_guides: ***************** -Upgrade Guide +Upgrade Guides ***************** -Upgrading your SQream version requires stopping all running services. - -1. Stop all actively running SQream services. - - All SQream services must remain stopped while the upgrade is in process. Ensuring that SQream services remain stopped depends on the tool being used. - -2. Verify that SQream has stopped listening on ports **500X**, **510X**, and **310X**: - -.. code-block:: console - - $ sudo netstat -nltp #to make sure sqream stopped listening on 500X, 510X and 310X ports. - -3. Replace the old version ``sqream-db-v2021.1``, with the new version ``sqream-db-v2021.1``: - -.. code-block:: console - - $ cd /home/sqream - $ mkdir tempfolder - $ mv sqream-db-v2021.1.tar.gz tempfolder/ - $ cd tempfolder/ - $ tar -xf sqream-db-v2021.1.tar.gz - $ sudo mv sqream /usr/local/sqream-db-v2021.1 - $ cd /usr/local - $ sudo chown -R sqream:sqream sqream-db-v2021.1 - -4. Remove the symbolic link: - -.. code-block:: console - - $ sudo rm sqream - -5. Create a new symbolic link named "sqream" pointing to the new version: - -.. code-block:: console - - $ sudo ln -s sqream-db-v2021.1 sqream - -6. Verify that the symbolic SQream link points to the real folder: - -.. code-block:: console - - $ ls -l - - -- Output example: - - $ sqream -> sqream-db-v2021.1 - -7. Upgrade your version of SQream storage. - - a. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - - b. Shut down all SQream services. - - c. Extract the recently created back-up file. - - d. Replace your current metadata with the metadata you stored in the back-up file. - - e. Navigate to the new SQream package bin folder. - - f. Get the cluster path - - .. code-block:: console - - $ cat /etc/sqream/sqream1_config.json |grep cluster - - g. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <RocksDB path> - - -- Output example: - - get_leveldb_version path{<cluster path>} - current storage version 23 - upgrade_v24 - upgrade_storage to 24 - upgrade_storage to 24 - Done - upgrade_v25 - upgrade_storage to 25 - upgrade_storage to 25 - Done - upgrade_v26 - upgrade_storage to 26 - upgrade_storage to 26 - Done - validate_leveldb - ... - upgrade_v37 - upgrade_storage to 37 - upgrade_storage to 37 - Done - validate_leveldb - storage has been upgraded successfully to version 37 - -8. Verify that the latest version has been installed: - -.. code-block:: console - - $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" - - -- Output example: - - v2021.1 - 1 row - time: 0.050603s - -For more information, see the :ref:`upgrade_storage<upgrade_storage_cli_reference>` command line program. - - - -Upgrading to Version 2022.1.7 ------------------------------- - -Version 2022.1.7 uses storage version 43. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <RocksDB path> - -Upgrading to Version 2022.1.6 ---------------------------------- - -Version 2022.1.6 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <RocksDB path> - -Upgrading to Version 2022.1.5 -------------------------------- - -Version 2022.1.5 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. +.. toctree:: + :maxdepth: 1 + :titlesonly: -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <RocksDB path> - -Upgrading to Version 2022.1.4 ------------------------------- - -Version 2022.1.4 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - -Upgrading to Version 2022.1.3 ---------------------------------- - -Version 2022.1.3 uses storage version 42. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -In SQream version 2022.1.3 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - -Upgrading to Version 2022.1.2 -------------------------------- - -Version 2022.1.2 uses storage version 41. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - -Upgrading to Version 2022.1.1 ------------------------------- - -Operation and Configuration Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Version 2022.1.1 uses storage version 40. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -In compliance with GDPR standards, version 2022.1.1 requires a strong password policy when accessing the CLI and Studio. For more information, see :ref:`Password Policy<access_control_password_policy>`. - -The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. For more information, see :ref:`Adjusting the Permitted Log-In Attempts<login_max_retries>`. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - -Upgrading to Version 2022.1 ------------------------------ - -Operation and Configuration Changes -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Version 2022.1 uses storage version 40. If you're using an older storage version, you need to upgrade to the latest one using the :ref:`Upgrading SQreamDB Version<installing_sqream_with_binary>` guide. - -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQreamDB, see the :ref:`Using Legacy String Literals<use_legacy_string_literals>` configuration flag. - -Upgrade Procedure -^^^^^^^^^^^^^^^^^^ - -1. Generate a backup of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path', 'single_file'); - - SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created backup file. - -4. Replace your current metadata with the metadata you stored in the backup file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> \ No newline at end of file + version_upgrade + version_upgrade_configurations \ No newline at end of file diff --git a/upgrade_guide/version_upgrade.rst b/upgrade_guide/version_upgrade.rst new file mode 100644 index 000000000..f556e74e9 --- /dev/null +++ b/upgrade_guide/version_upgrade.rst @@ -0,0 +1,120 @@ +.. _version_upgrade: + +***************** +Version Upgrade +***************** + +Upgrading your SQreamDB version requires stopping all running services. + +1. Stop all actively running SQreamDB services. + + Ensuring that SQreamDB services are at a halt depends on the tool being used. + +2. Verify that SQreamDB has stopped listening on ports **500X**, **510X**, and **310X**: + +.. code-block:: console + + $ sudo netstat -nltp #to make sure SQreamDB stopped listening on 500X, 510X and 310X ports. + +3. Replace the old SQreamDB version with the new version, such as in the following example: + +.. code-block:: console + + $ cd /home/sqream + $ mkdir tempfolder + $ mv sqream-db-v2021.1.tar.gz tempfolder/ + $ cd tempfolder/ + $ tar -xf sqream-db-v2021.1.tar.gz + $ sudo mv sqream /usr/local/sqream-db-v2021.1 + $ cd /usr/local + $ sudo chown -R sqream:sqream sqream-db-v2021.1 + +4. Remove the symbolic link: + +.. code-block:: console + + $ sudo rm sqream + +5. Create a new symbolic link named "sqream" pointing to the new version: + +.. code-block:: console + + $ sudo ln -s sqream-db-v2021.1 sqream + +6. Verify that the symbolic SQreamDB link points to the real folder: + +.. code-block:: console + + $ ls -l + + -- Output example: + + $ sqream -> sqream-db-v2021.1 + +7. Upgrade your version of SQreamDB storage. + + a. SQreamDB recommends storing the generated back-up locally in case needed. To generate a back-up of the metadata, run the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + + b. Shut down all SQreamDB services. + + c. Extract the recently created back-up file. + + d. Replace your current metadata with the metadata you stored in the back-up file. + + e. Navigate to the new SQreamDB package bin folder. + + f. Get the cluster path + + .. code-block:: console + + $ cat /etc/sqream/sqream1_config.json |grep cluster + + g. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <RocksDB path> + + -- Output example: + + get_leveldb_version path{<cluster path>} + current storage version 23 + upgrade_v24 + upgrade_storage to 24 + upgrade_storage to 24 - Done + upgrade_v25 + upgrade_storage to 25 + upgrade_storage to 25 - Done + upgrade_v26 + upgrade_storage to 26 + upgrade_storage to 26 - Done + validate_leveldb + ... + upgrade_v37 + upgrade_storage to 37 + upgrade_storage to 37 - Done + validate_leveldb + storage has been upgraded successfully to version 37 + +8. Verify that the latest version has been installed: + +.. code-block:: console + + $ ./sqream sql --username sqream --password sqream --host localhost --databasename master -c "SELECT SHOW_VERSION();" + + -- Output example: + + v2021.1 + 1 row + time: 0.050603s + +For more information, see the :ref:`upgrade_storage<upgrade_storage_cli_reference>` command line program. + +9. After completing the upgrade process, ensure that ALL :ref:`operational and configuration<version_upgrade_configurations>` changes introduced in versions newer than the version you are upgrading from are applied before returning to regular SQreamDB operations. + diff --git a/upgrade_guide/version_upgrade_configurations.rst b/upgrade_guide/version_upgrade_configurations.rst new file mode 100644 index 000000000..b932c03f9 --- /dev/null +++ b/upgrade_guide/version_upgrade_configurations.rst @@ -0,0 +1,43 @@ +.. _version_upgrade_configurations: + +****************************************** +Version History and Configuration Changes +****************************************** + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SQreamDB Version + - Storage Version + - Configurations and Changes + * - 2022.1.7 + - 43 + - None + * - 2022.1.6 + - 42 + - None + * - 2022.1.5 + - 42 + - None + * - 2022.1.4 + - 42 + - None + * - 2022.1.3 + - 42 + - In SQream version 2022.1.3 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. + * - 2022.1.2 + - 41 + - None + * - 2022.1.1 + - 40 + - * In compliance with GDPR standards, version 2022.1.1 requires a strong password policy when accessing the CLI and Studio. For more information, see :ref:`Password Policy<access_control_password_policy>`. + + * The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. For more information, see :ref:`Adjusting the Permitted Log-In Attempts<login_max_retries>`. + * - 2022.1 + - 40 + - * In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. + + * If you are using an earlier version of SQreamDB, see the :ref:`Using Legacy String Literals<use_legacy_string_literals>` configuration flag. + + From 953eff3d1d0ae34813d61c29a2f5b13b0411d3c6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:08:12 +0300 Subject: [PATCH 0971/1892] Foreign Tables --- external_storage_platforms/azure.rst | 23 +++---- external_storage_platforms/gcp.rst | 64 ++++++++++++++++--- external_storage_platforms/s3.rst | 29 ++++----- .../ddl_commands/create_foreign_table.rst | 15 +---- 4 files changed, 74 insertions(+), 57 deletions(-) diff --git a/external_storage_platforms/azure.rst b/external_storage_platforms/azure.rst index 2a974a044..42a95f20f 100644 --- a/external_storage_platforms/azure.rst +++ b/external_storage_platforms/azure.rst @@ -1,33 +1,26 @@ .. _azure: *********************** -Azure +Azure Blob Storage *********************** +Azure Blob Storage (ABS) is a scalable object storage solution within Microsoft Azure, designed to store and manage vast amounts of unstructured data. -.. contents:: - :local: - :depth: 1 +ABS Bucket File Location +================================= +ABS syntax to be used for specifying a single or multiple file location within an ABS bucket: -Azure URI Format -================= - -Specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. - -The following is an example of the general Azure syntax: - -.. code-block:: console +.. code-block:: sql azure://accountname.core.windows.net/path - Connection String =================== Connection String Example: -.. code-block:: +.. code-block:: json "DefaultEndpointsProtocol=https;AccountName=myaccount101;AccountKey=#######################################==;EndpointSuffix=core.windows.net" @@ -50,7 +43,7 @@ Use the following parameters within your SQreamDB legacy configuration file for -Example +Examples ============ .. code-block:: diff --git a/external_storage_platforms/gcp.rst b/external_storage_platforms/gcp.rst index 7f52a386f..32fc23994 100644 --- a/external_storage_platforms/gcp.rst +++ b/external_storage_platforms/gcp.rst @@ -7,18 +7,16 @@ Google Cloud Platform Ingesting data using Google Cloud Platform (GCP) requires configuring Google Cloud Storage (GCS) bucket access. You may configure SQreamDB to separate source and destination by granting read access to one bucket and write access to a different bucket. Such separation requires that each bucket be individually configured. -Google Cloud Platform URI Format +GCP Bucket File Location ================================= -Specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. +GCP syntax to be used for specifying a single or multiple file location within a GCP bucket: -The following is an example of the general GCP syntax: - -.. code-block:: console +.. code-block:: sql gs://<gcs path>/<gcs_bucket>/ -Granting GCP access +GCP Access ==================== Before You Begin @@ -32,6 +30,9 @@ String example: sample_service_account@sample_project.iam.gserviceaccount.com +Granting GCP Access +--------------------- + #. In your Google Cloud console, go to **Select a project** and select the desired project. #. From the **PRODUCTS** menu, select **Cloud Storage** > **Buckets**. @@ -54,10 +55,53 @@ String example: Optimize access time to your data by configuring the location of your bucket according to `Google Cloud location considerations <https://cloud.google.com/storage/docs/locations#location-r>`_. -Example + + +Examples ============ -.. code-block:: - - COPY table_name FROM WRAPPER csv_fdw OPTIONS(location = 'gs://mybucket/sqream-demo-data/file.csv'); +Using the ``COPY FROM`` command: + +.. code-block:: sql + + CREATE TABLE nba + ( + name TEXT, + team TEXT, + number TEXT, + position TEXT, + age TEXT, + height TEXT, + weight TEXT, + college TEXT, + salary TEXT + ); + +.. code-block:: sql + + COPY nba FROM + WRAPPER csv_fdw + OPTIONS(location = 'gs://blue_docs/nba.csv'); + +Using the ``CREATE FOREIGN TABLE`` command: + +.. code-block:: sql + + CREATE FOREIGN TABLE nba + ( + Name TEXT, + Team TEXT, + Number TEXT, + Position TEXT, + Age TEXT, + Height TEXT, + Weight TEXT, + College TEXT, + Salary TEXT + ) + WRAPPER csv_fdw + OPTIONS + ( + LOCATION = 'gs://blue_docs/nba.csv' + ); diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index e986ee10a..39aaec59f 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -4,24 +4,27 @@ Amazon Web Services *********************** -SQreamDB uses a native Amazon Simple Storage Services (S3) connector for inserting data. The ``s3://`` URI specifies an external file path to an S3 bucket. File names may contain wildcard characters, and the files can be in CSV or columnar format, such as Parquet and ORC. +SQreamDB uses a native Amazon Simple Storage Services (S3) connector for inserting data. -S3 URI Format -============= +S3 Bucket File Location +======================== -With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`foreign_tables`. - -The following is an example of the general S3 syntax: +S3 syntax to be used for specifying a single or multiple file location within an S3 bucket: .. code-block:: console s3://bucket_name/path -Granting Access to S3 +S3 Access ====================== A best practice for granting access to AWS S3 is by creating an `Identity and Access Management (IAM) <https://docs.aws.amazon.com/IAM/latest/UserGuide/getting-started.html>`_ user account. If creating an IAM user account is not possible, you may follow AWS guidelines for `using the global configuration object <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/global-config-object.html>`_ and setting an `AWS region <https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-region.html>`_. +Authentication +============== + +After being granted access to an S3 bucket, you'll be able to execute statements using the ``AWS ID`` and ``AWS SECRET`` parameters for authentication. + Connecting to S3 Using SQreamDB Legacy Configuration File ========================================================= @@ -58,22 +61,17 @@ You may use the following parameters within your SQreamDB legacy configuration f "AwsObjectAccessStyle": "path" } -Authentication -============== -SQreamDB supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. Examples ======== -Use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. - Creating a Foreign Table ------------------------ Based on the source file's structure, you can create a foreign table with the appropriate structure, and point it to your file as shown in the following example: -.. code-block:: postgres +.. code-block:: sql CREATE FOREIGN TABLE nba ( @@ -97,11 +95,6 @@ Based on the source file's structure, you can create a foreign table with the ap In the example above the file format is CSV, and it is stored as an S3 object. If the path is on HDFS, you must change the URI accordingly. Note that the record delimiter is a DOS newline (``\r\n``). -For more information, see the following: - -* :ref:`Creating a foreign table<create_foreign_table>` -* :ref:`hdfs` - Querying Foreign Tables ----------------------- diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 8c36a0f75..ded035dc7 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -4,22 +4,9 @@ CREATE FOREIGN TABLE *********************** -.. note:: - - Starting with SQream DB v2020.2, external tables have been renamed to foreign tables, and use a more flexible foreign data wrapper concept. - - Upgrading to a new version of SQream DB converts existing external tables automatically. - - ``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. -See more in the :ref:`Foreign tables guide<external_tables>`. - -.. tip:: - - * Data in a foreign table can change if the sources change, and frequent access to remote files may harm performance. - - * To create a regular table, see :ref:`CREATE TABLE <create_table>` +Changes in the source data can result in corresponding modifications to the content of a foreign table. Consistent access to remote files might impact performance. Permissions ============= From dce6b4c113005dab0425344a06d8c53c7142e56b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 24 Oct 2023 14:48:57 +0300 Subject: [PATCH 0972/1892] _ --- .../get_all_roles_database_ddl.rst | 9 +-- .../get_statement_permissions.rst | 6 +- .../grant_usage_on_service_to_all_roles.rst | 4 +- reference/sql/sql_statements/index.rst | 77 +++++++++---------- .../show_subscribed_instances.rst | 4 +- .../wlm_commands/subscribe_service.rst | 4 +- .../wlm_commands/unsubscribe_service.rst | 4 +- 7 files changed, 50 insertions(+), 58 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst b/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst index 1f6b6d734..13543d585 100644 --- a/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst +++ b/reference/sql/sql_statements/access_control_commands/get_all_roles_database_ddl.rst @@ -1,9 +1,10 @@ .. _get_all_roles_database_ddl: ************************** -GET_ALL_ROLES_DATABASE_DDL +GET ALL ROLES DATABASE DDL ************************** -The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role databases in DDL format. + +The ``GET ALL ROLES DATABASE DDL`` statement returns the definition of all role databases in DDL format. .. contents:: :local: @@ -11,7 +12,6 @@ The ``GET_ALL_ROLES_DATABASE_DDL`` statement returns the definition of all role Syntax ========== -The following is the correct syntax for using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: .. code-block:: postgres @@ -19,7 +19,6 @@ The following is the correct syntax for using the ``GET_ALL_ROLES_DATABASE_DDL`` Example =========== -The following is an example of using the ``GET_ALL_ROLES_DATABASE_DDL`` statement: .. code-block:: psql @@ -35,7 +34,7 @@ The following is an example of the output of the ``GET_ALL_ROLES_DATABASE_DDL`` Permissions ============= -Using the ``GET_ALL_ROLES_DATABASE_DDL`` statement requires no special permissions. +Using the ``GET ALL ROLES DATABASE DDL`` statement requires no special permissions. For more information, see the following: diff --git a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst index f83a2efb2..cee5a3d38 100644 --- a/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/get_statement_permissions.rst @@ -1,10 +1,10 @@ .. _get_statement_permissions: **************************** -GET_STATEMENT_PERMISSIONS +GET STATEMENT PERMISSIONS **************************** -``GET_STATEMENT_PERMISSIONS`` analyzes an SQL statement and returns a list of permissions required to execute it. +``GET STATEMENT PERMISSIONS`` analyzes an SQL statement and returns a list of permissions required to execute it. Use this function to understand the permissions required, before :ref:`granting<grant>` them to a specific role. @@ -15,7 +15,7 @@ See also :ref:`grant`, :ref:`create_role`. Permissions ============= -No special permissions are required to run ``GET_STATEMENT_PERMISSIONS``. +No special permissions required. Syntax ========== diff --git a/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst b/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst index 2c0f1d338..083dcd2d6 100644 --- a/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst +++ b/reference/sql/sql_statements/access_control_commands/grant_usage_on_service_to_all_roles.rst @@ -1,10 +1,10 @@ .. _grant_usage_on_service_to_all_roles: *********************************** -GRANT_USAGE_ON_SERVICE_TO_ALL_ROLES +GRANT USAGE ON SERVICE TO ALL ROLES *********************************** -The ``grant_usage_on_service_to_all_roles`` utility function enables a ``SUPERUSER`` to grant access to services for other system roles. +The ``GRANT USAGE ON SERVICE TO ALL ROLES`` utility function enables a ``SUPERUSER`` to grant access to services for other system roles. You may use it to perform one of the following options: diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 28060acd2..f1141b0b7 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -24,47 +24,47 @@ The following table shows the Data Definition commands: * - Command - Usage - * - :ref:`ADD_COLUMN<add_column>` + * - :ref:`ADD COLUMN<add_column>` - Add a new column to a table - * - :ref:`ALTER_DEFAULT_SCHEMA<alter_default_schema>` + * - :ref:`ALTER DEFAULT SCHEMA<alter_default_schema>` - Change the default schema for a role - * - :ref:`ALTER_TABLE<alter_table>` + * - :ref:`ALTER TABLE<alter_table>` - Change the schema of a table - * - :ref:`CLUSTER_BY<cluster_by>` + * - :ref:`CLUSTER BY<cluster_by>` - Change clustering keys in a table - * - :ref:`CREATE_DATABASE<create_database>` + * - :ref:`CREATE DATABASE<create_database>` - Create a new database - * - :ref:`CREATE_FOREIGN_TABLE<create_foreign_table>` + * - :ref:`CREATE FOREIGN TABLE<create_foreign_table>` - Create a new foreign table in the database - * - :ref:`CREATE_FUNCTION<create_function>` + * - :ref:`CREATE FUNCTION<create_function>` - Create a new user defined function in the database - * - :ref:`CREATE_SCHEMA<create_schema>` + * - :ref:`CREATE SCHEMA<create_schema>` - Create a new schema in the database - * - :ref:`CREATE_TABLE<create_table>` + * - :ref:`CREATE TABLE<create_table>` - Create a new table in the database - * - :ref:`CREATE_TABLE_AS<create_table_as>` + * - :ref:`CREATE TABLE AS<create_table_as>` - Create a new table in the database using results from a select query - * - :ref:`CREATE_VIEW<create_view>` + * - :ref:`CREATE VIEW<create_view>` - Create a new view in the database - * - :ref:`DROP_CLUSTERING_KEY<drop_clustering_key>` + * - :ref:`DROP CLUSTERING KEY<drop_clustering_key>` - Drops all clustering keys in a table - * - :ref:`DROP_COLUMN<drop_column>` + * - :ref:`DROP COLUMN<drop_column>` - Drop a column from a table - * - :ref:`DROP_DATABASE<drop_database>` + * - :ref:`DROP DATABASE<drop_database>` - Drop a database and all of its objects - * - :ref:`DROP_FUNCTION<drop_function>` + * - :ref:`DROP FUNCTION<drop_function>` - Drop a function - * - :ref:`DROP_SCHEMA<drop_schema>` + * - :ref:`DROP SCHEMA<drop_schema>` - Drop a schema - * - :ref:`DROP_TABLE<drop_table>` + * - :ref:`DROP TABLE<drop_table>` - Drop a table and its contents from a database - * - :ref:`DROP_VIEW<drop_view>` + * - :ref:`DROP VIEW<drop_view>` - Drop a view - * - :ref:`RENAME_COLUMN<rename_column>` + * - :ref:`RENAME COLUMN<rename_column>` - Rename a column - * - :ref:`RENAME_TABLE<rename_table>` + * - :ref:`RENAME TABLE<rename_table>` - Rename a table - * - :ref:`RENAME_SCHEMA<rename_schema>` + * - :ref:`RENAME SCHEMA<rename_schema>` - Rename a schema @@ -80,13 +80,13 @@ The following table shows the Data Manipulation commands: * - Command - Usage - * - :ref:`CREATE_TABLE_AS<create_table_as>` + * - :ref:`CREATE TABLE AS<create_table_as>` - Create a new table in the database using results from a select query * - :ref:`DELETE<delete>` - Delete specific rows from a table - * - :ref:`COPY_FROM<copy_from>` + * - :ref:`COPY FROM<copy_from>` - Bulk load CSV data into an existing table - * - :ref:`COPY_TO<copy_to>` + * - :ref:`COPY TO<copy_to>` - Export a select query or entire table to CSV files * - :ref:`INSERT<insert>` - Insert rows into a table @@ -121,23 +121,23 @@ The following table shows the Utility commands: - Lists previously saved query names, one per row. * - :ref:`RECOMPILE SAVED QUERY<recompile_saved_query>` - Recompiles a saved query that has been invalidated due to a schema change - * - :ref:`SELECT GET_LICENSE_INFO<get_license_info>` + * - :ref:`SELECT GET LICENSE INFO<get_license_info>` - View a user's license information - * - :ref:`SELECT GET_DDL<get_ddl>` + * - :ref:`SELECT GET DDL<get_ddl>` - View the ``CREATE TABLE`` statement for a table - * - :ref:`SELECT GET_FUNCTION_DDL<get_function_ddl>` + * - :ref:`SELECT GET FUNCTION DDL<get_function_ddl>` - View the ``CREATE FUNCTION`` statement for a UDF - * - :ref:`SELECT GET_TOTAL_CHUNKS_SIZE<get_total_chunks_size>` + * - :ref:`SELECT GET TOTAL CHUNKS SIZE<get_total_chunks_size>` - Shows the total size of all data chunks saved in the system in both compressed and uncompressed formats - * - :ref:`SELECT GET_VIEW_DDL<get_view_ddl>` + * - :ref:`SELECT GET VIEW DDL<get_view_ddl>` - View the ``CREATE VIEW`` statement for a view - * - :ref:`SELECT DATA_READ_METRICS<select_data_read_metrics>` + * - :ref:`SELECT DATA READ METRICS<select_data_read_metrics>` - Monitor license quota usage by reviewing monthly or daily data read usage - * - :ref:`SELECT GPU_METRICS<select_gpu_metrics>` + * - :ref:`SELECT GPU METRICS<select_gpu_metrics>` - Monitor license quota usage by reviewing monthly or daily GPU usage - * - :ref:`SELECT RECOMPILE_VIEW<recompile_view>` + * - :ref:`SELECT RECOMPILE VIEW<recompile_view>` - Recreate a view after schema changes - * - :ref:`SELECT DUMP_DATABASE_DDL<dump_database_ddl>` + * - :ref:`SELECT DUMP DATABASE DDL<dump_database_ddl>` - View the ``CREATE TABLE`` statement for an current database * - :ref:`SHOW CONNECTIONS<show_connections>` - Returns a list of active sessions on the current worker @@ -151,18 +151,11 @@ The following table shows the Utility commands: - Returns a list of active sessions across the cluster * - :ref:`SHOW VERSION<show_version>` - Returns the system version for SQream DB - * - :ref:`SHUTDOWN_SERVER<shutdown_server_command>` + * - :ref:`SHUTDOWN SERVER<shutdown_server_command>` - Sets your server to finish compiling all active queries before shutting down according to a user-defined time value * - :ref:`STOP STATEMENT<stop_statement>` - Stops or aborts an active statement -.. |icon-new_2022.1| image:: /_static/images/new_2022.1.png - :align: middle - :width: 110 - -.. |icon-New_Dark_Gray| image:: /_static/images/New_Dark_Gray.png - :align: middle - :width: 110 Workload Management ====================== @@ -213,7 +206,7 @@ The following table shows the Access Control commands: - Returns a list of permissions required to run a statement or query * - :ref:`grant` - Grant permissions to a role - * - :ref:`GRANT_USAGE_ON_SERVICE_TO_ALL_ROLES` + * - :ref:`GRANT USAGE ON SERVICE TO ALL ROLES` - Grant service usage permissions * - :ref:`revoke` - Revoke permissions from a role diff --git a/reference/sql/sql_statements/wlm_commands/show_subscribed_instances.rst b/reference/sql/sql_statements/wlm_commands/show_subscribed_instances.rst index 95fd55022..301bb55b5 100644 --- a/reference/sql/sql_statements/wlm_commands/show_subscribed_instances.rst +++ b/reference/sql/sql_statements/wlm_commands/show_subscribed_instances.rst @@ -1,10 +1,10 @@ .. _show_subscribed_instances : *************************** -SHOW_SUBSCRIBED_INSTANCES +SHOW SUBSCRIBED INSTANCES *************************** -``SHOW_SUBSCRIBED_INSTANCES`` lists the cluster workers and their service queues. +``SHOW SUBSCRIBED INSTANCES`` lists the cluster workers and their service queues. .. note:: If you haven't already, read the :ref:`Workload manager guide<workload_manager>`. diff --git a/reference/sql/sql_statements/wlm_commands/subscribe_service.rst b/reference/sql/sql_statements/wlm_commands/subscribe_service.rst index a36fcf3a4..143ef4acc 100644 --- a/reference/sql/sql_statements/wlm_commands/subscribe_service.rst +++ b/reference/sql/sql_statements/wlm_commands/subscribe_service.rst @@ -1,10 +1,10 @@ .. _subscribe_service : ******************* -SUBSCRIBE_SERVICE +SUBSCRIBE SERVICE ******************* -``SUBSCRIBE_SERVICE`` subscribes a worker to a service queue for the duration of the connected session. +``SUBSCRIBE SERVICE`` subscribes a worker to a service queue for the duration of the connected session. .. note:: If you haven't already, read the :ref:`Workload manager guide<workload_manager>`. diff --git a/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst b/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst index 939d8918a..91019889d 100644 --- a/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst +++ b/reference/sql/sql_statements/wlm_commands/unsubscribe_service.rst @@ -1,10 +1,10 @@ .. _unsubscribe_service : ******************** -UNSUBSCRIBE_SERVICE +UNSUBSCRIBE SERVICE ******************** -``UNSUBSCRIBE_SERVICE`` unsubscribes a worker from a service queue for the duration of the connected session. +``UNSUBSCRIBE SERVICE`` unsubscribes a worker from a service queue for the duration of the connected session. .. note:: If you haven't already, read the :ref:`Workload manager guide<workload_manager>`. From e8716dcbb108731d967d4c68df05a18ba7dc318d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 24 Oct 2023 15:31:33 +0300 Subject: [PATCH 0973/1892] Update index.rst --- upgrade_guide/index.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/upgrade_guide/index.rst b/upgrade_guide/index.rst index a523f3363..0186499c3 100644 --- a/upgrade_guide/index.rst +++ b/upgrade_guide/index.rst @@ -4,9 +4,12 @@ Upgrade Guides ***************** +Refer to the :ref:`version_upgrade` guide to upgrade from your current SQreamDB version and explore the :ref:`version_upgrade_configurations` guide. It provides a breakdown of the necessary system modifications for the specific version you’re upgrading to, ensuring a thorough and effective upgrade process. + .. toctree:: :maxdepth: 1 - :titlesonly: + :titlesonly: + :hidden: version_upgrade version_upgrade_configurations \ No newline at end of file From 46d99bdf35f3c1e3e1778a455e4b1e5bf2ef902e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 24 Oct 2023 16:24:14 +0300 Subject: [PATCH 0974/1892] Update version_upgrade_configurations.rst --- .../version_upgrade_configurations.rst | 31 ++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/upgrade_guide/version_upgrade_configurations.rst b/upgrade_guide/version_upgrade_configurations.rst index b932c03f9..eef5b8312 100644 --- a/upgrade_guide/version_upgrade_configurations.rst +++ b/upgrade_guide/version_upgrade_configurations.rst @@ -4,6 +4,8 @@ Version History and Configuration Changes ****************************************** + + .. list-table:: :widths: auto :header-rows: 1 @@ -11,6 +13,33 @@ Version History and Configuration Changes * - SQreamDB Version - Storage Version - Configurations and Changes + * - 4.4 + - 49 + - + * - 4.3 + - 49 + - + * - 4.2 + - 46 + - New Releases: + * Pysqream 3.2.5 Connector is released + + * ODBC 4.4.4 Connector is released + + * JDBC 4.5.8 Connector is released + + * Apache Spark 5.0.0 Connector is released + + * The ``INT96`` data type is deprecated + * - 4.1 + - 45 + - New Releases: + * JDBC 4.5.7 Connector + + * SQream Studio v5.5.4 + * - 4.0 + - 45 + - None * - 2022.1.7 - 43 - None @@ -25,7 +54,7 @@ Version History and Configuration Changes - None * - 2022.1.3 - 42 - - In SQream version 2022.1.3 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. + - The ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. * - 2022.1.2 - 41 - None From 9466bf6ea8660fa2e345f42720a2a24cc3a1197d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 26 Oct 2023 08:55:06 +0300 Subject: [PATCH 0975/1892] Remove cross-database queries --- .../sql/sql_syntax/cross_database_query.rst | 176 ------------------ reference/sql/sql_syntax/index.rst | 2 - 2 files changed, 178 deletions(-) delete mode 100644 reference/sql/sql_syntax/cross_database_query.rst diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst deleted file mode 100644 index 8b525d386..000000000 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ /dev/null @@ -1,176 +0,0 @@ -.. _cross_database_query: - -*************************** -Cross-Database Query -*************************** - -Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQreamDB cluster, through the execution of a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. - -To ensure optimal performance, it is advised to refrain from querying more than 10 databases in a single query. - - -Syntax -========== - -.. code-block:: sql - - -- SELECT statement - - SELECT - <column_name1>, - <column_name2>, - ... - FROM - <database_name>.<schema_name>.<table_name> AS <alias1> - JOIN - <database_name>.<schema_name>.<table_name> AS <alias2> - ON - <alias1>.<join_column> = <alias2>.<join_column> - WHERE - <condition1> - AND <condition2> - - -- CREATE TABLE statement - - CREATE TABLE - <database_name>.<schema_name>.<table_name> ( - <column_name1> <data_type1>, - <column_name2> <data_type2>, - ... - ) - - -- CREATE FOREIGN TABLE statement - - CREATE FOREIGN TABLE - <database_name>.<schema_name>.<table_name> ( - <column_name1> <data_type1>, - <column_name2> <data_type2>, - ... - ) - - -- ALTER TABLE statement - - ALTER TABLE - <database_name>.<schema_name>.<table_name> - ADD COLUMN - <new_column_name> <new_column_data_type> - - -- CREATE VIEW statement - - CREATE VIEW - <database_name>.<schema_name>.<view_name> (<column_name1>, <column_name2>, ...) - AS - SELECT - <alias1>.<column_name1>, - <alias1>.<column_name2>, - ... - FROM - <database_name1>.<schema_name1>.<table_name1> AS <alias1> - JOIN - <database_name2>.<schema_name2>.<table_name2> AS <alias2> - ON - <alias1>.<join_column> = <alias2>.<join_column> - WHERE - <condition1> - AND <condition2> - - -- INSERT INTO statement - - INSERT INTO - <database_name>.<schema_name>.<table_name> (<column_name1>, <column_name2>, ...) - VALUES - (<value1>, <value2>, ...) - - -- UPDATE statement - - UPDATE - <database_name>.<schema_name>.<table_name> - SET - <column_name1> = <new_value1>, - <column_name2> = <new_value2> - WHERE - <condition> - - -- DELETE statement - - DELETE FROM - <database_name>.<schema_name>.<table_name> - WHERE - <condition> - - -- TRUNCATE TABLE statement - - TRUNCATE TABLE - <database_name>.<schema_name>.<table_name> - - -- DROP TABLE statement - - DROP TABLE - <database_name>.<schema_name>.<table_name> - - -Parameters -=========== - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``column_name`` - - The name of a specific column to read or write data from - * - ``database_name`` - - The name of a specific database to read or write data from - * - ``schema_name`` - - The name of a specific schema to read or write data within - * - ``table_name`` - - The name of a specific table to read or write data from - * - ``condition`` - - The condition for performing a specific operation - -Examples -========= - -Querying data from two tables in different databases: - -.. code-block:: sql - - SELECT * - FROM database1.schema1.table1 t1 - JOIN database2.schema2.table2 t2 - ON t1.id = t2.id - WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; - -Querying data from two tables in different schemas and databases: - -.. code-block:: sql - - SELECT * - FROM database1.schema1.table1 t1 - JOIN database2.schema2.table2 t2 - ON t1.id = t2.id - WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; - -Querying data from two tables in different databases with a where clause: - -.. code-block:: sql - - SELECT t1.*, t2.* - FROM database1.schema1.table1 t1 - JOIN database2.schema2.table2 t2 - ON t1.id = t2.id - WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; - -Querying data from three tables in different databases: - -.. code-block:: sql - - SELECT t1.*, t2.*, t3.* - FROM database1.schema1.table1 t1 - JOIN database2.schema2.table2 t2 - ON t1.id = t2.id - JOIN database3.schema3.table3 t3 - ON t2.id = t3.id - WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; - diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index b8ce4d329..cced92a61 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -18,8 +18,6 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Literals are fixed values representing specific data types, such as numbers or strings, used directly in SQL statements. * - :ref:`scalar_expressions` - Scalar expressions are single-value computations that operate on one or more values to produce a single result. - * - :ref:`cross_database_query` - - Cross-database queries involve accessing and manipulating data from multiple databases within a single SQL statement or operation. * - :ref:`joins` - Joins combine rows from two or more tables based on a related column to retrieve data from multiple sources in a single result set. * - :ref:`common_table_expressions` From a7c1d92b871035a76fb03ef27ee0a1f0eb15d2cb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 26 Oct 2023 10:49:11 +0300 Subject: [PATCH 0976/1892] Update version_upgrade_configurations.rst --- upgrade_guide/version_upgrade_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/upgrade_guide/version_upgrade_configurations.rst b/upgrade_guide/version_upgrade_configurations.rst index eef5b8312..e4ccbd63b 100644 --- a/upgrade_guide/version_upgrade_configurations.rst +++ b/upgrade_guide/version_upgrade_configurations.rst @@ -1,7 +1,7 @@ .. _version_upgrade_configurations: ****************************************** -Version History and Configuration Changes +Upgrade-Related Configuration Changes ****************************************** From 63329a33d2e7d5286ed5741211988d806fb723e9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 31 Oct 2023 15:16:24 +0200 Subject: [PATCH 0977/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index f0a1b2479..bb922664d 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -45,7 +45,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - Server - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) * - Processor - - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or similar + - 2x Intel Xeon Gold 6348 (28C/56HT) 3.5GHz or similar * - RAM - 1.5 TB * - Onboard storage @@ -90,7 +90,7 @@ The following table shows SQream's recommended hardware specifications: * - Server - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) * - Processor - - 2x Intel Xeon Gold 6240 (18C/36HT) 2.6GHz or similar + - 2x Intel Xeon Gold 6348 (28C/56HT) 3.5GHz or similar * - RAM - 2 TB * - Onboard storage From 5f20c52c8680752ba5da9a50f3b8388dd19ba0c8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Nov 2023 09:38:23 +0200 Subject: [PATCH 0978/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 76b3e3086..ffe4395eb 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -78,7 +78,7 @@ The ``DEFAULT`` value constraint specifies a value to use if one is not defined The default value may be a literal or NULL. -.. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into an nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. +.. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into a nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. Syntax --------- @@ -95,7 +95,9 @@ The following is the correct syntax for using the **DEFAULT** value constraints: default ::= DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] + | IDENTITY [ ( start_with [ , increment_by ] ) ] [ check_specification ] + | check_specification [ IDENTITY [ ( start_with [ , increment_by ] ) ] + check_specification ::= CHECK( 'CS compression_spec' ) From 5f919f66667c84fc03ecd393886443b24fe1dc6a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Nov 2023 11:17:17 +0200 Subject: [PATCH 0979/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 654796f9b..0a60bd126 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Thread Allocation ------------------ SQLoader allocates concurrent threads based on the available CPU cores, limiting it to the number of cores minus one. For instance, with 16 cores, 15 threads are allocated. Additionally, when dealing with partitioned tables, each partition consumes a thread, meaning users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 05488254048ba2e85d9fa1d59a75abe2bc91b4ae Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 Nov 2023 13:39:35 +0200 Subject: [PATCH 0980/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 0a60bd126..8833a91e6 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Thread Allocation ------------------ SQLoader allocates concurrent threads based on the available CPU cores, limiting it to the number of cores minus one. For instance, with 16 cores, 15 threads are allocated. Additionally, when dealing with partitioned tables, each partition consumes a thread, meaning users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 069864c2584eb462f37f691fb9e3b0a228c601d7 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 07:45:21 +0200 Subject: [PATCH 0981/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index bb922664d..1cdd0965e 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -55,7 +55,10 @@ An average single-node cluster can be a rackmount server or workstation, contain * 10x 3.84TB SSD 2.5in Hot plug for storage, RAID6 * - GPU - - NVIDIA 2x A100 or H100 + - + * NVIDIA 2x A100 or H100 + * NVIDIA 2x L40S + * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux @@ -102,7 +105,7 @@ The following table shows SQream's recommended hardware specifications: * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high-speed network card minimum 40G compatible with customer’s infrastructure * 50 TB (NAS connected over GPFS, Lustre, Weka, or VAST) GPFS recommended * - GPU - - NVIDIA 2x A100 or H100 + - NVIDIA 2x A100, H100, or L40S * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux @@ -237,5 +240,5 @@ Storage For clustered scale-out installations, SQream relies on NAS storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. -SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 GPU or H100 per 2 users, for full, uninterrupted dedicated access. +SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 / H100 or L40S GPU per 2 users, for full, uninterrupted dedicated access. From f7cd929c8bf3b207787851eb84c89e21e99600e3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 08:17:26 +0200 Subject: [PATCH 0982/1892] Update catalog_reference_catalog_tables.rst --- reference/catalog_reference_catalog_tables.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 4ad9a916f..6d07f9008 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -264,10 +264,6 @@ The following table describes the ``schema_permissions`` data object: * - ``permission_type`` - Identifies the permission type. -UDF Permissions -***************** - -**Comment** - *No content.* .. _queries: From e7bdb24f6c90e82a8eff28997bf4055188c93b8d Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 08:37:33 +0200 Subject: [PATCH 0983/1892] Update catalog_reference_overview.rst --- reference/catalog_reference_overview.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/catalog_reference_overview.rst b/reference/catalog_reference_overview.rst index b74663509..132e2db1f 100644 --- a/reference/catalog_reference_overview.rst +++ b/reference/catalog_reference_overview.rst @@ -3,9 +3,10 @@ ************************************* Overview ************************************* -The SQream database uses a schema called ``sqream_catalog`` that contains information about your database's objects, such tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and which may be different across SQream versions. + +The SQream database uses a schema called ``sqream_catalog`` that contains information about your database's objects, such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQream versions. * :ref:`catalog_reference_schema_information` * :ref:`catalog_reference_catalog_tables` * :ref:`catalog_reference_additonal_tables` -* :ref:`catalog_reference_examples` \ No newline at end of file +* :ref:`catalog_reference_examples` From 11232518001f0bae897a3c385ef43062514903bf Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 08:46:28 +0200 Subject: [PATCH 0984/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index 7a76dbe8e..a71428241 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -54,7 +54,7 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da - Variable length string - UTF-8 unicode - Up to ``4`` bytes - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING``, ``NVARCHAR`` * - ``NUMERIC`` - 38 digits - 16 bytes From 43d499a8bee429b8de6290a99dd4a034fb2af5d5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:31:22 +0200 Subject: [PATCH 0985/1892] Revert "Update sql_data_types_primitives.rst" This reverts commit 11232518001f0bae897a3c385ef43062514903bf. --- data_type_guides/sql_data_types_primitives.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index a71428241..7a76dbe8e 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -54,7 +54,7 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da - Variable length string - UTF-8 unicode - Up to ``4`` bytes - ``'Kiwis have tiny wings, but cannot fly.'`` - - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING``, ``NVARCHAR`` + - ``CHAR VARYING``, ``CHAR``, ``CHARACTER VARYING``, ``CHARACTER``, ``NATIONAL CHARACTER VARYING``, ``NATIONAL CHARACTER``, ``NCHAR VARYING``, ``NCHAR``, ``NATIONAL CHAR``, ``NATIONAL CHAR VARYING`` * - ``NUMERIC`` - 38 digits - 16 bytes From 5ddb696700121c66711e9d07c80fbe44422f2fc3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 11:37:02 +0200 Subject: [PATCH 0986/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 1cdd0965e..f03f57f83 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -56,9 +56,8 @@ An average single-node cluster can be a rackmount server or workstation, contain * - GPU - - * NVIDIA 2x A100 or H100 - * NVIDIA 2x L40S - + NVIDIA 2x A100ת, H100, or L40S + * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux From 90f42346e8571e93dcb957ec458089fa341a2420 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 6 Nov 2023 13:32:46 +0200 Subject: [PATCH 0987/1892] catalog reference guide --- reference/catalog_reference.rst | 4 ++-- reference/catalog_reference_examples.rst | 3 --- reference/catalog_reference_overview.rst | 17 ++++++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index 6035dd34b..b9ac28df9 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -4,13 +4,13 @@ Catalog Reference Guide *********************** -The **Catalog Reference Guide** describes the following: +The SQreamDB database uses a schema called ``sqream_catalog`` that contains information about database objects such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQreamDB versions. .. toctree:: :maxdepth: 1 :glob: + :hidden: - catalog_reference_overview catalog_reference_schema_information catalog_reference_catalog_tables catalog_reference_additonal_tables diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst index 612d4b76f..06b8b3b11 100644 --- a/reference/catalog_reference_examples.rst +++ b/reference/catalog_reference_examples.rst @@ -4,8 +4,6 @@ Examples ******** -The **Examples** page includes the following examples: - .. contents:: :local: :depth: 1 @@ -62,4 +60,3 @@ Listing Saved Queries SELECT * FROM sqream_catalog.savedqueries; -For more information, see :ref:`saved_queries`. \ No newline at end of file diff --git a/reference/catalog_reference_overview.rst b/reference/catalog_reference_overview.rst index 132e2db1f..1df2a9af7 100644 --- a/reference/catalog_reference_overview.rst +++ b/reference/catalog_reference_overview.rst @@ -1,12 +1,15 @@ .. _catalog_reference_overview: -************************************* +********* Overview -************************************* +********* -The SQream database uses a schema called ``sqream_catalog`` that contains information about your database's objects, such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQream versions. +The SQreamDB database uses a schema called ``sqream_catalog`` that contains information about database objects such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQreamDB versions. -* :ref:`catalog_reference_schema_information` -* :ref:`catalog_reference_catalog_tables` -* :ref:`catalog_reference_additonal_tables` -* :ref:`catalog_reference_examples` +:ref:`catalog_reference_schema_information` + +:ref:`catalog_reference_catalog_tables` + +:ref:`catalog_reference_additonal_tables` + +:ref:`catalog_reference_examples` From 6dd9bbf07d5b891259c88260d212ea39af83ca9c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Nov 2023 15:09:55 +0200 Subject: [PATCH 0988/1892] sqream_catalog --- reference/catalog_reference.rst | 73 ++++++++++++++++++- .../catalog_reference_additonal_tables.rst | 9 +++ .../catalog_reference_catalog_tables.rst | 26 +++++++ .../catalog_reference_schema_information.rst | 34 ++++----- 4 files changed, 120 insertions(+), 22 deletions(-) diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index b9ac28df9..71a1a1285 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -6,12 +6,83 @@ Catalog Reference Guide The SQreamDB database uses a schema called ``sqream_catalog`` that contains information about database objects such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQreamDB versions. + +What Information Does the Schema Contain? +========================================== + +The schema contains data management tables with information about structure and management of database elements, including tables, schemas, queries, and permissions, and physical storage and organization of data tables of extents, chunk columns, chunks, and delete predicates. + +How to Get Table Information? +============================= + +To get the information stored on a table, use this syntax, as in this example of working with the ``parameters`` table: + +.. code-block:: sql + + SELECT * FROM sqream_catalog.parameters; + +To get the table ddl, use this syntax, as in this example of working with the ``parameters`` table: + +.. code-block:: sql + + SELECT get_ddl('sqream_catalog.parameters'); + +Database Management Tables +--------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Database Object + - Table + * - :ref:`Clustering Keys<clustering_keys>` + - ``clustering_keys`` + * - :ref:`Columns<columns>` + - ``columns``, ``external_table_columns`` + * - :ref:`Databases<databases>` + - ``databases`` + * - :ref:`Parameters<parameters>` + - ``parameters`` + * - :ref:`Permissions<permissions>` + - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions``, ``sqream_catalog.table_default_permissions`` + * - :ref:`Queries<queries>` + - ``saved_queries`` + * - :ref:`Roles<roles>` + - ``roles``, ``roles_memeberships`` + * - :ref:`Schemas<schemas>` + - ``schemas`` + * - :ref:`Tables<tables>` + - ``tables``, ``external_tables`` + * - :ref:`Views<views>` + - ``views`` + * - :ref:`User Defined Functions<udfs>` + - ``user_defined_functions`` + +Data Storage and Organization Tables +--------------------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Database Object + - Table + * - :ref:`Extents<extents>` + - Shows ``extents`` + * - :ref:`Chunk columns<chunk_columns>` + - Shows ``chunks_columns`` + * - :ref:`Chunks<chunks>` + - Shows ``chunks`` + * - :ref:`Delete predicates<delete_predicates>` + - Shows ``delete_predicates``. For more information, see :ref:`Deleting Data<delete_guide>` + .. toctree:: :maxdepth: 1 :glob: :hidden: - catalog_reference_schema_information + catalog_reference_catalog_tables catalog_reference_additonal_tables catalog_reference_examples \ No newline at end of file diff --git a/reference/catalog_reference_additonal_tables.rst b/reference/catalog_reference_additonal_tables.rst index 7d34429d3..37979b216 100644 --- a/reference/catalog_reference_additonal_tables.rst +++ b/reference/catalog_reference_additonal_tables.rst @@ -3,12 +3,15 @@ ************************************* Additional Tables ************************************* + The Reference Catalog includes additional tables that can be used for performance monitoring and inspection. The definition for these tables described on this page may change across SQream versions. .. contents:: :local: :depth: 1 +.. _extents: + Extents ---------- The ``extents`` storage object identifies storage extents, and each storage extents can contain several chunks. @@ -34,6 +37,8 @@ The ``extents`` storage object identifies storage extents, and each storage exte * - ``path`` - Shows the full path to the extent on the file system. +.. _chunk_columns: + Chunk Columns ------------------- The ``chunk_columns`` storage object lists chunk information by column. @@ -73,6 +78,8 @@ The ``chunk_columns`` storage object lists chunk information by column. .. note:: This is an internal table designed for low-level performance troubleshooting. +.. _chunks: + Chunks ------- The ``chunks`` storage object identifies storage chunks. @@ -96,6 +103,8 @@ The ``chunks`` storage object identifies storage chunks. .. note:: This is an internal table designed for low-level performance troubleshooting. +.. _delete_predicates: + Delete Predicates ------------------- The ``delete_predicates`` storage object identifies the existing delete predicates that have not been cleaned up. diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index 6d07f9008..b206ea5b1 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -118,6 +118,32 @@ The ``databases`` data object is used for displaying database information, and i * - ``compression_chunk_size_threshold`` - Reserved for internal use. +.. _parameters: + +Parameters +------------- + +The ``parameters`` object is used for displaying all flags, providing the scope (default, cluster and session), description, default value and actual value. + +.. list-table:: + :widths: 20 180 + :header-rows: 1 + + * - Column + - Description + * - ``flag_name`` + - Shows the flag name + * - ``value`` + - Shows the current flag configured value + * - ``default_value`` + - Shows the flag default value + * - ``scope`` + - Shows whether flag configuration is session-based or cluster-based + * - ``description`` + - Describes the purpose of the flag + + + .. _permissions: Permissions diff --git a/reference/catalog_reference_schema_information.rst b/reference/catalog_reference_schema_information.rst index be669999d..c706f3c07 100644 --- a/reference/catalog_reference_schema_information.rst +++ b/reference/catalog_reference_schema_information.rst @@ -4,19 +4,13 @@ What Information Does the Schema Contain? ***************************************** -The schema includes tables designated and relevant for both external and internal use: - -.. contents:: - :local: - :depth: 1 +The schema contains data management tables with information about structure and management of database elements, including tables, schemas, queries, and permissions, and physical storage and organization of data tables of extents, chunk columns, chunks, and delete predicates. -External Tables ---------------- - -The following table shows the data objects contained in the ``sqream_catalog`` schema designated for external use: +Database Management Tables +--------------------------- -.. list-table:: Database Objects - :widths: 20 180 +.. list-table:: + :widths: auto :header-rows: 1 * - Database Object @@ -42,22 +36,20 @@ The following table shows the data objects contained in the ``sqream_catalog`` s * - :ref:`User Defined Functions<udfs>` - ``user_defined_functions`` -Internal Tables ---------------- - -The following table shows the data objects contained in the ``sqream_catalog`` schema designated for internal use: +Data Storage and Organization Tables +--------------------------------------- -.. list-table:: Storage Objects - :widths: 20 180 +.. list-table:: + :widths: auto :header-rows: 1 * - Database Object - Table * - Extents - - Shows ``extents``. + - Shows ``extents`` * - Chunk columns - - Shows ``chunks_columns``. + - Shows ``chunks_columns`` * - Chunks - - Shows ``chunks``. + - Shows ``chunks`` * - Delete predicates - - Shows ``delete_predicates``. For more information, see :ref:`Deleting Data<delete_guide>`. \ No newline at end of file + - Shows ``delete_predicates``. For more information, see :ref:`Deleting Data<delete_guide>` \ No newline at end of file From 9702a15b861c127557910bfb71068e42941cf9f4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Nov 2023 15:27:31 +0200 Subject: [PATCH 0989/1892] sqream_catalog --- reference/catalog_reference.rst | 2 +- reference/catalog_reference_examples.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index 71a1a1285..d82602192 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -1,7 +1,7 @@ .. _catalog_reference: *********************** -Catalog Reference Guide +Catalog Reference *********************** The SQreamDB database uses a schema called ``sqream_catalog`` that contains information about database objects such as tables, columns, views, and permissions. Some additional catalog tables are used primarily for internal analysis and may differ across SQreamDB versions. diff --git a/reference/catalog_reference_examples.rst b/reference/catalog_reference_examples.rst index 06b8b3b11..f43f1b3fd 100644 --- a/reference/catalog_reference_examples.rst +++ b/reference/catalog_reference_examples.rst @@ -2,7 +2,7 @@ ******** Examples -******** +******** .. contents:: :local: From d2262e3e8983c500d35bf3996344a44b61918131 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:08:06 +0200 Subject: [PATCH 0990/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index a0ff5128e..d163461cc 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -89,7 +89,7 @@ Spooling Configuration :math:`spoolMemoryGB=limitQueryMemoryGB - 50GB` -SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. +The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. Example ------- @@ -97,7 +97,7 @@ Example Setting Spool Memory ~~~~~~~~~~~~~~~~~~~~ -The following examples are for 2T of RAM and 9 workers running on 3 A100(40) GPUs: +The provided examples assume a configuration with 2T of RAM, 8 workers running on 2 A100(80GB) GPUs, with 200 GB allocated for Internal Operations, Metadata Server, Server Picker, and UI. Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: @@ -112,7 +112,7 @@ Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: “metadataServerPort”: 3105, “port”: 5000, “useConfigIP”: true, - “limitQueryMemoryGB" : 201, + “limitQueryMemoryGB" : 225, } Configuring the ``spoolMemoryGB`` using the legacy configuration file: @@ -130,7 +130,7 @@ Configuring the ``spoolMemoryGB`` using the legacy configuration file: "nodeInfoLoggingSec": 60, "useClientLog": true, "useMetadataServer": true, - "spoolMemoryGB": 151, + "spoolMemoryGB": 175, "waitForClientSeconds": 18000, "enablePythonUdfs": true } From de37ab5df9111d6f032dc14ba5b621a2ab2c2074 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 Nov 2023 16:29:41 +0200 Subject: [PATCH 0991/1892] Spooling configuration --- .../concurrency_and_scaling_in_sqream.rst | 2 + configuration_guides/index.rst | 1 - configuration_guides/spooling.rst | 45 ------------------- .../installing_sqream_with_binary.rst | 2 + 4 files changed, 4 insertions(+), 46 deletions(-) delete mode 100644 configuration_guides/spooling.rst diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index d163461cc..bbad40a37 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -82,6 +82,8 @@ To boost the performance of a single statement, start by examining the :ref:`bes Adding additional RAM to nodes, using more GPU memory, and faster CPUs or storage can also sometimes help. +.. _spooling: + Spooling Configuration ====================== diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index 5a060d551..a694bb227 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -11,5 +11,4 @@ The **Configuration Guides** page describes the following configuration informat :glob: configuring_sqream - spooling ldap \ No newline at end of file diff --git a/configuration_guides/spooling.rst b/configuration_guides/spooling.rst deleted file mode 100644 index 78df2e93f..000000000 --- a/configuration_guides/spooling.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. _spooling: - -********************** -Spooling Configuration -********************** - -From the SQreamDB Acceleration Studio you can allocate the amount of memory (GB) available to the server for spooling using the :ref:`spoolMemoryGB flag<spool_memory_gb>`. SQreamDB recommends setting the ``spoolMemoryGB`` flag to 90% of the ``limitQueryMemoryGB`` flag. The ``limitQueryMemoryGB`` flag is the total memory you’ve allocated for processing queries. - -In addition, the ``limitQueryMemoryGB`` defines how much total system memory is used by each worker. - -Note that ``spoolMemoryGB`` must bet set to less than the ``limitQueryMemoryGB``. - -Example Configurations ----------------------- - -Setting Spool Memory -~~~~~~~~~~~~~~~~~~~~ - -The following is an example of setting ``spoolMemoryGB`` value per-worker for 512GB of RAM and 4 workers: - -.. code-block:: console - - { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: “127.0.0.1”, - “metadataServerPort”: “3105, - “port”: 5000, - “useConfigIP”” true, - “limitQueryMemoryGB" : 121, - “spoolMemoryGB" : 108 - “legacyConfigFilePath”: “home/SQream_develop/SqrmRT/utils/json/legacy_congif.json” - } - -Recommended Settings -~~~~~~~~~~~~~~~~~~~~ - -The following is an example of the recommended settings for a machine with 512GB of RAM and 4 workers: - -.. code-block:: console - - limitQueryMemoryGB - ⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121 - spoolMemoryGB - ⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108 diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index be2502534..ba9a575e9 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -87,6 +87,8 @@ In each JSON file, the following parameters **must be updated**: * port * ssl_port +See how to :ref:`configure <spooling>` the Spool Memory. + Note the following: * The value of the **metadataServerIp** parameter must point to the IP that the metadata is running on. From 7a320d4c1411dd880a3c47a5e0ec9464eba1e4bb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:19:18 +0200 Subject: [PATCH 0992/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 18d3489bd..d9f4d836c 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -125,12 +125,18 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins SQLAlchemy ========== + SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. .. contents:: :local: :depth: 1 +* SQLalchemy version 1.4.46 +* Currently supports Pysqream 3.2.5 + + + Creating a Standard Connection ------------------------------ @@ -177,7 +183,7 @@ Creating a Standard Connection Pulling a Table into Pandas --------------------------- -The following example shows how to pull a table in Pandas. This examples uses the URL method to create the connection string: +The following example shows how to pull a table in Pandas. This example uses the URL method to create the connection string: .. code-block:: python From 3db32070b123529566b4509b682b082d88f618a9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 9 Nov 2023 11:19:46 +0200 Subject: [PATCH 0993/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index d9f4d836c..d4cee407c 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -151,7 +151,7 @@ Creating a Standard Connection * - ``password`` - Specifies the password of the selected role * - ``host`` - - Specifies the host name + - Specifies the hostname * - ``port`` - Specifies the port number * - ``port_ssl`` From 75a65a72c21b496c09464f4af9e8abb414e57431 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:34:49 +0200 Subject: [PATCH 0994/1892] Update foreign_tables.rst --- operational_guides/foreign_tables.rst | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 557e76c16..42730434c 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -4,9 +4,9 @@ Foreign Tables *********************** Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. -SQream DB supports read only foreign tables, so you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. +SQream DB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. -Running queries directly on external data is most effectively used for things like one off querying. If you will be repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. +Running queries directly on foreign data is most effectively used for one-off querying. If you are repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. @@ -35,12 +35,8 @@ Use a foreign table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging -------------------------------- -For the following examples, we will want to interact with a CSV file. Here's a peek at the table contents: - -.. csv-table:: nba.csv - :file: nba-t10.csv - :widths: auto - :header-rows: 1 + +For the following examples, we will interact with a CSV file. The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. @@ -94,8 +90,8 @@ Let's peek at the data from the foreign table: Modifying Data from Staging ------------------------------- -One of the main reasons for staging data is to examine the contents and modify them before loading them. -Assume we are unhappy with weight being in pounds, because we want to use kilograms instead. We can apply the transformation as part of a query: +One of the main reasons for staging data is to examine the content and modify it before loading. +Assume we are unhappy with weight being in pounds because we want to use kilograms instead. We can apply the transformation as part of a query: .. code-block:: psql @@ -155,4 +151,4 @@ Error Handling and Limitations t=> SELECT * FROM nba; master=> select * from nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. \ No newline at end of file +* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. From 8f0454ca57a04efbf5d97a1ec44b7126e046c018 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:36:23 +0200 Subject: [PATCH 0995/1892] Update retrieving_execution_plan_output_using_studio.rst --- .../retrieving_execution_plan_output_using_studio.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/troubleshooting/retrieving_execution_plan_output_using_studio.rst b/troubleshooting/retrieving_execution_plan_output_using_studio.rst index 6dac66f74..d7d0a2598 100644 --- a/troubleshooting/retrieving_execution_plan_output_using_studio.rst +++ b/troubleshooting/retrieving_execution_plan_output_using_studio.rst @@ -11,7 +11,7 @@ Retrieving Execution Plan Output You can retrieve the execution plan output either after the query execution has completed, in the case of a hanging query, or if you suspect no progress is being made. -1. In the **Result Panel**, select **Execution Details View** |icon-execution-details-view|. +1. In the **Result Panel**, select **Execution Details View**. The **Execution Tree** window opens. @@ -24,4 +24,4 @@ You can retrieve the execution plan output either after the query execution has 3. Save the execution plan on your local machine. -The information may be analyzed by :ref:`monitoring_query_performance` or with help from `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. \ No newline at end of file +You can analyze this information using :ref:`monitoring_query_performance` or with assistance from `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. From bdb9c2ea092ac7382a4a4465c435f4f7ccbb9793 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:39:44 +0200 Subject: [PATCH 0996/1892] Update requirements.txt --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a8c8329d7..d17a7f108 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,5 @@ urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page Pygments>=2.4.0 -pdftex \ No newline at end of file +sphinx-favicon>=1.0.1 +pdftex From 2d7d116a64fb6e560ff9dc33f05958930aedaa37 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 11:59:05 +0200 Subject: [PATCH 0997/1892] Update conf.py --- conf.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/conf.py b/conf.py index beb7d00bb..e2ad6e6fd 100644 --- a/conf.py +++ b/conf.py @@ -58,12 +58,17 @@ # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' +html_favicon = "_static/images/faviconSQ.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +favicons = [ + "_static/images/faviconSQ.png" +] + html_css_files = [ 'css/custom.css', # Relative to the _static path ] From 3c9604edcd966b6db0853a30259d576b18d5a8a8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 12:55:29 +0200 Subject: [PATCH 0998/1892] Update conf.py --- conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/conf.py b/conf.py index e2ad6e6fd..73eea6ad3 100644 --- a/conf.py +++ b/conf.py @@ -37,7 +37,8 @@ # ones. extensions = [ 'sphinx_rtd_theme' - ,'notfound.extension' # 404 handling + ,'notfound.extension' # 404 handling + ,'sphinx_favicon' ] # Mark 'index' as the main page From 5d4941b5b45e616c45bbeb08922d1ec72511ce0b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 16 Nov 2023 13:04:07 +0200 Subject: [PATCH 0999/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 73eea6ad3..0b09c5545 100644 --- a/conf.py +++ b/conf.py @@ -64,7 +64,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ['_static/images'] favicons = [ "_static/images/faviconSQ.png" From 76321bfa47dfe35932f6b8f020d5a64eeb6d9cf4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 08:57:20 +0200 Subject: [PATCH 1000/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 8833a91e6..e1e205228 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Defines the partition to load data from if table is partitioned * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to be used during loading * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 0774484a8580307ac7ba154dda8f2e0c3133e61c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 09:07:17 +0200 Subject: [PATCH 1001/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index e1e205228..c93c58481 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Type and Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 96b1637a1e05ad3d0342b274048572c1ba9187fa Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 09:52:54 +0200 Subject: [PATCH 1002/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index c93c58481..e3b645c6f 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: 5 4 5 25 :header-rows: 1 * - CLI Parameter - State - Type and Default - Description * - ``-batchsize`` - Optional - ``10.000`` - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - The number of records read at once from the source database * - ``-columnlist`` - Optional - None - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - None - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - None - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - None - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - None - Source table name to load data from * - ``-target`` - Optional - Source table name - Target table name to load data into * - ``-target_db`` - Optional - None - Target database name to load data into * - ``-thread`` - Optional - ``1`` - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - Truncate target table before loading * - ``-type`` - Optional - ``full`` - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Source table name - Table name ``string`` - Target table name to load data into * - ``-target_db`` - Optional - *None* - Database name ``string`` - Target database name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 1bb263b7f19ac05f931d56a6cf84c11e8949c76b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 10:57:34 +0200 Subject: [PATCH 1003/1892] RN --- .../max_statement_inactivity_seconds.rst | 2 +- releases/4.0_index.rst | 3 +- releases/4.5.rst | 54 ++------------- releases/4.6.rst | 66 +++++++++++++++++++ 4 files changed, 75 insertions(+), 50 deletions(-) create mode 100644 releases/4.6.rst diff --git a/configuration_guides/max_statement_inactivity_seconds.rst b/configuration_guides/max_statement_inactivity_seconds.rst index a6e35d28c..868d1ab64 100644 --- a/configuration_guides/max_statement_inactivity_seconds.rst +++ b/configuration_guides/max_statement_inactivity_seconds.rst @@ -4,7 +4,7 @@ MAX STATEMENT INACTIVITY SECONDS ******************************** -The ``maxConnectionInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. +The ``maxStatementInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. * **Data type** - size_t * **Default value** - ``5*60*60 seconds (18000)`` diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 6dfb60bd1..785ee501b 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -16,4 +16,5 @@ 4.1 4.2 4.3 - 4.4 \ No newline at end of file + 4.4 + 4.5 \ No newline at end of file diff --git a/releases/4.5.rst b/releases/4.5.rst index 617b5e456..b9dbeb04a 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -65,58 +65,16 @@ Version 4.4 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+================================================================================================+ -| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | +| SQ-11523 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-11804 | Slow metadata optimization | +| SQ-14292 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | +| SQ-15074 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12799 | Catalog queries may not be terminated | +| SQ-15547 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12965 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13112 | ``GRANT`` query queue issue | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13210, SQ-13426 | Slow query execution time | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13322 | Cleanup operation case-sensitivity issue | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13453 | Metadata performance issue | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13461 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13467 | Snapshot issue causes metadata failure | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13587 | Large number of worker connections failure | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13772 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13805 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13947 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13954 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13971 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14094 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14136 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14268 -| SQ-14399 -| SQ-14400 -| SQ-14556 -| SQ-14724 -| SQ-15074 + + diff --git a/releases/4.6.rst b/releases/4.6.rst new file mode 100644 index 000000000..d3495484f --- /dev/null +++ b/releases/4.6.rst @@ -0,0 +1,66 @@ +.. _4.6: + +***************** +Release Notes 4.6 +***************** + +The 4.6 release notes were released on XXXXXXXXXXX + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 49 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.0.0 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 5.0.0 | +| | * Spark | ++-------------------------+------------------------------------------------------------------------+ + + +| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-11804 | Slow metadata optimization | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12799 | Catalog queries may not be terminated | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-12965 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13112 | ``GRANT`` query queue issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13210, SQ-13426 | Slow query execution time | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13322 | Cleanup operation case-sensitivity issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13453 | Metadata performance issue | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13461 | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13467 | Snapshot issue causes metadata failure | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13587 | Large number of worker connections failure | ++--------------------+------------------------------------------------------------------------------------------------+ \ No newline at end of file From 80e9415249655d92f33296f8aa488cb80b7a4e9c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 11:17:08 +0200 Subject: [PATCH 1004/1892] SQLoader --- data_ingestion/ingesting_from_databases.rst | 2 +- releases/4.5.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index e3b645c6f..4690b68f5 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Source table name - Table name ``string`` - Target table name to load data into * - ``-target_db`` - Optional - *None* - Database name ``string`` - Target database name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file diff --git a/releases/4.5.rst b/releases/4.5.rst index b9dbeb04a..ed3680239 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -65,9 +65,9 @@ Version 4.4 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+================================================================================================+ -| SQ-11523 | +| SQ-11523 | Saved query ``datetime`` internal runtime issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14292 | +| SQ-14292 | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-15074 | +--------------------+------------------------------------------------------------------------------------------------+ From 4c4b47f10be8ac69e03f11d0f09e87990cafdf92 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:29:13 +0200 Subject: [PATCH 1005/1892] maxStatementInactivitySeconds --- .../max_statement_inactivity_seconds.rst | 2 +- releases/4.5.rst | 12 +++--------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/configuration_guides/max_statement_inactivity_seconds.rst b/configuration_guides/max_statement_inactivity_seconds.rst index 868d1ab64..7a1483f6c 100644 --- a/configuration_guides/max_statement_inactivity_seconds.rst +++ b/configuration_guides/max_statement_inactivity_seconds.rst @@ -4,7 +4,7 @@ MAX STATEMENT INACTIVITY SECONDS ******************************** -The ``maxStatementInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. +The ``maxStatementInactivitySeconds`` parameter is optional and determines the maximum duration of statement inactivity before terminating the Worker. Its behavior is contingent on the configuration of ``healerActionGracefulShutdown``. If set to ``true``, it triggers a graceful Worker shutdown; if set to ``false``, the Worker continues without shutting down, accompanied by relevant log information regarding the stuck query. * **Data type** - size_t * **Default value** - ``5*60*60 seconds (18000)`` diff --git a/releases/4.5.rst b/releases/4.5.rst index ed3680239..face5f839 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -34,9 +34,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► The newly supported :ref:`sql_data_type_array` data type enables you to simplify queries and optimize space utilization. +► :ref:`Health-Check Monitor<>` -► :ref:`denodo` may now be used for real-time data visualization of various sources. +► Newly Released Connector Drivers --------------------------------- @@ -69,14 +69,8 @@ Version 4.4 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | SQ-14292 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15074 | +| SQ-15074 | Non-``SUPERUSER`` UI access issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15547 | -+--------------------+------------------------------------------------------------------------------------------------+ - - - - Configuration Adjustments ------------------------- From a35c145c37d6b9584ecf3813e78985b69f6a1c9b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:33:20 +0200 Subject: [PATCH 1006/1892] Delete healer_max_statement_inactivity_seconds.rst --- .../healer_max_statement_inactivity_seconds.rst | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 configuration_guides/healer_max_statement_inactivity_seconds.rst diff --git a/configuration_guides/healer_max_statement_inactivity_seconds.rst b/configuration_guides/healer_max_statement_inactivity_seconds.rst deleted file mode 100644 index 533888fff..000000000 --- a/configuration_guides/healer_max_statement_inactivity_seconds.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _healer_max_statement_inactivity_seconds: - -************************* -Max Statement Inactivity Seconds -************************* -The ``maxStatementInactivitySeconds`` flag is used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. - -The following describes the ``maxStatementInactivitySeconds`` worker flag: - -* **Data type** - size_t -* **Default value** - ``5`` -* **Allowed values** - 1-4000000000 - -For related flags, see :ref:`is_healer_on`. \ No newline at end of file From 0347907dc7ac59623a292831d14774ed441d0d3d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 15:53:56 +0200 Subject: [PATCH 1007/1892] modifying_role --- operational_guides/access_control_permissions.rst | 2 +- .../access_control_commands/alter_default_permissions.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 23d28b031..2883ffee6 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -328,7 +328,7 @@ schema statement is run. .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR target_role_name + ALTER DEFAULT PERMISSIONS FOR modifying_role [IN schema_name, ...] FOR { SCHEMAS diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index c2de52db5..478bbdf5b 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -24,7 +24,7 @@ Syntax .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR target_role_name + ALTER DEFAULT PERMISSIONS FOR modifying_role [IN schema_name, ...] FOR { SCHEMAS From 35bb6eee161527f5d4ad79154bd4e0343a843f08 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:33:55 +0200 Subject: [PATCH 1008/1892] 50 --- releases/4.4.rst | 2 +- releases/4.5.rst | 67 +++++++++++++++--------------------------------- 2 files changed, 22 insertions(+), 47 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index f7c1b8243..522d7265c 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -21,7 +21,7 @@ Compatibility Matrix +---------------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +---------------------------------+------------------------------------------------------------------------+ -| Storage version | 49 | +| Storage version | 50 | +---------------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | diff --git a/releases/4.5.rst b/releases/4.5.rst index face5f839..e4ab7e24f 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -13,23 +13,25 @@ The 4.5 release notes were released on XXXXXXXXXXX Compatibility Matrix -------------------- -+-------------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=========================+========================================================================+ -| Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x / 8.x | -+-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | -+-------------------------+------------------------------------------------------------------------+ -| Storage version | 49 | -+-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.0.0 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | -| | * Pysqream 5.0.0 | -| | * Spark | -+-------------------------+------------------------------------------------------------------------+ ++---------------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=================================+========================================================================+ +| Supported OS | * CentOS 7.x | +| | * RHEL 7.x / 8.x | ++---------------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++---------------------------------+------------------------------------------------------------------------+ +| Storage version | 50 | ++---------------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.0.0 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 5.0.0 | +| | * Spark | ++---------------------------------+------------------------------------------------------------------------+ +| SQream Acceleration Studio | Version 5.7.0 | ++---------------------------------+------------------------------------------------------------------------+ New Features and Enhancements ----------------------------- @@ -38,19 +40,6 @@ New Features and Enhancements ► -Newly Released Connector Drivers ---------------------------------- - -► **Pysqream 5.0.0** - -* `tar.file <https://github.com/SQream/pysqream/releases/tag/v5.0.0>`_ -* :ref:`Documentation<pysqream>` - -► **JDBC 5.0.0** - -* `jar.file <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ -* :ref:`Documentation<java_jdbc>` - Known Issues ------------ @@ -59,7 +48,7 @@ Known Issues * Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression -Version 4.4 resolved Issues +Version 4.5 resolved Issues --------------------------- +--------------------+------------------------------------------------------------------------------------------------+ @@ -91,21 +80,7 @@ Deprecations * **REHL 8.x** is now officially supported. -► ``INT96`` - -Due to Parquet's lack of support of the ``INT96`` data type, SQreamDB has decided to deprecate this data type. - - -► Square Brackets ``[]`` - -The ``[]``, which are frequently used to delimit :ref:`identifiers<keywords_and_identifiers>` such as column names, table names, and other database objects, are officially deprecated to facilitate the use of the ``ARRAY`` data type. To delimit database object identifiers, use double quotes ``""``. - - -► ``VARCHAR`` - -With the improvement of the core functionalities of the platform and to align with the constantly evolving ecosystem requirements, the ``VARCHAR`` data type is deprecated and may not be used. The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. - -Upgrading to Version 4.4 +Upgrading to Version 4.5 ------------------------- 1. Generate a back-up of the metadata by running the following command: From b4069a32cd421462dbb87525d8d035e663605c71 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:34:53 +0200 Subject: [PATCH 1009/1892] 50 --- releases/4.4.rst | 2 +- releases/4.5.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.4.rst b/releases/4.4.rst index 522d7265c..55dbe8de1 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -21,7 +21,7 @@ Compatibility Matrix +---------------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +---------------------------------+------------------------------------------------------------------------+ -| Storage version | 50 | +| Storage version | 50 | +---------------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | diff --git a/releases/4.5.rst b/releases/4.5.rst index e4ab7e24f..2d2e5733f 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -21,7 +21,7 @@ Compatibility Matrix +---------------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +---------------------------------+------------------------------------------------------------------------+ -| Storage version | 50 | +| Storage version | 50 | +---------------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | From 3251664b34a73c277cdf499bfb0e69b8a62df679 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 Nov 2023 16:42:11 +0200 Subject: [PATCH 1010/1892] Update 4.5.rst --- releases/4.5.rst | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 2d2e5733f..52a3082c5 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -38,7 +38,9 @@ New Features and Enhancements ► :ref:`Health-Check Monitor<>` -► +► :ref:`Query Timeout Per Service<>` + +► :ref:```JOIN`` Performance Enhancements<>` Known Issues ------------ @@ -56,21 +58,13 @@ Version 4.5 resolved Issues +====================+================================================================================================+ | SQ-11523 | Saved query ``datetime`` internal runtime issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14292 | +| SQ-14292 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-14869 | | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-15074 | Non-``SUPERUSER`` UI access issue | +--------------------+------------------------------------------------------------------------------------------------+ -Configuration Adjustments -------------------------- - -► You may now configure the object access style and your endpoint URL with Virtual Private Cloud (VPC) when using AWS S3. - -Visit :ref:`s3` to learn more about how and when you should use these two new parameters: - -* ``AwsEndpointOverride`` -* ``AwsObjectAccessStyle`` - Deprecations ------------------- @@ -82,6 +76,7 @@ Deprecations Upgrading to Version 4.5 ------------------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console From 9678b3678d25f3f035a674690c4557fea2b03eea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:14:57 +0200 Subject: [PATCH 1011/1892] SQLAlchemy limitation --- connecting_to_sqream/client_drivers/python/index.rst | 5 +++++ data_type_guides/sql_data_type_array.rst | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index d4cee407c..d56f2de1a 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -128,6 +128,11 @@ SQLAlchemy SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. +Limitation +----------- + +Please note that SQLAlchemy does not support the ``ARRAY`` data type. + .. contents:: :local: :depth: 1 diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index b3e296686..863f2824c 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -16,6 +16,11 @@ The maximum size of an ``ARRAY``, indicating the number of elements it can hold, .. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. +Limitation +------------- + +Please note that SQLAlchemy does not support the ``ARRAY`` data type. + Syntax ====== From 212bde143b96d93a3ad5ff3fccfe059eabcaf7c9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:20:01 +0200 Subject: [PATCH 1012/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index bbad40a37..03fb1c5d5 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -57,6 +57,8 @@ Maximum Workers Per GPU: - 6 * - NVIDIA Tesla H100 (80GB) - 6 + * - L40S (48GB) + - 4 From 0eafd1d04168edafc51cb8c840ddff22866bbbed Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:38:33 +0200 Subject: [PATCH 1013/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 03fb1c5d5..740a5ff10 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -47,17 +47,17 @@ Maximum Workers Per GPU: * - GPU - Workers - * - NVIDIA Tesla T4 (16GB) + * - NVIDIA Turing T4 (16GB) - 1 - * - NVIDIA Tesla V100 (32GB) + * - NVIDIA Volta V100 (32GB) - 2 - * - NVIDIA Tesla A100 (40GB) + * - NVIDIA Ampere A100 (40GB) - 3 - * - NVIDIA Tesla A100 (80GB) + * - NVIDIA Ampere A100 (80GB) - 6 - * - NVIDIA Tesla H100 (80GB) + * - NVIDIA Hopper H100 (80GB) - 6 - * - L40S (48GB) + * - L40S Ada Lovelace (48GB) - 4 From 2d913e91e0e2d3a6e726d785b130f9ec50495d1e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 08:47:04 +0200 Subject: [PATCH 1014/1892] Update installing_sqream_with_binary.rst --- installation_guides/installing_sqream_with_binary.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/installing_sqream_with_binary.rst b/installation_guides/installing_sqream_with_binary.rst index ba9a575e9..9c79c1688 100644 --- a/installation_guides/installing_sqream_with_binary.rst +++ b/installation_guides/installing_sqream_with_binary.rst @@ -87,7 +87,7 @@ In each JSON file, the following parameters **must be updated**: * port * ssl_port -See how to :ref:`configure <spooling>` the Spool Memory. +See how to :ref:`configure <spooling>` the Spool Memory and Limit Query Memory. Note the following: From 56e6d58f72c08eaacc2761dda7937ed1b3b995be Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:21:51 +0200 Subject: [PATCH 1015/1892] Health-Check Monitor --- reference/sql/sql_statements/index.rst | 2 + .../select_health_check_monitoring.rst | 160 ++++++++++++++++++ 2 files changed, 162 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index f1141b0b7..25699492b 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -135,6 +135,8 @@ The following table shows the Utility commands: - Monitor license quota usage by reviewing monthly or daily data read usage * - :ref:`SELECT GPU METRICS<select_gpu_metrics>` - Monitor license quota usage by reviewing monthly or daily GPU usage + * - :ref:`SELECT HEALTH CHECK MONITORING<select_health_check_monitoring>` + - Returns system health monitoring logs * - :ref:`SELECT RECOMPILE VIEW<recompile_view>` - Recreate a view after schema changes * - :ref:`SELECT DUMP DATABASE DDL<dump_database_ddl>` diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst new file mode 100644 index 000000000..16efd5a4f --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -0,0 +1,160 @@ +.. _select_health_check_monitoring: + +******************************* +SELECT HEALTH CHECK MONITORING +******************************* + +The ``SELECT health_check_monitoring`` command allows system administrators to oversee the health of the database by monitoring the following categories: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Category + - Description + * - ``storage`` + - + * - ``metadata_stats`` + - + * - ``license`` + - + * - ``self_healing`` + - + +Syntax +========== + +.. code-block:: sql + + SELECT health_check_monitoring('<category>', '<input_file>', '<export_path>') + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Description + * - ``category`` + - Mandatory + - Specifies the system area for which to get health information about + * - ``input_file`` + - Mandatory + - The path to the specific configuration file of the *category* you wish to get information about + * - ``export_path`` + - Mandatory + - The path to the directory you wish to have your monitoring log file to extracted to + +Storage +-------- + +Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - + - + + + +Example +^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('storage', '', '') + +License +-------- + +Provides details about the customer's license, including database storage capacity and licensing restrictions. Proactively alerts the customer before reaching license limitations, ensuring awareness and timely action. + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - + - + + + +Example +^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('license', '', '') + +self_healing +-------------- + + +Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - + - + + + +Example +^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('self_healing', '', '') + +Metadata Statistics +-------------------- + +Provides information on Worker and metadata reactivity. Regular monitoring allows for the identification of the system's performance during peak loads, indicating periods of heavy system load. This insight can be invaluable for uncovering potential concurrent issues. + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - + - + + + + +Example +^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('metadata_stats', '', '') + +Permissions +============= + +Using the ``SELECT health_check_monitoring`` command requires ``SUPERUSER`` permissions. \ No newline at end of file From a5809d75435875d9ac0b1676cfd3a73f739a0e04 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 22 Nov 2023 16:42:53 +0200 Subject: [PATCH 1016/1892] Health-Check Monitoring --- .../select_health_check_monitoring.rst | 25 +++++++++---------- releases/4.5.rst | 4 +-- 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 16efd5a4f..ed828fbbf 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -6,20 +6,19 @@ SELECT HEALTH CHECK MONITORING The ``SELECT health_check_monitoring`` command allows system administrators to oversee the health of the database by monitoring the following categories: -.. list-table:: - :widths: auto - :header-rows: 1 +.. glossary:: - * - Category - - Description - * - ``storage`` - - - * - ``metadata_stats`` - - - * - ``license`` - - - * - ``self_healing`` - - + storage + Offers insights into cluster storage chunks and their fragmentation, indicating irrelevant files to prevent bottlenecks during table readings. + + metadata_stats + Provides information on Worker and metadata reactivity. Regular monitoring identifies system performance during peak loads, revealing potential concurrent issues. + + license + Gives details on the customer's license, including storage capacity and restrictions. Proactively alerts before reaching limitations for timely action. + + self_healing + Supplies ETL and load details, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots. Essential for regular monitoring, providing clear insights during the RCA process for optimal resource allocation. Syntax ========== diff --git a/releases/4.5.rst b/releases/4.5.rst index 52a3082c5..61230958a 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -36,11 +36,11 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► :ref:`Health-Check Monitor<>` +► :ref:`Health-Check Monitor<select_health_check_monitoring>` ► :ref:`Query Timeout Per Service<>` -► :ref:```JOIN`` Performance Enhancements<>` +► ``JOIN`` Performance Enhancements Known Issues ------------ From fe4ec9093ac8c55f7905a51ab8101baaeb9010b4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:14:51 +0200 Subject: [PATCH 1017/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 196 ++++++++++++++---- 1 file changed, 158 insertions(+), 38 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index ed828fbbf..b72e1dc59 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -4,21 +4,15 @@ SELECT HEALTH CHECK MONITORING ******************************* -The ``SELECT health_check_monitoring`` command allows system administrators to oversee the health of the database by monitoring the following categories: +The ``SELECT health_check_monitoring`` command empowers system administrators to comprehensively monitor the database's health across multiple *categories*. -.. glossary:: - - storage - Offers insights into cluster storage chunks and their fragmentation, indicating irrelevant files to prevent bottlenecks during table readings. - - metadata_stats - Provides information on Worker and metadata reactivity. Regular monitoring identifies system performance during peak loads, revealing potential concurrent issues. +In the ``storage`` domain, it provides insights into cluster storage chunks and their fragmentation, helping prevent bottlenecks during table readings by identifying irrelevant files. The ``metadata_stats`` category offers information on Worker and metadata reactivity, enabling the identification of system performance during peak loads and the revelation of potential concurrent issues. Addressing licensing concerns, the command gives details on the customer's ``license``, including storage capacity and restrictions, and proactively alerts administrators before reaching limitations. Lastly, under ``self_healing``, it supplies essential details on ETL and load processes, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots—crucial for regular monitoring and offering clear insights during the Root Cause Analysis (RCA) process for optimal resource allocation. - license - Gives details on the customer's license, including storage capacity and restrictions. Proactively alerts before reaching limitations for timely action. - - self_healing - Supplies ETL and load details, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots. Essential for regular monitoring, providing clear insights during the RCA process for optimal resource allocation. +Here you can find information about how to configure and execute each of the 4 monitoring categories. + +.. contents:: + :local: + :depth: 2 Syntax ========== @@ -39,7 +33,7 @@ Parameters - Description * - ``category`` - Mandatory - - Specifies the system area for which to get health information about + - Specifies the system domain for which to get health information about. The 4 categories are: ``storage``, ``metadata_stats``, ``license``, and ``self_healing`` * - ``input_file`` - Mandatory - The path to the specific configuration file of the *category* you wish to get information about @@ -47,11 +41,131 @@ Parameters - Mandatory - The path to the directory you wish to have your monitoring log file to extracted to +Configuration File +=================== + +The Health-Check Monitor has a default configuration file. To reconfigure any of the default metric values, navigate to the ``input.json`` file located under... and modify according to your personal preferences. + +Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseExpire`` require valid range configuration. Keep in mind that your default configuration file is best-practice configured. + +Default Metric Values +---------------------- + +.. code-block:: json + + { + "totalNumberOfFragmentedChunks":{ + "from":0, + "to":100 + }, + "percentageStorageCapacity":{ + "from":0, + "to":0.9 + }, + "daysForLicenseExpire":{ + "from":60 + }, + "stuckSnapshots":{ + "from":0, + "to":2 + }, + "queriesInQueue":{ + "from":0, + "to":100 + }, + "availableWorkers":{ + "from":0, + "to":5 + }, + "nodeHeartbeatMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "checkLocksMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysAndValuesNMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "nodeHeartbeatMsgVariance":{ + "from":0, + "to":1000 + }, + "checkLocksMsgVariance":{ + "from":0, + "to":1000 + }, + "keysAndValuesNVariance":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgVariance":{ + "from":0, + "to":1000 + } + } + +Log File +========= + +Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseExpire`` require valid range configuration. Valid range metrics will show one of three different metric statuses in the log file: ``info``, ``warning``, or ``none``. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Metric Status + - Description + * - ``info`` + - If the metric falls within the valid range, the metric status will be logged as ``info`` + * - ``warning`` + - If the metric exceeds the valid range, the metric status will be logged as ``warning`` + * - ``none`` + - If the metric does not have a valid range, the metric status will be logged as ``none`` + +Category Specifications +======================== + Storage -------- Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. +You may filter ``storage`` health-check by database, schema, and table. + +Execution Example +^^^^^^^^^^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('storage', '', '') + +Metrics +^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Metric + - Configuration Flag + - Default Value + - Description + * - ``No. storage chunks`` + - NA + - NA + - + * - ``No. fragmented chunks`` + - ``totalNumberOfFragmentedChunks`` + - + - + Output ^^^^^^^^^ @@ -61,22 +175,26 @@ Output * - Parameter - Description - * - - - + * - ``metric_time`` + - + * - ``metric_category`` + - + * - ``metric_name`` + - + * - ``metric_description`` + - + * - ``metric_value`` + - + * - ``metric_validation_status`` + - + * - ``response_time_sec`` + - - -Example -^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('storage', '', '') - -License --------- +Metadata Statistics +-------------------- -Provides details about the customer's license, including database storage capacity and licensing restrictions. Proactively alerts the customer before reaching license limitations, ensuring awareness and timely action. +Provides information on Worker and metadata reactivity. Regular monitoring allows for the identification of the system's performance during peak loads, indicating periods of heavy system load. This insight can be invaluable for uncovering potential concurrent issues. Output ^^^^^^^^^ @@ -89,6 +207,7 @@ Output - Description * - - + @@ -97,13 +216,12 @@ Example .. code-block:: sql - SELECT health_check_monitoring('license', '', '') - -self_healing --------------- + SELECT health_check_monitoring('metadata_stats', '', '') +License +-------- -Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. +Provides details about the customer's license, including database storage capacity and licensing restrictions. Proactively alerts the customer before reaching license limitations, ensuring awareness and timely action. Output ^^^^^^^^^ @@ -124,12 +242,13 @@ Example .. code-block:: sql - SELECT health_check_monitoring('self_healing', '', '') + SELECT health_check_monitoring('license', '', '') -Metadata Statistics --------------------- +self_healing +-------------- -Provides information on Worker and metadata reactivity. Regular monitoring allows for the identification of the system's performance during peak loads, indicating periods of heavy system load. This insight can be invaluable for uncovering potential concurrent issues. + +Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. Output ^^^^^^^^^ @@ -142,7 +261,6 @@ Output - Description * - - - @@ -151,7 +269,9 @@ Example .. code-block:: sql - SELECT health_check_monitoring('metadata_stats', '', '') + SELECT health_check_monitoring('self_healing', '', '') + + Permissions ============= From a2dad3f76b6b3e38a31393564561dbd6614ecce7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Nov 2023 13:25:56 +0200 Subject: [PATCH 1018/1892] health check monitor --- _static/samples/input.json | 57 +++++++++++++++++++ .../utility_commands/input.json | 57 +++++++++++++++++++ .../select_health_check_monitoring.rst | 26 +++++---- 3 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 _static/samples/input.json create mode 100644 reference/sql/sql_statements/utility_commands/input.json diff --git a/_static/samples/input.json b/_static/samples/input.json new file mode 100644 index 000000000..bfd11d94e --- /dev/null +++ b/_static/samples/input.json @@ -0,0 +1,57 @@ +{ + "totalNumberOfFragmentedChunks":{ + "from":0, + "to":100 + }, + "percentageStorageCapacity":{ + "from":0, + "to":0.9 + }, + "daysForLicenseExpire":{ + "from":60 + }, + "stuckSnapshots":{ + "from":0, + "to":2 + }, + "queriesInQueue":{ + "from":0, + "to":100 + }, + "availableWorkers":{ + "from":0, + "to":5 + }, + "nodeHeartbeatMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "checkLocksMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysAndValuesNMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "nodeHeartbeatMsgVariance":{ + "from":0, + "to":1000 + }, + "checkLocksMsgVariance":{ + "from":0, + "to":1000 + }, + "keysAndValuesNVariance":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgVariance":{ + "from":0, + "to":1000 + } +} \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/input.json b/reference/sql/sql_statements/utility_commands/input.json new file mode 100644 index 000000000..bfd11d94e --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/input.json @@ -0,0 +1,57 @@ +{ + "totalNumberOfFragmentedChunks":{ + "from":0, + "to":100 + }, + "percentageStorageCapacity":{ + "from":0, + "to":0.9 + }, + "daysForLicenseExpire":{ + "from":60 + }, + "stuckSnapshots":{ + "from":0, + "to":2 + }, + "queriesInQueue":{ + "from":0, + "to":100 + }, + "availableWorkers":{ + "from":0, + "to":5 + }, + "nodeHeartbeatMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "checkLocksMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysAndValuesNMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgMaxResponseTimeMS":{ + "from":0, + "to":1000 + }, + "nodeHeartbeatMsgVariance":{ + "from":0, + "to":1000 + }, + "checkLocksMsgVariance":{ + "from":0, + "to":1000 + }, + "keysAndValuesNVariance":{ + "from":0, + "to":1000 + }, + "keysWithPrefixMsgVariance":{ + "from":0, + "to":1000 + } +} \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index b72e1dc59..7dcd22c93 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -1,19 +1,24 @@ .. _select_health_check_monitoring: ******************************* -SELECT HEALTH CHECK MONITORING +HEALTH CHECK MONITORING ******************************* The ``SELECT health_check_monitoring`` command empowers system administrators to comprehensively monitor the database's health across multiple *categories*. In the ``storage`` domain, it provides insights into cluster storage chunks and their fragmentation, helping prevent bottlenecks during table readings by identifying irrelevant files. The ``metadata_stats`` category offers information on Worker and metadata reactivity, enabling the identification of system performance during peak loads and the revelation of potential concurrent issues. Addressing licensing concerns, the command gives details on the customer's ``license``, including storage capacity and restrictions, and proactively alerts administrators before reaching limitations. Lastly, under ``self_healing``, it supplies essential details on ETL and load processes, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots—crucial for regular monitoring and offering clear insights during the Root Cause Analysis (RCA) process for optimal resource allocation. -Here you can find information about how to configure and execute each of the 4 monitoring categories. - +Here, you can discover details on configuring the monitoring for each of the four categories, along with instructions on how to access and interpret the log files for each category. + .. contents:: :local: - :depth: 2 - + :depth: 1 + +Before You Begin +================== + +Download the Health-Check Monitor :download:`input.json configuration file </_static/samples/input.json>` and save it anywhere you want. + Syntax ========== @@ -22,31 +27,28 @@ Syntax SELECT health_check_monitoring('<category>', '<input_file>', '<export_path>') Parameters -============ +----------- .. list-table:: :widths: auto :header-rows: 1 * - Parameter - - State - Description * - ``category`` - - Mandatory - Specifies the system domain for which to get health information about. The 4 categories are: ``storage``, ``metadata_stats``, ``license``, and ``self_healing`` * - ``input_file`` - - Mandatory - The path to the specific configuration file of the *category* you wish to get information about * - ``export_path`` - - Mandatory - The path to the directory you wish to have your monitoring log file to extracted to Configuration File =================== -The Health-Check Monitor has a default configuration file. To reconfigure any of the default metric values, navigate to the ``input.json`` file located under... and modify according to your personal preferences. -Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseExpire`` require valid range configuration. Keep in mind that your default configuration file is best-practice configured. +The Health-Check Monitor configuration file comes pre-configured with best practices, but you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. + +You can set both highest and lowest thresholds for metrics, or choose to configure only one. Note that configuring only one threshold will make the Health-Check Monitor assume the other threshold is set to *infinity*. Default Metric Values ---------------------- From ceb52cc8c06447129c411cc9cc35e0523c9365f3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Nov 2023 14:05:38 +0200 Subject: [PATCH 1019/1892] ODBC --- .../odbc/install_configure_odbc_linux.rst | 5 +- .../utility_commands/input.json | 57 ------------------- 2 files changed, 2 insertions(+), 60 deletions(-) delete mode 100644 reference/sql/sql_statements/utility_commands/input.json diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index ff99fd6ee..83f8df52e 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -73,14 +73,13 @@ Use this method if you have never used ODBC on your machine before. If you have .. code-block:: console - $ mkdir -p sqream_odbc64 - $ tar xf sqream_2019.2.1_odbc_3.0.0_x86_64_linux.tar.gz -C sqream_odbc64 + $ tar xf sqream_xxxxxxxxxxxxx.tar.gz -C sqream_odbc64 #. Run the first-time installer. The installer will create an editable DSN. .. code-block:: console - $ cd sqream_odbc64 + $ cd sqream_odbc_installer ./odbc_install.sh --install diff --git a/reference/sql/sql_statements/utility_commands/input.json b/reference/sql/sql_statements/utility_commands/input.json deleted file mode 100644 index bfd11d94e..000000000 --- a/reference/sql/sql_statements/utility_commands/input.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "totalNumberOfFragmentedChunks":{ - "from":0, - "to":100 - }, - "percentageStorageCapacity":{ - "from":0, - "to":0.9 - }, - "daysForLicenseExpire":{ - "from":60 - }, - "stuckSnapshots":{ - "from":0, - "to":2 - }, - "queriesInQueue":{ - "from":0, - "to":100 - }, - "availableWorkers":{ - "from":0, - "to":5 - }, - "nodeHeartbeatMsgMaxResponseTimeMS":{ - "from":0, - "to":1000 - }, - "checkLocksMsgMaxResponseTimeMS":{ - "from":0, - "to":1000 - }, - "keysAndValuesNMaxResponseTimeMS":{ - "from":0, - "to":1000 - }, - "keysWithPrefixMsgMaxResponseTimeMS":{ - "from":0, - "to":1000 - }, - "nodeHeartbeatMsgVariance":{ - "from":0, - "to":1000 - }, - "checkLocksMsgVariance":{ - "from":0, - "to":1000 - }, - "keysAndValuesNVariance":{ - "from":0, - "to":1000 - }, - "keysWithPrefixMsgVariance":{ - "from":0, - "to":1000 - } -} \ No newline at end of file From 75fb440fec4a2e01ae1285fdb3afd6fe9788bf68 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 23 Nov 2023 16:16:40 +0200 Subject: [PATCH 1020/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 204 ++++++++++++------ 1 file changed, 144 insertions(+), 60 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 7dcd22c93..ac3a703af 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -17,38 +17,17 @@ Here, you can discover details on configuring the monitoring for each of the fou Before You Begin ================== -Download the Health-Check Monitor :download:`input.json configuration file </_static/samples/input.json>` and save it anywhere you want. +* Download the Health-Check Monitor :download:`input.json </_static/samples/input.json>` configuration file and save it anywhere you want. +* Using the ``SELECT health_check_monitoring`` command requires ``SUPERUSER`` permissions. -Syntax -========== - -.. code-block:: sql - - SELECT health_check_monitoring('<category>', '<input_file>', '<export_path>') - -Parameters ------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``category`` - - Specifies the system domain for which to get health information about. The 4 categories are: ``storage``, ``metadata_stats``, ``license``, and ``self_healing`` - * - ``input_file`` - - The path to the specific configuration file of the *category* you wish to get information about - * - ``export_path`` - - The path to the directory you wish to have your monitoring log file to extracted to - -Configuration File -=================== +Setup +====== +There are two types of Health-Check Monitor metrics. The first type, valid-range metrics, may be reconfigured by adjusting the lowest threshold, the highest threshold, or both. The second type of metric is non-configurable, as it returns existing system information instead of measuring resource usage. -The Health-Check Monitor configuration file comes pre-configured with best practices, but you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. +The Health-Check Monitor configuration file is pre-configured with best practices, but you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. -You can set both highest and lowest thresholds for metrics, or choose to configure only one. Note that configuring only one threshold will make the Health-Check Monitor assume the other threshold is set to *infinity*. +You can set both highest and lowest thresholds, or choose to configure only one. Note that configuring only one threshold will make the Health-Check Monitor assume the ignored threshold is set to *infinity*. Default Metric Values ---------------------- @@ -113,8 +92,32 @@ Default Metric Values } } -Log File -========= +General Syntax +=============== + +.. code-block:: sql + + SELECT health_check_monitoring('<category>', '<input_file>', '<export_path>') + +Parameters +----------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``category`` + - Specifies the system domain for which to get health information about. The 4 categories are: ``storage``, ``metadata_stats``, ``license``, and ``self_healing`` + * - ``input_file`` + - The path to the specific configuration file of the *category* you wish to get information about + * - ``export_path`` + - The path to the directory you wish to have your monitoring log file to extracted to + + +Logs +===== Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseExpire`` require valid range configuration. Valid range metrics will show one of three different metric statuses in the log file: ``info``, ``warning``, or ``none``. @@ -134,6 +137,8 @@ Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseE Category Specifications ======================== + + Storage -------- @@ -146,7 +151,16 @@ Execution Example .. code-block:: sql - SELECT health_check_monitoring('storage', '', '') + SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +Execution Example With Filtering +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You may filter storage information retrieval by database, schema, table, or all three. + +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') Metrics ^^^^^^^^ @@ -168,6 +182,13 @@ Metrics - - +Execution Example +^^^^^^^^^^^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') + Output ^^^^^^^^^ @@ -198,84 +219,147 @@ Metadata Statistics Provides information on Worker and metadata reactivity. Regular monitoring allows for the identification of the system's performance during peak loads, indicating periods of heavy system load. This insight can be invaluable for uncovering potential concurrent issues. -Output -^^^^^^^^^ +Metrics +^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - Parameter + * - Metric + - Configuration Flag + - Default Value - Description - * - - - - - - Example ^^^^^^^^^ .. code-block:: sql - SELECT health_check_monitoring('metadata_stats', '', '') + SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``metric_time`` + - + * - ``metric_category`` + - + * - ``metric_name`` + - + * - ``metric_description`` + - + * - ``metric_value`` + - + * - ``metric_validation_status`` + - + * - ``response_time_sec`` + - + License -------- Provides details about the customer's license, including database storage capacity and licensing restrictions. Proactively alerts the customer before reaching license limitations, ensuring awareness and timely action. -Output -^^^^^^^^^ +Metrics +^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - Parameter + * - Metric + - Configuration Flag + - Default Value - Description - * - - - - - Example ^^^^^^^^^ .. code-block:: sql - SELECT health_check_monitoring('license', '', '') + SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +Output +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``metric_time`` + - + * - ``metric_category`` + - + * - ``metric_name`` + - + * - ``metric_description`` + - + * - ``metric_value`` + - + * - ``metric_validation_status`` + - + * - ``response_time_sec`` + - + + self_healing -------------- - Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. -Output -^^^^^^^^^ +Metrics +^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - Parameter + * - Metric + - Configuration Flag + - Default Value - Description - * - - - - - Example ^^^^^^^^^ .. code-block:: sql - SELECT health_check_monitoring('self_healing', '', '') + SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +Output +^^^^^^^^^ +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``metric_time`` + - + * - ``metric_category`` + - + * - ``metric_name`` + - + * - ``metric_description`` + - + * - ``metric_value`` + - + * - ``metric_validation_status`` + - + * - ``response_time_sec`` + - -Permissions -============= -Using the ``SELECT health_check_monitoring`` command requires ``SUPERUSER`` permissions. \ No newline at end of file From 359751c319782b27e93e2a50aa1a893eddecf3df Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:33:52 +0200 Subject: [PATCH 1021/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 4690b68f5..63a56a19f 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other databases. **SQLoader** supports Oracle and Postgresql. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.7.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.7.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps Postgresql and Oracle data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Configuring SQLoader Connection ------------------------------- 1. Open the ``sqload-jdbc.properties`` file. 2. Configure the following parameters for: a. Either Postgresql, Oracle, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 6aed19686ce6132c62589875b0da5bd19473a7c7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:43:37 +0200 Subject: [PATCH 1022/1892] Update install_configure_odbc_linux.rst --- .../client_drivers/odbc/install_configure_odbc_linux.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index 83f8df52e..dedfdfe0e 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -60,7 +60,7 @@ Install unixODBC on Ubuntu .. code-block:: console - $ sudo apt-get install unixodbc unixodbc-dev + $ sudo apt-get install odbcinst1debian2 libodbc1 odbcinst unixodbc Install the ODBC driver with a script @@ -73,13 +73,14 @@ Use this method if you have never used ODBC on your machine before. If you have .. code-block:: console - $ tar xf sqream_xxxxxxxxxxxxx.tar.gz -C sqream_odbc64 + $ mkdir -p sqream_odbc64 + $ tar -xf sqream_odbc_vX.Y_x86_64_linux.tar.gz --strip-components=1 -C sqream_odbc64/ #. Run the first-time installer. The installer will create an editable DSN. .. code-block:: console - $ cd sqream_odbc_installer + $ cd sqream_odbc64 ./odbc_install.sh --install From 65d26c3763c3a108b43a6ff7418b31d982e6723e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 08:51:53 +0200 Subject: [PATCH 1023/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index f03f57f83..196482a6e 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -59,7 +59,7 @@ An average single-node cluster can be a rackmount server or workstation, contain NVIDIA 2x A100ת, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -106,7 +106,7 @@ The following table shows SQream's recommended hardware specifications: * - GPU - NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux Metadata Specifications ~~~~~~~~~~~~~~~~~~~~~~~ @@ -132,7 +132,7 @@ The following table shows SQream's recommended metadata server specifications: * - Power sources - Two Power Supplies - 800W AC 50/60Hz 100~240Vac/9.2-4.7A, 3139 BTU/hr * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at 5GB/s or more. @@ -156,7 +156,7 @@ The following table shows SQream's recommended Studio server specifications: * - Onboard storage - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 + - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 Cluster Design Considerations ============================= @@ -229,7 +229,7 @@ Operating System SQream can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v7.9 + * Red Hat Enterprise Linux (RHEL) v7.x / 8.x * CentOS v7.9 * Amazon Linux 2018.03 From db4c3a082b44082a78452a602bbcf81053a2bca9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 09:01:09 +0200 Subject: [PATCH 1024/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index b1374d131..ac82224ce 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -89,7 +89,7 @@ If any doubt arises, consult the documentation for your server or your hardware Installing the Operating System =================================================== -Once the BIOS settings have been set, you must install the operating system. Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.6-7.9) must be installed before installing the SQream database, by either the customer or a SQream representative. +Once the BIOS settings have been set, you must install the operating system. Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.x-8.x) must be installed before installing the SQream database, by either the customer or a SQream representative. **To install the operating system:** From 17fe7f998c3670da0617c249210b661962f428f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:54:05 +0200 Subject: [PATCH 1025/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index ac3a703af..7e72a26c5 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -1,7 +1,7 @@ .. _select_health_check_monitoring: ******************************* -HEALTH CHECK MONITORING +HEALTH-CHECK MONITORING ******************************* The ``SELECT health_check_monitoring`` command empowers system administrators to comprehensively monitor the database's health across multiple *categories*. @@ -12,22 +12,20 @@ Here, you can discover details on configuring the monitoring for each of the fou .. contents:: :local: - :depth: 1 + :depth: 2 Before You Begin ================== * Download the Health-Check Monitor :download:`input.json </_static/samples/input.json>` configuration file and save it anywhere you want. -* Using the ``SELECT health_check_monitoring`` command requires ``SUPERUSER`` permissions. +* The ``SELECT health_check_monitoring`` command requires ``SUPERUSER`` permissions. -Setup -====== - -There are two types of Health-Check Monitor metrics. The first type, valid-range metrics, may be reconfigured by adjusting the lowest threshold, the highest threshold, or both. The second type of metric is non-configurable, as it returns existing system information instead of measuring resource usage. +Configuration +-------------- -The Health-Check Monitor configuration file is pre-configured with best practices, but you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. +There are two types of Health-Check Monitor metrics: one is configurable, and the second is non-configurable. Non-configurable metrics provide information about the system, such as total storage capacity measured in Gigabytes. Configurable metrics are set with low, high, or both thresholds within a valid range to be reported in case of deviation. For example, this could include the number of days remaining on your SQreamDB license. -You can set both highest and lowest thresholds, or choose to configure only one. Note that configuring only one threshold will make the Health-Check Monitor assume the ignored threshold is set to *infinity*. +The Health-Check Monitor configuration file comes pre-configured with best practices. However, as mentioned before, you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. It's important to note that configuring only one threshold will make the Health-Check Monitor assume the ignored threshold is set to *infinity*. Default Metric Values ---------------------- @@ -95,49 +93,56 @@ Default Metric Values General Syntax =============== -.. code-block:: sql +.. code-block:: postgres SELECT health_check_monitoring('<category>', '<input_file>', '<export_path>') + + category :: = { storage | metadata_stats | license | self_healing } -Parameters ------------ - -.. list-table:: +.. list-table:: Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``category`` - - Specifies the system domain for which to get health information about. The 4 categories are: ``storage``, ``metadata_stats``, ``license``, and ``self_healing`` + - Specifies the system domain for which health information is to be retrieved. * - ``input_file`` - - The path to the specific configuration file of the *category* you wish to get information about + - Specifies the path to the configuration file of the designated *category* for which you want to obtain information. * - ``export_path`` - - The path to the directory you wish to have your monitoring log file to extracted to + - Specifies the directory path where you want the monitoring log file to be extracted. -Logs -===== +Health-Check Logs +=================== -Some of the metrics, such as ``percentageStorageCapacity`` and ``daysForLicenseExpire`` require valid range configuration. Valid range metrics will show one of three different metric statuses in the log file: ``info``, ``warning``, or ``none``. +After executing the ``SELECT health_check_monitoring`` command, a system health-check log file is generated and saved in the specified directory. Simultaneously, a result set is displayed in the result pane, showcasing the following output: -.. list-table:: +.. list-table:: Log Output :widths: auto :header-rows: 1 - - * - Metric Status - - Description - * - ``info`` - - If the metric falls within the valid range, the metric status will be logged as ``info`` - * - ``warning`` - - If the metric exceeds the valid range, the metric status will be logged as ``warning`` - * - ``none`` - - If the metric does not have a valid range, the metric status will be logged as ``none`` -Category Specifications -======================== + * - Metric + - Description + * - ``metric_time`` + - The time when the specific metric was checked + * - ``metric_category`` + - The system domain for which health information is retrieved + * - ``metric_name`` + - + * - ``metric_description`` + - + * - ``metric_value`` + - The value of the specific metric + * - ``metric_validation_status`` + - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warning``, metric deviates from its defined valid range + * - ``response_time_sec`` + - +When examining your Health-Check log through the result pane, in addition to the metric output log, your initial valid range configuration is displayed along with the location of your exported log file. +Health-Check Category Specifications +======================================== Storage -------- From 471088f26fb21cf4adc3fd7538dc95c6c490010a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:35:09 +0200 Subject: [PATCH 1026/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 192 +++++++----------- 1 file changed, 70 insertions(+), 122 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 7e72a26c5..d2847d0a2 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,7 +116,7 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, a system health-check log file is generated and saved in the specified directory. Simultaneously, a result set is displayed in the result pane, showcasing the following output: +After executing the ``SELECT health_check_monitoring`` command, both a system health-check log file and a result set are generated. The log file is saved in the specified directory, and the result set is displayed in the result pane, both showcasing the following output: .. list-table:: Log Output :widths: auto @@ -139,7 +139,7 @@ After executing the ``SELECT health_check_monitoring`` command, a system health- * - ``response_time_sec`` - -When examining your Health-Check log through the result pane, in addition to the metric output log, your initial valid range configuration is displayed along with the location of your exported log file. +Besides presenting the metric outputs, the result pane also showcases your initial metric range configuration and provides the location of your exported log file. Health-Check Category Specifications ======================================== @@ -149,8 +149,6 @@ Storage Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. -You may filter ``storage`` health-check by database, schema, and table. - Execution Example ^^^^^^^^^^^^^^^^^^ @@ -158,10 +156,7 @@ Execution Example SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') -Execution Example With Filtering -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You may filter storage information retrieval by database, schema, table, or all three. +You may also filter storage information retrieval by database, schema, table, or all three. .. code-block:: sql @@ -184,41 +179,9 @@ Metrics - * - ``No. fragmented chunks`` - ``totalNumberOfFragmentedChunks`` - - - - - -Execution Example -^^^^^^^^^^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -Output -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``metric_time`` - - - * - ``metric_category`` - - - * - ``metric_name`` - - - * - ``metric_description`` - - - * - ``metric_value`` - - - * - ``metric_validation_status`` - - - * - ``response_time_sec`` + - ``"from":0, "to":100`` - - Metadata Statistics -------------------- @@ -235,37 +198,45 @@ Metrics - Configuration Flag - Default Value - Description + * - ``NodeHeartbeatMsg`` + - ``nodeHeartbeatMsgMaxResponseTimeMS`` + - ``"from":0, "to":1000`` + - + * - ``NodeHeartbeatMsg`` + - ``nodeHeartbeatMsgVariance`` + - ``"from":0, "to":1000`` + - + * - ``CheckLocksMsg`` + - ``checkLocksMsgMaxResponseTimeMS`` + - ``"from":0, "to":1000`` + - + * - ``CheckLocksMsg`` + - ``checkLocksMsgVariance`` + - ``"from":0, "to":1000`` + - + * - ``KeysAndValuesNMsg`` + - ``keysAndValuesNMaxResponseTimeMS`` + - ``"from":0, "to":1000`` + - + * - ``KeysAndValuesNMsg`` + - ``keysAndValuesNVariance`` + - ``"from":0, "to":1000`` + - + * - ``KeysWithPrefixMsg`` + - ``keysWithPrefixMsgMaxResponseTimeMS`` + - ``"from":0, "to":1000`` + - + * - ``KeysWithPrefixMsg`` + - ``keysWithPrefixMsgVariance`` + - ``"from":0, "to":1000`` + - -Example -^^^^^^^^^ +Execution Example +^^^^^^^^^^^^^^^^^^^ .. code-block:: sql SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -Output -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``metric_time`` - - - * - ``metric_category`` - - - * - ``metric_name`` - - - * - ``metric_description`` - - - * - ``metric_value`` - - - * - ``metric_validation_status`` - - - * - ``response_time_sec`` - - License @@ -284,40 +255,31 @@ Metrics - Configuration Flag - Default Value - Description + * - ``Total storage capacity`` + - NA + - NA + - + * - ``Used storage capacity`` + - NA + - NA + - + * - ``% of used storage capacity`` + - ``percentageStorageCapacity`` + - ``"from":0, "to":0.9`` + - + * - ``License expiration date`` + - ``daysForLicenseExpire`` + - ``"from":60`` + - -Example -^^^^^^^^^ +Execution Example +^^^^^^^^^^^^^^^^^^^ .. code-block:: sql SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -Output -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``metric_time`` - - - * - ``metric_category`` - - - * - ``metric_name`` - - - * - ``metric_description`` - - - * - ``metric_value`` - - - * - ``metric_validation_status`` - - - * - ``response_time_sec`` - - - self_healing -------------- @@ -334,37 +296,23 @@ Metrics - Configuration Flag - Default Value - Description + * - ``Queries in queue`` + - ``queriesInQueue`` + - ``"from":0, "to":100`` + - + * - ``Available workers per service`` + - ``availableWorkers`` + - ``"from":0, "to":5`` + - + * - ``Stuck snapshots`` + - ``stuckSnapshots`` + - ``"from":0, "to":2`` + - -Example -^^^^^^^^^ +Execution Example +^^^^^^^^^^^^^^^^^^^ .. code-block:: sql SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') -Output -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``metric_time`` - - - * - ``metric_category`` - - - * - ``metric_name`` - - - * - ``metric_description`` - - - * - ``metric_value`` - - - * - ``metric_validation_status`` - - - * - ``response_time_sec`` - - - - - From 8113dab1d5b964153f9cd614032b66fa78417f25 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 13:57:58 +0200 Subject: [PATCH 1027/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index d2847d0a2..9213b143e 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -25,11 +25,11 @@ Configuration There are two types of Health-Check Monitor metrics: one is configurable, and the second is non-configurable. Non-configurable metrics provide information about the system, such as total storage capacity measured in Gigabytes. Configurable metrics are set with low, high, or both thresholds within a valid range to be reported in case of deviation. For example, this could include the number of days remaining on your SQreamDB license. -The Health-Check Monitor configuration file comes pre-configured with best practices. However, as mentioned before, you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. It's important to note that configuring only one threshold will make the Health-Check Monitor assume the ignored threshold is set to *infinity*. - Default Metric Values ---------------------- +The Health-Check Monitor configuration file comes pre-configured with best practices. However, as mentioned before, you have the flexibility to customize any default metric values based on your preferences. All metrics presented below are defined with valid ranges, so any value outside the range triggers a warning. It's important to note that configuring only one threshold will make the Health-Check Monitor assume the ignored threshold is set to *infinity*. + .. code-block:: json { @@ -149,23 +149,7 @@ Storage Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. -Execution Example -^^^^^^^^^^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -You may also filter storage information retrieval by database, schema, table, or all three. - -.. code-block:: sql - - SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -Metrics -^^^^^^^^ - -.. list-table:: +.. list-table:: Metrics :widths: auto :header-rows: 1 @@ -316,3 +300,18 @@ Execution Example SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') +Examples +========= + +Storage +^^^^^^^^ + +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +You may also filter storage information retrieval by database, schema, table, or all three. + +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') \ No newline at end of file From c1d8feb4c9d45e823757039a06dd1ef9377a90f1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 15:12:34 +0200 Subject: [PATCH 1028/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 71 +++++++------------ 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 9213b143e..29e6d5af8 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -135,7 +135,7 @@ After executing the ``SELECT health_check_monitoring`` command, both a system he * - ``metric_value`` - The value of the specific metric * - ``metric_validation_status`` - - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warning``, metric deviates from its defined valid range + - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warn``, metric deviates from its defined valid range * - ``response_time_sec`` - @@ -149,6 +149,16 @@ Storage Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +When monitoring your storage health, you may also filter information retrieval by database, schema, table, or all three. + +.. code-block:: sql + + SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') + .. list-table:: Metrics :widths: auto :header-rows: 1 @@ -171,10 +181,11 @@ Metadata Statistics Provides information on Worker and metadata reactivity. Regular monitoring allows for the identification of the system's performance during peak loads, indicating periods of heavy system load. This insight can be invaluable for uncovering potential concurrent issues. -Metrics -^^^^^^^^ +.. code-block:: sql + + SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: +.. list-table:: Metrics :widths: auto :header-rows: 1 @@ -215,23 +226,16 @@ Metrics - ``"from":0, "to":1000`` - -Execution Example -^^^^^^^^^^^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') - - License -------- Provides details about the customer's license, including database storage capacity and licensing restrictions. Proactively alerts the customer before reaching license limitations, ensuring awareness and timely action. -Metrics -^^^^^^^^ +.. code-block:: sql -.. list-table:: + SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') + +.. list-table:: Metrics :widths: auto :header-rows: 1 @@ -256,23 +260,17 @@ Metrics - ``"from":60`` - -Execution Example -^^^^^^^^^^^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') - - self_healing -------------- Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. -Metrics -^^^^^^^^ +.. code-block:: sql + + SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: + +.. list-table:: Metrics :widths: auto :header-rows: 1 @@ -293,25 +291,4 @@ Metrics - ``"from":0, "to":2`` - -Execution Example -^^^^^^^^^^^^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -Examples -========= - -Storage -^^^^^^^^ - -.. code-block:: sql - - SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') - -You may also filter storage information retrieval by database, schema, table, or all three. - -.. code-block:: sql - SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') \ No newline at end of file From 99f1b28fb2dc8dfb5b114a932f8f261569a2428b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 27 Nov 2023 16:18:13 +0200 Subject: [PATCH 1029/1892] Update recommended_pre-installation_configurations.rst --- ...ecommended_pre-installation_configurations.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index ac82224ce..fc8d87e65 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -833,20 +833,21 @@ Installing the CUDA driver from the Repository is the recommended installation m Installing the CUDA depedendencies from the **epel** repository is only required for installing **runfile**. 3. Download and install the required local repository: - - * **Intel - CUDA 10.1 for RHEL7**: + + * **Intel - 11.4.3 repository for RHEL7**: .. code-block:: console - $ wget http://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.x86_64.rpm + $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **Intel - 11.4.3 repository**: + * **Intel - CUDA 12.2 for RHEL8**: .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ wget https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.x86_64.rpm + + $ sudo rpm -i cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.x86_64.rpm * **IBM Power9 - CUDA 10.1 for RHEL7**: From 8ac22a74dbd6093b24286dc09d8f3341acc2b96c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 11:33:32 +0200 Subject: [PATCH 1030/1892] SQLoader 7.8.1 --- data_ingestion/ingesting_from_databases.rst | 2 +- .../select_health_check_monitoring.rst | 34 ++++++++++--------- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 63a56a19f..dbb7770ac 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql and Oracle tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4`` ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 29e6d5af8..c599d144c 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,7 +116,7 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, both a system health-check log file and a result set are generated. The log file is saved in the specified directory, and the result set is displayed in the result pane, both showcasing the following output: +After executing the ``SELECT health_check_monitoring`` command, both a system health-check log file and a result set are generated. The log file is saved in the specified directory, and the result set is displayed in your CLI, both showcasing the following output: .. list-table:: Log Output :widths: auto @@ -127,7 +127,7 @@ After executing the ``SELECT health_check_monitoring`` command, both a system he * - ``metric_time`` - The time when the specific metric was checked * - ``metric_category`` - - The system domain for which health information is retrieved + - The system domain for which health information is retrieved; either ``storage``, ``metadata_stats``, ``license``, or ``self_healing`` * - ``metric_name`` - * - ``metric_description`` @@ -137,9 +137,11 @@ After executing the ``SELECT health_check_monitoring`` command, both a system he * - ``metric_validation_status`` - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warn``, metric deviates from its defined valid range * - ``response_time_sec`` - - + - Indicates the time taken to gather information for a specific metric. This is helpful for timing a health-check executions + +When reading your health-check log through the CLI, besides presenting the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. -Besides presenting the metric outputs, the result pane also showcases your initial metric range configuration and provides the location of your exported log file. +For each of the four Health-Check Monitor *categories*, a separated log file and result set are generated. Health-Check Category Specifications ======================================== @@ -159,7 +161,7 @@ When monitoring your storage health, you may also filter information retrieval b SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: Metrics +.. list-table:: Storage Metrics :widths: auto :header-rows: 1 @@ -170,7 +172,7 @@ When monitoring your storage health, you may also filter information retrieval b * - ``No. storage chunks`` - NA - NA - - + - Chunk status; either ``clean``, `` mixed``, or ``deleted``. Helps in understanding why reading from a tale might be slow. ``clean`` means that read table is clean of temporarily held deleted data. ``mixed`` means that the read table holds data that was deleted but not yet cleaned up (the process of physically removing deleted data), and ``deleted`` means that the table read was cleaned-up. This is helpful for analyzing your deletion and cleaned-up habits and is extremely clear when using visualization tools. * - ``No. fragmented chunks`` - ``totalNumberOfFragmentedChunks`` - ``"from":0, "to":100`` @@ -185,7 +187,7 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: Metrics +.. list-table:: Metadata Statistics Metrics :widths: auto :header-rows: 1 @@ -196,31 +198,31 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgVariance`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``CheckLocksMsg`` - ``checkLocksMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``CheckLocksMsg`` - ``checkLocksMsgVariance`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysAndValuesNMsg`` - ``keysAndValuesNMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysAndValuesNMsg`` - ``keysAndValuesNVariance`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - + - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgVariance`` - ``"from":0, "to":1000`` @@ -235,7 +237,7 @@ Provides details about the customer's license, including database storage capaci SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: Metrics +.. list-table:: License Metrics :widths: auto :header-rows: 1 @@ -270,7 +272,7 @@ Supplies details on customer ETLs and loads, monitors the execution flow of quer SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') -.. list-table:: Metrics +.. list-table:: self_healing Metrics :widths: auto :header-rows: 1 From 32e1316dc7c82468ada3ea763c37f91c1a3ad912 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 12:20:52 +0200 Subject: [PATCH 1031/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index dbb7770ac..6ac33570b 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ============================ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. .. code-block:: sql CREATE TABLE "SMSDW"."SQLOAD_SUMMARY" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "UPDATED_DTTM_FROM" DATE VISIBLE, "UPDATED_DTTM_TO" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE, "LAST_VAL_TS" DATE VISIBLE, "START_TIME" TIMESTAMP(6) VISIBLE, "FINISH_TIME" TIMESTAMP(6) VISIBLE, "ELAPSED_SEC" NUMBER VISIBLE, "ROW_COUNT" NUMBER VISIBLE, "SQL_FILTER" VARCHAR2(200 BYTE) VISIBLE, "PARTITION" VARCHAR2(200 BYTE) VISIBLE, "STMT_TYPE" VARCHAR2(200 BYTE) VISIBLE, "STATUS" VARCHAR2(200 BYTE) VISIBLE, "LOG_FILE" VARCHAR2(200 BYTE) VISIBLE, "DB_URL" VARCHAR2(200 BYTE) VISIBLE, "PARTITION_COUNT" NUMBER VISIBLE DEFAULT 0, "THREAD_COUNT" NUMBER VISIBLE DEFAULT 1, "ELAPSED_MS" NUMBER VISIBLE DEFAULT 0, "STATUS_CODE" NUMBER VISIBLE DEFAULT 0 ); CDC TABLES (ORACLE ONLY): CREATE TABLE "SMSDW"."CDC_TABLES" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_CDC" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_TYPE" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_INTERVAL" NUMBER(22,0) VISIBLE, "IS_ACTIVE" NUMBER VISIBLE DEFAULT 0, "STATUS_LOAD" NUMBER VISIBLE DEFAULT 0, "INC_GAP_VALUE" NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE "SMSDW"."CDC_TRACKING" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LAST_UPDATED_DTTM" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE DEFAULT 0, "LAST_VAL_TS" TIMESTAMP(6) VISIBLE, "LAST_VAL_DT" DATE VISIBLE ); CREATE TABLE "SMSDW"."CDC_TABLE_PRIMARY_KEYS" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "CONSTRAINT_NAME" VARCHAR2(200 BYTE) VISIBLE, "COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "IS_NULLABLE" NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 5fde47d97f23f1642c9453d7b2842477c0931650 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:12:43 +0200 Subject: [PATCH 1032/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 6ac33570b..5bd4ae176 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. .. code-block:: sql CREATE TABLE "SMSDW"."SQLOAD_SUMMARY" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "UPDATED_DTTM_FROM" DATE VISIBLE, "UPDATED_DTTM_TO" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE, "LAST_VAL_TS" DATE VISIBLE, "START_TIME" TIMESTAMP(6) VISIBLE, "FINISH_TIME" TIMESTAMP(6) VISIBLE, "ELAPSED_SEC" NUMBER VISIBLE, "ROW_COUNT" NUMBER VISIBLE, "SQL_FILTER" VARCHAR2(200 BYTE) VISIBLE, "PARTITION" VARCHAR2(200 BYTE) VISIBLE, "STMT_TYPE" VARCHAR2(200 BYTE) VISIBLE, "STATUS" VARCHAR2(200 BYTE) VISIBLE, "LOG_FILE" VARCHAR2(200 BYTE) VISIBLE, "DB_URL" VARCHAR2(200 BYTE) VISIBLE, "PARTITION_COUNT" NUMBER VISIBLE DEFAULT 0, "THREAD_COUNT" NUMBER VISIBLE DEFAULT 1, "ELAPSED_MS" NUMBER VISIBLE DEFAULT 0, "STATUS_CODE" NUMBER VISIBLE DEFAULT 0 ); CDC TABLES (ORACLE ONLY): CREATE TABLE "SMSDW"."CDC_TABLES" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_CDC" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_TYPE" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_INTERVAL" NUMBER(22,0) VISIBLE, "IS_ACTIVE" NUMBER VISIBLE DEFAULT 0, "STATUS_LOAD" NUMBER VISIBLE DEFAULT 0, "INC_GAP_VALUE" NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE "SMSDW"."CDC_TRACKING" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LAST_UPDATED_DTTM" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE DEFAULT 0, "LAST_VAL_TS" TIMESTAMP(6) VISIBLE, "LAST_VAL_DT" DATE VISIBLE ); CREATE TABLE "SMSDW"."CDC_TABLE_PRIMARY_KEYS" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "CONSTRAINT_NAME" VARCHAR2(200 BYTE) VISIBLE, "COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "IS_NULLABLE" NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE "SMSDW"."SQLOAD_SUMMARY" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "UPDATED_DTTM_FROM" DATE VISIBLE, "UPDATED_DTTM_TO" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE, "LAST_VAL_TS" DATE VISIBLE, "START_TIME" TIMESTAMP(6) VISIBLE, "FINISH_TIME" TIMESTAMP(6) VISIBLE, "ELAPSED_SEC" NUMBER VISIBLE, "ROW_COUNT" NUMBER VISIBLE, "SQL_FILTER" VARCHAR2(200 BYTE) VISIBLE, "PARTITION" VARCHAR2(200 BYTE) VISIBLE, "STMT_TYPE" VARCHAR2(200 BYTE) VISIBLE, "STATUS" VARCHAR2(200 BYTE) VISIBLE, "LOG_FILE" VARCHAR2(200 BYTE) VISIBLE, "DB_URL" VARCHAR2(200 BYTE) VISIBLE, "PARTITION_COUNT" NUMBER VISIBLE DEFAULT 0, "THREAD_COUNT" NUMBER VISIBLE DEFAULT 1, "ELAPSED_MS" NUMBER VISIBLE DEFAULT 0, "STATUS_CODE" NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE "SMSDW"."CDC_TABLES" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_CDC" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_TYPE" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_INTERVAL" NUMBER(22,0) VISIBLE, "IS_ACTIVE" NUMBER VISIBLE DEFAULT 0, "STATUS_LOAD" NUMBER VISIBLE DEFAULT 0, "INC_GAP_VALUE" NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE "SMSDW"."CDC_TRACKING" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LAST_UPDATED_DTTM" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE DEFAULT 0, "LAST_VAL_TS" TIMESTAMP(6) VISIBLE, "LAST_VAL_DT" DATE VISIBLE ); CREATE TABLE "SMSDW"."CDC_TABLE_PRIMARY_KEYS" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "CONSTRAINT_NAME" VARCHAR2(200 BYTE) VISIBLE, "COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "IS_NULLABLE" NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 2f52f81f4dead80c63f0d49081a9f7252d43ce32 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:54:35 +0200 Subject: [PATCH 1033/1892] SQLoader 7.8.1 --- data_ingestion/connection_string.java | 19 ++++++++++++++----- data_ingestion/ingesting_from_databases.rst | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java index 3f4c414d4..680ca117c 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.java @@ -1,6 +1,6 @@ ####mandatory! -##Postgresql, Oracle, and SQreamDB Connection Strings +##Postgresql, Oracle, Teradata, SAP HANA, Microsoft SQL Server, and SQreamDB Connection Strings #postgres source.jdbc.connectionstring=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> @@ -8,14 +8,23 @@ #oracle source.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> +#teradata +source.jdbc.connectionstring=jdbc:teradata://<HostIp>/DATABASE=<database_name>,DBS_PORT=<port>,user=<user_name>,password=<password> + +#sap hana +source.jdbc.connectionstring=jdbc:sap://<HostIp>:<port>/?user=<user_name>&password=<password> + +#microsoft sql server +source.jdbc.connectionstring=jdbc:sqlserver://<HostIp>:<port>;databaseName=<database_name>;user=<user_name>;password=<password>;encrypt=<true/false>;trustServerCertificate=<true/false> + #sqream sqream.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> ##CDC and Incremental Parameter -cdc_catalog_table=SMSDW.CDC_TABLES -cdc_tracking_table=SMSDW.CDC_TRACKING -cdc_primary_keys_table=SMSDW.CDC_TABLE_PRIMARY_KEYS +cdc_catalog_table=public.CDC_TABLES +cdc_tracking_table=public.CDC_TRACKING +cdc_primary_keys_table=public.CDC_TABLE_PRIMARY_KEYS @@ -28,4 +37,4 @@ #catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> #Summary Parameter -#load_summary_table=SMSDW.SQLOAD_SUMMARY \ No newline at end of file +#load_summary_table=public.SQLOAD_SUMMARY \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 5bd4ae176..8225abf17 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE "SMSDW"."SQLOAD_SUMMARY" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "UPDATED_DTTM_FROM" DATE VISIBLE, "UPDATED_DTTM_TO" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE, "LAST_VAL_TS" DATE VISIBLE, "START_TIME" TIMESTAMP(6) VISIBLE, "FINISH_TIME" TIMESTAMP(6) VISIBLE, "ELAPSED_SEC" NUMBER VISIBLE, "ROW_COUNT" NUMBER VISIBLE, "SQL_FILTER" VARCHAR2(200 BYTE) VISIBLE, "PARTITION" VARCHAR2(200 BYTE) VISIBLE, "STMT_TYPE" VARCHAR2(200 BYTE) VISIBLE, "STATUS" VARCHAR2(200 BYTE) VISIBLE, "LOG_FILE" VARCHAR2(200 BYTE) VISIBLE, "DB_URL" VARCHAR2(200 BYTE) VISIBLE, "PARTITION_COUNT" NUMBER VISIBLE DEFAULT 0, "THREAD_COUNT" NUMBER VISIBLE DEFAULT 1, "ELAPSED_MS" NUMBER VISIBLE DEFAULT 0, "STATUS_CODE" NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE "SMSDW"."CDC_TABLES" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_CDC" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "INC_COLUMN_TYPE" VARCHAR2(200 BYTE) VISIBLE, "LOAD_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_TYPE" VARCHAR2(200 BYTE) VISIBLE, "FREQ_INTERVAL" NUMBER(22,0) VISIBLE, "IS_ACTIVE" NUMBER VISIBLE DEFAULT 0, "STATUS_LOAD" NUMBER VISIBLE DEFAULT 0, "INC_GAP_VALUE" NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE "SMSDW"."CDC_TRACKING" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "LAST_UPDATED_DTTM" DATE VISIBLE, "LAST_VAL_INT" NUMBER(22,0) VISIBLE DEFAULT 0, "LAST_VAL_TS" TIMESTAMP(6) VISIBLE, "LAST_VAL_DT" DATE VISIBLE ); CREATE TABLE "SMSDW"."CDC_TABLE_PRIMARY_KEYS" ( "DB_NAME" VARCHAR2(200 BYTE) VISIBLE, "SCHEMA_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME" VARCHAR2(200 BYTE) VISIBLE, "TABLE_NAME_FULL" VARCHAR2(200 BYTE) VISIBLE, "CONSTRAINT_NAME" VARCHAR2(200 BYTE) VISIBLE, "COLUMN_NAME" VARCHAR2(200 BYTE) VISIBLE, "IS_NULLABLE" NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From c742be9d968b2084074297904c3a490baf0390d8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 15:42:49 +0200 Subject: [PATCH 1034/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index c599d144c..08b66a730 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,7 +116,9 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, both a system health-check log file and a result set are generated. The log file is saved in the specified directory, and the result set is displayed in your CLI, both showcasing the following output: +After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a result set are generated. When reading your health-check log through the CLI, in addition to the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. + +The log file and the result set both showcase the following output: .. list-table:: Log Output :widths: auto @@ -137,11 +139,7 @@ After executing the ``SELECT health_check_monitoring`` command, both a system he * - ``metric_validation_status`` - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warn``, metric deviates from its defined valid range * - ``response_time_sec`` - - Indicates the time taken to gather information for a specific metric. This is helpful for timing a health-check executions - -When reading your health-check log through the CLI, besides presenting the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. - -For each of the four Health-Check Monitor *categories*, a separated log file and result set are generated. + - Indicates the time taken to gather information for a specific metric. This is helpful for timing a health-check executions Health-Check Category Specifications ======================================== @@ -176,7 +174,7 @@ When monitoring your storage health, you may also filter information retrieval b * - ``No. fragmented chunks`` - ``totalNumberOfFragmentedChunks`` - ``"from":0, "to":100`` - - + - Defines Metadata Statistics -------------------- From be8f1fe14a877f81de46fd3c7697b738d3892f78 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 Nov 2023 16:19:28 +0200 Subject: [PATCH 1035/1892] Update select_health_check_monitoring.rst --- .../utility_commands/select_health_check_monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 08b66a730..45d3eba4e 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,7 +116,7 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a result set are generated. When reading your health-check log through the CLI, in addition to the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. +After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. The log file and the result set both showcase the following output: From 969adb14a34acfee5f0d79d6b7f1aebbd6adc4c9 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 3 Dec 2023 11:58:12 +0200 Subject: [PATCH 1036/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 45d3eba4e..a506bb9cd 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,11 +116,11 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric outputs, it also showcases your initial metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. +After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric values, it also showcases your initially set metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. -The log file and the result set both showcase the following output: +The log file and the result set both output the following metrics: -.. list-table:: Log Output +.. list-table:: Log Metrics :widths: auto :header-rows: 1 @@ -170,11 +170,11 @@ When monitoring your storage health, you may also filter information retrieval b * - ``No. storage chunks`` - NA - NA - - Chunk status; either ``clean``, `` mixed``, or ``deleted``. Helps in understanding why reading from a tale might be slow. ``clean`` means that read table is clean of temporarily held deleted data. ``mixed`` means that the read table holds data that was deleted but not yet cleaned up (the process of physically removing deleted data), and ``deleted`` means that the table read was cleaned-up. This is helpful for analyzing your deletion and cleaned-up habits and is extremely clear when using visualization tools. + - Chunk status; categorized as either ``clean``, ``mixed``, or ``deleted``. This classification aids in comprehending potential slowdowns when reading from a table. ``Clean`` indicates that your table is free of physically lingering deleted data. ``Mixed`` suggests that your table contains data marked for deletion but not yet purged (awaiting the removal of deleted data). Meanwhile, ``deleted`` signifies that the table has undergone the cleanup process. This categorization proves valuable for scrutinizing deletion and clean-up practices, particularly when visualizing data through dedicated tools * - ``No. fragmented chunks`` - ``totalNumberOfFragmentedChunks`` - ``"from":0, "to":100`` - - Defines + - Defines the number of fragmented chunks Metadata Statistics -------------------- From bbf8dcf076e32da228b0275d1a9ccd369e1d095a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 3 Dec 2023 13:22:44 +0200 Subject: [PATCH 1037/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index a506bb9cd..cba037c11 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -116,7 +116,7 @@ General Syntax Health-Check Logs =================== -After executing the ``SELECT health_check_monitoring`` command, both a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric values, it also showcases your initially set metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. +After executing the ``SELECT health_check_monitoring`` command, a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric values, it also showcases your initially set metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. The log file and the result set both output the following metrics: @@ -139,7 +139,7 @@ The log file and the result set both output the following metrics: * - ``metric_validation_status`` - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warn``, metric deviates from its defined valid range * - ``response_time_sec`` - - Indicates the time taken to gather information for a specific metric. This is helpful for timing a health-check executions + - Indicates the time taken to gather information for a specific metric. This is helpful for timing health-check executions Health-Check Category Specifications ======================================== @@ -196,35 +196,35 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``max response time`` indicates the peak time for the monitored *category* * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgVariance`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``CheckLocksMsg`` - ``checkLocksMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``max response time`` indicates the peak time for the monitored *category* * - ``CheckLocksMsg`` - ``checkLocksMsgVariance`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysAndValuesNMsg`` - ``keysAndValuesNMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``max response time`` indicates the peak time for the monitored *category* * - ``KeysAndValuesNMsg`` - ``keysAndValuesNVariance`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``variance`` represents the standard deviation between the peak time and the monitoring time * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - Either ``max response time`` or ``variance``. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time + - ``max response time`` indicates the peak time for the monitored *category* * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgVariance`` - ``"from":0, "to":1000`` - - + - ``variance`` represents the standard deviation between the peak time and the monitoring time License -------- From dc3205d4f216ed5e99b20d4851917bfb0f79c917 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 3 Dec 2023 14:18:38 +0200 Subject: [PATCH 1038/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index cba037c11..1c631f6e5 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -185,6 +185,8 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') +``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. + .. list-table:: Metadata Statistics Metrics :widths: auto :header-rows: 1 @@ -196,35 +198,35 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - ``max response time`` indicates the peak time for the monitored *category* + - * - ``NodeHeartbeatMsg`` - ``nodeHeartbeatMsgVariance`` - ``"from":0, "to":1000`` - - ``variance`` represents the standard deviation between the peak time and the monitoring time + - * - ``CheckLocksMsg`` - ``checkLocksMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - ``max response time`` indicates the peak time for the monitored *category* + - * - ``CheckLocksMsg`` - ``checkLocksMsgVariance`` - ``"from":0, "to":1000`` - - ``variance`` represents the standard deviation between the peak time and the monitoring time + - * - ``KeysAndValuesNMsg`` - ``keysAndValuesNMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - ``max response time`` indicates the peak time for the monitored *category* + - * - ``KeysAndValuesNMsg`` - ``keysAndValuesNVariance`` - ``"from":0, "to":1000`` - - ``variance`` represents the standard deviation between the peak time and the monitoring time + - * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgMaxResponseTimeMS`` - ``"from":0, "to":1000`` - - ``max response time`` indicates the peak time for the monitored *category* + - * - ``KeysWithPrefixMsg`` - ``keysWithPrefixMsgVariance`` - ``"from":0, "to":1000`` - - ``variance`` represents the standard deviation between the peak time and the monitoring time + - License -------- @@ -246,19 +248,19 @@ Provides details about the customer's license, including database storage capaci * - ``Total storage capacity`` - NA - NA - - + - Indicates your licensed storage capacity, outlining the permissible limit for your usage * - ``Used storage capacity`` - NA - NA - - + - Indicates current storage utilization * - ``% of used storage capacity`` - ``percentageStorageCapacity`` - ``"from":0, "to":0.9`` - - + - Indicates current storage utilization percentage * - ``License expiration date`` - ``daysForLicenseExpire`` - ``"from":60`` - - + - Indicates how many days until your license expires self_healing -------------- @@ -281,14 +283,14 @@ Supplies details on customer ETLs and loads, monitors the execution flow of quer * - ``Queries in queue`` - ``queriesInQueue`` - ``"from":0, "to":100`` - - + - Indicates the number of currently queued queries * - ``Available workers per service`` - ``availableWorkers`` - ``"from":0, "to":5`` - - + - Indicates the number of unused Workers per service * - ``Stuck snapshots`` - ``stuckSnapshots`` - ``"from":0, "to":2`` - - + - Indicates the number of currently stuck snapshots From 8681fb3d0d0f5f3aeafeeb7513ba2c2441ed1712 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 3 Dec 2023 14:39:18 +0200 Subject: [PATCH 1039/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 3a855c9f6..4058d18a6 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -23,7 +23,7 @@ Client Driver Downloads - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All - * - **.NET** + * - **SQreamNet** - `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ - :ref:`net` - From 47ff672d3c8105af436b3e006079a2cf03e1204f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 09:16:29 +0200 Subject: [PATCH 1040/1892] Update 4.5.rst --- releases/4.5.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 61230958a..138842878 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -4,7 +4,7 @@ Release Notes 4.5 ***************** -The 4.5 release notes were released on XXXXXXXXXXX +The 4.5 release notes were released on December XXth, 2023 .. contents:: :local: @@ -26,7 +26,7 @@ Compatibility Matrix | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | | | * NodeJS | -| | * .NET 3.0.2 | +| | * .NET 5.0.0 | | | * Pysqream 5.0.0 | | | * Spark | +---------------------------------+------------------------------------------------------------------------+ @@ -40,7 +40,7 @@ New Features and Enhancements ► :ref:`Query Timeout Per Service<>` -► ``JOIN`` Performance Enhancements +► Optimized ``JOIN`` operation for improved performance with large tables Known Issues ------------ @@ -56,13 +56,13 @@ Version 4.5 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+================================================================================================+ -| SQ-11523 | Saved query ``datetime`` internal runtime issue | +| SQ-11523 | Resolved internal runtime issue affecting the ``datetime`` saved query | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-14292 | | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14869 | | +| SQ-14869 | Optimized compilation time for improved performance with large metadata | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15074 | Non-``SUPERUSER`` UI access issue | +| SQ-15074 | Addressed UI access issue for non-``SUPERUSER`` roles | +--------------------+------------------------------------------------------------------------------------------------+ Deprecations From e503a4ed3c5079b270d0703506d4830425db3a04 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 09:19:38 +0200 Subject: [PATCH 1041/1892] Update 4.5.rst --- releases/4.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 138842878..62859e6cc 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -40,7 +40,7 @@ New Features and Enhancements ► :ref:`Query Timeout Per Service<>` -► Optimized ``JOIN`` operation for improved performance with large tables +► Optimized ``JOIN`` operation for improved performance with large tables Known Issues ------------ From e8e1b9d56ed9ab8ca7cbd0d36efe63e5e0d1a9a7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 10:15:34 +0200 Subject: [PATCH 1042/1892] Update 4.5.rst --- releases/4.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 62859e6cc..c5e4e6f96 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -36,7 +36,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► :ref:`Health-Check Monitor<select_health_check_monitoring>` +► A new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command that allows administrators to monitor the database health ► :ref:`Query Timeout Per Service<>` From 0b4cb903a6c307fe0864a5607a1c0ed52ce45df0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:13:50 +0200 Subject: [PATCH 1043/1892] Update index.rst --- .../client_drivers/dotnet/index.rst | 83 +++++++------------ 1 file changed, 28 insertions(+), 55 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dotnet/index.rst b/connecting_to_sqream/client_drivers/dotnet/index.rst index d21dfd0a1..54b5b050a 100644 --- a/connecting_to_sqream/client_drivers/dotnet/index.rst +++ b/connecting_to_sqream/client_drivers/dotnet/index.rst @@ -1,74 +1,43 @@ .. _net: -**** -.NET -**** +********** +SQreamNET +********** -The SqreamNet ADO.NET Data Provider lets you connect to SQream through your .NET environment. - -The .NET page includes the following sections: - -.. contents:: - :local: - :depth: 1 - -Integrating SQreamNet -===================== - -The **Integrating SQreamNet** section describes the following: +The SQreamNET ADO.NET Data Provider lets you connect to SQream through your .NET environment. .. contents:: :local: :depth: 1 -Prerequisites -------------- - -The SqreamNet provider requires a .NET version 6 or newer. - -Getting the DLL file --------------------- - -The .NET driver is available for download from the :ref:`client drivers download page<client_drivers>`. - -Integrating SQreamNet ---------------------- - -After downloading the .NET driver, save the archive file to a known location. Next, in your IDE, add a Sqreamnet.dll reference to your project. +Before You Begin +================= -If you wish to upgrade SQreamNet within an existing project, you may replace the existing .dll file with an updated one or change the project's reference location to a new one. +* The SQreamNET provider requires a .NET version 6 or newer +* Download the SQreamNET driver from the :ref:`client drivers page<client_drivers>` -Known Driver Limitations ------------------------- +Integrating SQreamNET +====================== - * Unicode characters are not supported when using ``INSERT INTO AS SELECT``. - - * To avoid possible casting issues, use ``getDouble`` when using ``FLOAT``. +#. After downloading the .NET driver, save the archived file to a known location. +#. In your IDE, add a SQreamNET.dll reference to your project. +#. If you wish to upgrade SQreamNET within an existing project, replace your existing .dll file with an updated one or change the project's reference location to a new one. Connecting to SQream For the First Time -======================================= +======================================== An initial connection to SQream must be established by creating a **SqreamConnection** object using a connection string. -.. contents:: - :local: - :depth: 1 - +Connection String Syntax +------------------------- -Connection String ------------------ +.. code-block:: console -To connect to SQream, instantiate a **SqreamConnection** object using this connection string. - -The following is the syntax for SQream: - -.. code-block:: text - - "Data Source=<hostname or ip>,<port>;User=<username>;Password=<password>;Initial Catalog=<database name>;Integrated Security=true"; + Data Source=<hostname or ip>,<port>;User=<username>;Password=<password>;Initial Catalog=<database name>;Integrated Security=true; Connection Parameters -^^^^^^^^^^^^^^^^^^^^^ +----------------------- .. list-table:: :widths: auto @@ -108,25 +77,25 @@ Connection Parameters - Connect via load balancer (use only if exists, and check port). Connection String Examples -^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------- The following is an example of a SQream cluster with load balancer and no service queues (with SSL): -.. code-block:: text +.. code-block:: console Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master;Integrated Security=true;ssl=true;cluster=true; The following is a minimal example for a local standalone SQream database: -.. code-block:: text +.. code-block:: console Data Source=127.0.0.1,5000;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=master; The following is an example of a SQream cluster with load balancer and a specific service queue named ``etl``, to the database named ``raviga`` -.. code-block:: text +.. code-block:: console Data Source=sqream.mynetwork.co,3108;User=rhendricks;Password=Tr0ub4dor&3;Initial Catalog=raviga;Integrated Security=true;service=etl;cluster=true; @@ -143,4 +112,8 @@ You can download the :download:`.NET Application Sample File <sample.cs>` below Limitations =============== -Please note that .NET does not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using .NET to connect to the database. \ No newline at end of file +* Unicode characters are not supported when using ``INSERT INTO AS SELECT`` + +* To avoid possible casting issues, use ``getDouble`` when using ``FLOAT`` + +* The ``ARRAY`` data types is not supported. If your database schema includes ``ARRAY`` columns, you may encounter compatibility issues when using SQreamNET to connect to the database. \ No newline at end of file From 005bd2e485eceef55d70ea7a302d392a0f8db496 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:30:54 +0200 Subject: [PATCH 1044/1892] maxConnections --- configuration_guides/current_method_flag_types.rst | 5 +++++ configuration_guides/max_connections.rst | 12 ++++++++++++ configuration_guides/metadata_server_port.rst | 5 +++-- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 configuration_guides/max_connections.rst diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index b0ddf8fc0..81d139707 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -48,6 +48,11 @@ It is worth noting that the worker configuration file is not subject to frequent - Enables you to manually set the reported IP. - string - ``127.0.0.1`` + * - ``maxConnections`` + - SUPERUSER + - Defines the maximum allowed connections per Worker. + - bigint + - ``1000`` * - ``metadataServerPort`` - SUPERUSER - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024 because ports below 1024 are usually reserved, although there are no strict limitations. You can use any positive number (1 - 65535) while setting this flag. diff --git a/configuration_guides/max_connections.rst b/configuration_guides/max_connections.rst new file mode 100644 index 000000000..7c442ecb5 --- /dev/null +++ b/configuration_guides/max_connections.rst @@ -0,0 +1,12 @@ +.. _max_connections: + +******************************** +MAX CONNECTIONS +******************************** + +The ``maxConnections`` parameter is optional and sets the maximum number of connections allowed per Worker. Once a Worker reaches its maximum capacity, any new connections are directed to other available Workers. + +* **Data type** - size_t +* **Default value** - ``1000`` +* **Allowed values** - ``1-∞`` + diff --git a/configuration_guides/metadata_server_port.rst b/configuration_guides/metadata_server_port.rst index 20f9a2db8..084359c52 100644 --- a/configuration_guides/metadata_server_port.rst +++ b/configuration_guides/metadata_server_port.rst @@ -1,8 +1,9 @@ .. _metadata_server_port: -************************* +************************************************** Setting Port Used for Metadata Server Connection -************************* +************************************************** + The ``metadataServerPort`` flag sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024 because ports below 1024 are usually reserved, although there are no strict limitations. You can use any positive number (1 - 65535) while setting this flag. The following describes the ``metadataServerPort`` flag: From 6c1c982d422cde86c66402f8bdf8d488af3ae890 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:35:19 +0200 Subject: [PATCH 1045/1892] Update 4.5.rst --- releases/4.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index c5e4e6f96..d4dca5050 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -58,7 +58,7 @@ Version 4.5 resolved Issues +====================+================================================================================================+ | SQ-11523 | Resolved internal runtime issue affecting the ``datetime`` saved query | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14292 | | +| SQ-14292 | Resolved ``maxConnections`` Worker allocation issue | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-14869 | Optimized compilation time for improved performance with large metadata | +--------------------+------------------------------------------------------------------------------------------------+ From 193d7307c2f3ad02a9d4cc606a5862ad6359c784 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 14:52:25 +0200 Subject: [PATCH 1046/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 4058d18a6..1c3a43814 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ Client Driver Downloads - Recommended installation via ``mvn`` - All * - **SQreamNet** - - `.NET .dll file <https://get.sqream-share.com/share/sIsu8fxv>`_ + - `.NET .dll file <https://sq-ftp-public.s3.amazonaws.com/SqreamNet6.0_v5.0.0.zip>`_ - :ref:`net` - - All From f024260a4f5357db34aa31cd996e2568b1be7a45 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:49:58 +0200 Subject: [PATCH 1047/1892] QueryTimeoutMinutes --- configuration_guides/cache_disk_dir.rst | 7 +- .../current_method_configuration_levels.rst | 106 ++---------------- 2 files changed, 11 insertions(+), 102 deletions(-) diff --git a/configuration_guides/cache_disk_dir.rst b/configuration_guides/cache_disk_dir.rst index 012955bc3..9e0fd4f76 100644 --- a/configuration_guides/cache_disk_dir.rst +++ b/configuration_guides/cache_disk_dir.rst @@ -1,11 +1,10 @@ .. _cache_disk_dir: -************************* +************************************************** Setting Spool Saved File Directory Location -************************* -The ``cacheDiskDir`` flag sets the ondisk directory location for the spool to save files on. +************************************************** -The following describes the ``cacheDiskDir`` flag: +The ``cacheDiskDir`` flag sets the ondisk directory location for the spool to save files on. * **Data type** - size_t * **Default value** - ``128`` diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index a3f0df6f1..a023a07e8 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -37,7 +37,6 @@ Flag List - Description - Data Type - Default Value - * - ``binSizes`` - SUPERUSER - Session @@ -49,226 +48,162 @@ Flag List ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` ``2684354560,2952790016,3221225472`` - * - ``cacheEvictionMilliseconds`` - Anyone - Session - Sets how long the cache stores contents before being flushed. Allowed values: 1-4000000000. - bigint - ``2000`` - - * - ``cacheDiskDir`` - Anyone - Session - Sets the ondisk directory location for the spool to save files on. Allowed values: Any legal string. - bigint - Any legal string - - * - ``cacheDiskGB`` - Anyone - Session - Sets the amount of memory (GB) to be used by Spool on the disk. Allowed values: 0-4000000000. - bigint - ``128`` - * - ``cachePartitions`` - Anyone - Session - Sets the number of partitions that the cache is split into. Allowed values: 1-4000000000. - bigint - ``4`` - - * - ``cachePersistentDir`` - Anyone - Session - Sets the persistent directory location for the spool to save files on. Allowed values: Any legal string. - string - ``/tmp`` - - * - ``cachePersistentGB`` - Anyone - Session - Sets the amount of data (GB) for the cache to store persistently. Allowed values: 0-4000000000. - bigint - ``128`` - - * - ``cacheRamGB`` - Anyone - Session - Sets the amount of memory (GB) to be used by Spool InMemory. Allowed values: 0-4000000000. - bigint - ``16`` - - - * - ``checkCudaMemory`` - SUPERUSER - Session - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - boolean - ``FALSE`` - * - ``compilerGetsOnlyUFs`` - SUPERUSER - Session - Sets the runtime to pass only utility functions names to the compiler. - boolean - ``FALSE`` - * - ``copyToRestrictUtf8`` - SUPERUSER - Session - Sets the custom bin size in the cache to enable high granularity bin control. - boolean - ``FALSE`` - * - ``cpuReduceHashtableSize`` - SUPERUSER - Session - Sets the hash table size of the CpuReduce. - uint - ``10000`` - * - ``csvLimitRowLength`` - SUPERUSER - Cluster - Sets the maximum supported CSV row length. Allowed values: 1-4000000000 - uint - ``100000`` - * - ``cudaMemcpyMaxSizeBytes`` - SUPERUSER - Session - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - uint - ``0`` - * - ``CudaMemcpySynchronous`` - SUPERUSER - Session - Indicates if copying from/to GPU is synchronous. - boolean - ``FALSE`` - - * - ``developerMode`` - SUPERUSER - Session - Enables modifying R&D flags. - boolean - - ``FALSE`` - + - ``FALSE`` * - ``enableDeviceDebugMessages`` - SUPERUSER - Session - Checks for CUDA errors after producing each chunk. - boolean - ``FALSE`` - * - ``enableLogDebug`` - SUPERUSER - Session - Enables creating and logging in the clientLogger_debug file. - boolean - ``TRUE`` - * - ``enableNvprofMarkers`` - SUPERUSER - Session - Activates the Nvidia profiler (nvprof) markers. - boolean - ``FALSE`` - * - ``endLogMessage`` - SUPERUSER - Session - Appends a string at the end of every log line. - string - ``EOM`` - - - - - - - * - ``extentStorageFileSizeMB`` - SUPERUSER - Cluster - Sets the minimum size in mebibytes of extents for table bulk data. - uint - ``20`` - - * - ``externalTableBlobEstimate`` - ? - Session - ? - ? - ? - - - - - * - ``flipJoinOrder`` - Anyone - Session - Reorders join to force equijoins and/or equijoins sorted by table size. - boolean - ``FALSE`` - - - * - ``gatherMemStat`` - SUPERUSER - Session - Monitors all pinned allocations and all **memcopies** to/from device, and prints a report of pinned allocations that were not memcopied to/from the device using the ``dump_pinned_misses`` utility function. - boolean - - ``FALSE`` - - - - - - + - ``FALSE`` * - ``increaseChunkSizeBeforeReduce`` - SUPERUSER - Session - Increases the chunk size to reduce query speed. - boolean - ``FALSE`` - * - ``increaseMemFactors`` - SUPERUSER - Session - Adds rechunker before expensive chunk producer. - boolean - ``TRUE`` - - - - - - - - * - ``leveldbWriteBufferSize`` - SUPERUSER - Session - Sets the buffer size. - uint - ``524288`` - - - - - * - ``logSysLevel`` - Anyone - Session @@ -283,103 +218,72 @@ Flag List 6 - L_TRACE - uint - ``100000`` - - - - - - - * - ``maxAvgBlobSizeToCompressOnGpu`` - Anyone - Session - Sets the CPU to compress columns with size above (flag’s value) * (row count). - uint - ``120`` - - * - ``maxPinnedPercentageOfTotalRAM`` - SUPERUSER - Session - Sets the maximum percentage CPU RAM that pinned memory can use. - uint - ``70`` - - - * - ``memMergeBlobOffsetsCount`` - SUPERUSER - Session - Sets the size of memory used during a query to trigger aborting the server. - uint - ``0`` - - - * - ``memoryResetTriggerMB`` - SUPERUSER - Session - Sets the size of memory used during a query to trigger aborting the server. - uint - ``0`` - - - * - ``mtRead`` - SUPERUSER - Session - Splits large reads to multiple smaller ones and executes them concurrently. - boolean - ``FALSE`` - * - ``mtReadWorkers`` - SUPERUSER - Session - Sets the number of workers to handle smaller concurrent reads. - uint - ``30`` - * - ``orcImplicitCasts`` - SUPERUSER - Session - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - boolean - ``TRUE`` - - * - ``sessionTag`` - Anyone - Session - Sets the name of the session tag. Allowed values: Any legal string. - string - Any legal string - - - * - ``spoolMemoryGB`` - Anyone - Session - Sets the amount of memory (GB) to be used by the server for spooling. - uint - ``8`` - - * - ``statementLockTimeout`` - SUPERUSER - Session - Sets the timeout (seconds) for acquiring object locks before executing statements. - uint - ``3`` - - - * - ``useLegacyDecimalLiterals`` - SUPERUSER - Session - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - boolean - ``FALSE`` - * - ``blockNewVarcharObjects`` - SUPERUSER - Session @@ -398,3 +302,9 @@ Flag List - Prevents a query from processing more memory than the defined value. - uint - ``100000`` + * - ``QueryTimeoutMinutes`` + - Anyone + - Cluster + - When set to 1—4320 minutes(72 hours), the flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. + - integer + - ``0`` (no query timeout) From 3e46d16767b3ae7202598e35aadc2606511e2510 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:52:32 +0200 Subject: [PATCH 1048/1892] Create query_timeout_minutes.rst --- configuration_guides/query_timeout_minutes.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 configuration_guides/query_timeout_minutes.rst diff --git a/configuration_guides/query_timeout_minutes.rst b/configuration_guides/query_timeout_minutes.rst new file mode 100644 index 000000000..988307111 --- /dev/null +++ b/configuration_guides/query_timeout_minutes.rst @@ -0,0 +1,11 @@ +.. _query_timeout_minutes: + +************************************************** +Query Timeout Minutes +************************************************** + +The ``QueryTimeoutMinutes`` flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. + +* **Data type** - integer +* **Default value** - ``0`` +* **Allowed values** - 1—4320 (1 minute up to 72 hours) \ No newline at end of file From c1bf2328114adbcf3c430a8222ecaa8339a6499e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 15:54:55 +0200 Subject: [PATCH 1049/1892] Update 4.5.rst --- releases/4.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index d4dca5050..6db666495 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -38,7 +38,7 @@ New Features and Enhancements ► A new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command that allows administrators to monitor the database health -► :ref:`Query Timeout Per Service<>` +► A new :ref:`Query Timeout Per Service<>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. ► Optimized ``JOIN`` operation for improved performance with large tables From 0080246d22786dc14e6ae2aded869c3a14865a28 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:10:02 +0200 Subject: [PATCH 1050/1892] Update 4.5.rst --- releases/4.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 6db666495..7192af92c 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -4,7 +4,7 @@ Release Notes 4.5 ***************** -The 4.5 release notes were released on December XXth, 2023 +The 4.5 release notes were released on December 5th, 2023 .. contents:: :local: From 01ba749c7e6b74e6651a3754257dd674ad85bcfd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:32:23 +0200 Subject: [PATCH 1051/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 1c631f6e5..f881217f5 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -6,7 +6,7 @@ HEALTH-CHECK MONITORING The ``SELECT health_check_monitoring`` command empowers system administrators to comprehensively monitor the database's health across multiple *categories*. -In the ``storage`` domain, it provides insights into cluster storage chunks and their fragmentation, helping prevent bottlenecks during table readings by identifying irrelevant files. The ``metadata_stats`` category offers information on Worker and metadata reactivity, enabling the identification of system performance during peak loads and the revelation of potential concurrent issues. Addressing licensing concerns, the command gives details on the customer's ``license``, including storage capacity and restrictions, and proactively alerts administrators before reaching limitations. Lastly, under ``self_healing``, it supplies essential details on ETL and load processes, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots—crucial for regular monitoring and offering clear insights during the Root Cause Analysis (RCA) process for optimal resource allocation. +In the ``storage`` domain, it provides insights into cluster storage chunks and their fragmentation, helping to prevent table reading bottlenecks by alerting in the case of a fragmentation scenario. Additionally, it gives indications per table on when to trigger cleanup executions (to free up storage and improve reading performance). The ``metadata_stats`` category offers information on Worker and metadata reactivity, enabling the identification of system performance during peak loads and the revelation of potential concurrent issues. Addressing licensing concerns, the command gives details on the customer's ``license``, including storage capacity and restrictions, and proactively alerts administrators before reaching limitations. Lastly, under ``self_healing``, it supplies essential details on ETL and load processes, monitors query execution flow, tracks Workers per service, identifies idle Workers, and detects issues like stuck snapshots—crucial for regular monitoring and offering clear insights during the Root Cause Analysis (RCA) process for optimal resource allocation. Here, you can discover details on configuring the monitoring for each of the four categories, along with instructions on how to access and interpret the log files for each category. @@ -151,7 +151,7 @@ Provides insights into cluster storage chunks and their fragmentation process. O .. code-block:: sql - SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'path/to/where/i/save/logs') + SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'directory/where/i/save/logs') When monitoring your storage health, you may also filter information retrieval by database, schema, table, or all three. @@ -183,7 +183,7 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow .. code-block:: sql - SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'path/to/where/i/save/logs') + SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'directory/where/i/save/logs') ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. @@ -235,7 +235,7 @@ Provides details about the customer's license, including database storage capaci .. code-block:: sql - SELECT health_check_monitoring('license', 'path/to/my/input.json', 'path/to/where/i/save/logs') + SELECT health_check_monitoring('license', 'path/to/my/input.json', 'directory/where/i/save/logs') .. list-table:: License Metrics :widths: auto @@ -265,11 +265,13 @@ Provides details about the customer's license, including database storage capaci self_healing -------------- -Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of workers per service. +Supplies details on customer ETLs and loads, monitors the execution flow of queries over time, tracks the number of Workers per service, identifies idle Workers, and detects potential issues such as stuck snapshots. It is imperative to regularly monitor this data. During the Root Cause Analysis (RCA) process, it provides a clear understanding of executed operations at specific times, offering customers guidance on optimal resource allocation, particularly in terms of Workers per service. + +Monitoring ``self_healing`` frequently is a best practice to maximize its value. .. code-block:: sql - SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'path/to/where/i/save/logs') + SELECT health_check_monitoring('self_healing', 'path/to/my/input.json', 'directory/where/i/save/logs') .. list-table:: self_healing Metrics From 2816a510e75c4791b96e420cd3922d785fbda424 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 4 Dec 2023 16:47:46 +0200 Subject: [PATCH 1052/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 35 ++++++------------- 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index f881217f5..eb22d1e88 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -185,7 +185,7 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'directory/where/i/save/logs') -``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. + .. list-table:: Metadata Statistics Metrics :widths: auto @@ -196,37 +196,22 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow - Default Value - Description * - ``NodeHeartbeatMsg`` - - ``nodeHeartbeatMsgMaxResponseTimeMS`` + - ``nodeHeartbeatMsgMaxResponseTimeMS``, ``nodeHeartbeatMsgVariance`` - ``"from":0, "to":1000`` - - - * - ``NodeHeartbeatMsg`` - - ``nodeHeartbeatMsgVariance`` - - ``"from":0, "to":1000`` - - + - Ensures worker vitality through metadata pings. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. * - ``CheckLocksMsg`` - - ``checkLocksMsgMaxResponseTimeMS`` - - ``"from":0, "to":1000`` - - - * - ``CheckLocksMsg`` - - ``checkLocksMsgVariance`` - - ``"from":0, "to":1000`` - - - * - ``KeysAndValuesNMsg`` - - ``keysAndValuesNMaxResponseTimeMS`` + - ``checkLocksMsgMaxResponseTimeMS``, ``checkLocksMsgVariance`` - ``"from":0, "to":1000`` - - + - Provides details on current locks at the metadata to determine the feasibility of executing the statement. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. * - ``KeysAndValuesNMsg`` - - ``keysAndValuesNVariance`` + - ``keysAndValuesNMaxResponseTimeMS``, ``keysAndValuesNVariance`` - ``"from":0, "to":1000`` - - + - Iterates through metadata keys and values. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. * - ``KeysWithPrefixMsg`` - - ``keysWithPrefixMsgMaxResponseTimeMS`` + - ``keysWithPrefixMsgMaxResponseTimeMS``, ``keysWithPrefixMsgVariance`` - ``"from":0, "to":1000`` - - - * - ``KeysWithPrefixMsg`` - - ``keysWithPrefixMsgVariance`` - - ``"from":0, "to":1000`` - - + - Iterates through metadata keys and values with a specific prefix. ``max response time`` indicates the peak time for the monitored *category*, while ``variance`` represents the standard deviation between the peak time and the monitoring time. + License -------- From 7eef1918834c7e8afeb6084945f5493892ac333d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 08:35:55 +0200 Subject: [PATCH 1053/1892] Update select_health_check_monitoring.rst --- .../utility_commands/select_health_check_monitoring.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index eb22d1e88..7b57b390d 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -149,6 +149,8 @@ Storage Provides insights into cluster storage chunks and their fragmentation process. Offers an indication of irrelevant storage files in the cluster, preventing potential bottlenecks in chunk iteration during table readings in advance. +``storage`` monitoring has a lengthy execution time, necessitating low-frequency checks to prevent undue strain on your environment. + .. code-block:: sql SELECT health_check_monitoring('storage', 'path/to/my/input.json', 'directory/where/i/save/logs') @@ -157,6 +159,10 @@ When monitoring your storage health, you may also filter information retrieval b .. code-block:: sql + SELECT health_check_monitoring('storage', 'master', 'path/to/my/input.json', 'path/to/where/i/save/logs') + + SELECT health_check_monitoring('storage', 'master', 'schema1', 'path/to/my/input.json', 'path/to/where/i/save/logs') + SELECT health_check_monitoring('storage', 'master', 'schema1', 'table1', 'path/to/my/input.json', 'path/to/where/i/save/logs') .. list-table:: Storage Metrics @@ -185,8 +191,6 @@ Provides information on Worker and metadata reactivity. Regular monitoring allow SELECT health_check_monitoring('metadata_stats', 'path/to/my/input.json', 'directory/where/i/save/logs') - - .. list-table:: Metadata Statistics Metrics :widths: auto :header-rows: 1 From 6b7d784794240796fe98ec7373e0429c45787d4e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 10:01:46 +0200 Subject: [PATCH 1054/1892] Update select_health_check_monitoring.rst --- .../select_health_check_monitoring.rst | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 7b57b390d..bab80e9a4 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -113,34 +113,42 @@ General Syntax - Specifies the directory path where you want the monitoring log file to be extracted. -Health-Check Logs -=================== +Health-Check Log Structure +============================= After executing the ``SELECT health_check_monitoring`` command, a health-check log file and a CLI result set are generated. When reading your health-check log through the CLI, in addition to the metric values, it also showcases your initially set metric range configuration and the location of your exported log file. It's important to note that logs are separately generated for each of the four Health-Check Monitor *categories*. -The log file and the result set both output the following metrics: +The log file and the result set both output the following information: -.. list-table:: Log Metrics +.. list-table:: Log Output :widths: auto :header-rows: 1 - * - Metric + * - Log Column Name - Description * - ``metric_time`` - The time when the specific metric was checked * - ``metric_category`` - The system domain for which health information is retrieved; either ``storage``, ``metadata_stats``, ``license``, or ``self_healing`` * - ``metric_name`` - - + - The specific metric that is being evaluated * - ``metric_description`` - - + - For metrics that need a detailed analysis breakdown, this column will showcase the breakdown alongside any additional information * - ``metric_value`` - The value of the specific metric * - ``metric_validation_status`` - - One of three statuses: ``info``, metric value is within its defined valid range, ``none``, the metric provides information about the system and has no valid range, and ``warn``, metric deviates from its defined valid range + - One of three statuses: + * :green:`info`, metric value is within its defined valid range + * none, the metric provides information about the system and has no valid range + * :red:`warn`, metric deviates from its defined valid range * - ``response_time_sec`` - Indicates the time taken to gather information for a specific metric. This is helpful for timing health-check executions +Handling Warnings +------------------- + + + Health-Check Category Specifications ======================================== From 1cb5e5e72add1215a249834a20d9b966169870ec Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:27:06 +0200 Subject: [PATCH 1055/1892] Health-Check --- .../select_health_check_monitoring.rst | 50 +++++++++++++++++++ troubleshooting/information_for_support.rst | 2 +- 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index bab80e9a4..4e274ab8a 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -1,5 +1,23 @@ .. _select_health_check_monitoring: +.. role:: red + :class: red-text + +.. role:: green + :class: green-text + +.. raw:: html + + <style> + .red-text { + color: red !important; + } + + .green-text { + color: green !important; + } + </style> + ******************************* HEALTH-CHECK MONITORING ******************************* @@ -147,7 +165,39 @@ The log file and the result set both output the following information: Handling Warnings ------------------- +Upon reviewing your log output, you'll observe that the ``metric_validation_status`` column reflects one of three potential statuses: :green:`info`, none, or :red:`warn`. This section offers guidance on effectively managing warnings whenever a :red:`warn` status is encountered. + +.. list-table:: + :widths: auto + :header-rows: 1 + * - Health-Check Category + - Metric Name + - How to Handle :red:`warn` + * - Storage + - ``No. fragmented chunks`` + - Recreating the table for triggering defragmentation + * - Metadata Statistics + - ``NodeHeartbeatMsg``, ``CheckLocksMsg``, ``KeysAndValuesNMsg``, ``KeysWithPrefixMsg`` + - Gather your metadata statistics by executing the following commands and send the information to `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_: + + .. code-block:: sql + + SELECT export_leveldb_stats('<EXPORT_FILE_PATH>'); + SELECT export_statement_queue_stats('<EXPORT_FILE_PATH>'); + SELECT export_conn_stats('<EXPORT_FILE_PATH>'); + * - License + - ``% of used storage capacity``, ``License expiration date`` + - Contact `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for license expansion + * - Self Healing + - ``Queries in queue`` + - To prevent bottlenecks in the service, reallocate service Workers. Distributing or reallocating service Workers strategically can help optimize performance and mitigate potential bottlenecks. Learn more about :ref:`Worker allocation<workload_manager>` + * - Self Healing + - ``Available workers per service`` + - Efficiently utilize resources by reallocating idle workers to a busier service. This approach optimizes resource consumption and helps balance the workload across services. Learn more about :ref:`Worker allocation<workload_manager>` + * - Self Healing + - ``Stuck snapshots`` + - The Healer is designed to autonomously address stuck snapshots based on its configured timeout. The session flag, :ref:`healerDetectionFrequencySeconds<healer_detection_frequency_seconds>`, determines when the Healer detects and takes corrective actions for stuck snapshots. To manually address a situation, execute a :ref:`graceful shutdown<shutdown_server_command>` of the statement's Worker Health-Check Category Specifications ======================================== diff --git a/troubleshooting/information_for_support.rst b/troubleshooting/information_for_support.rst index 8450cc664..3b3aa48b7 100644 --- a/troubleshooting/information_for_support.rst +++ b/troubleshooting/information_for_support.rst @@ -11,7 +11,7 @@ Gathering Information for SQream Support Getting Support and Reporting Bugs ================================== -When contacting `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_, we recommend reporting the following information: +When contacting `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_, we recommend reporting the following information: * What is the problem encountered? * What was the expected outcome? From b2ccf6f164fbc6fa278ef9f1cab536ef79dc113a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 11:34:47 +0200 Subject: [PATCH 1056/1892] 4.5 --- releases/4.5.rst | 4 ++-- releases/index.rst | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 7192af92c..975ea88e2 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -36,9 +36,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► A new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command that allows administrators to monitor the database health +► Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for real-time monitoring, enabling administrators to assess and ensure the optimal health and performance of the database -► A new :ref:`Query Timeout Per Service<>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. +► A new :ref:`Query Timeout Per Service<query_timeout_minutes>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops ► Optimized ``JOIN`` operation for improved performance with large tables diff --git a/releases/index.rst b/releases/index.rst index 57599c192..d3792cefe 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,12 @@ Release Notes ************* +:ref:`Version 4.5 - December 5, 2023<4.5>` + +* Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for real-time monitoring, enabling administrators to assess and ensure the optimal health and performance of the database + +* A new :ref:`Query Timeout Per Service<query_timeout_minutes>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops + :ref:`Version 4.4 - September 28, 2023<4.4>` * `Enhancing storage efficiency and performance with the newly supported ARRAY data type <https://docs.sqream.com/en/latest/releases/4.4.html#new-features-and-enhancements>`_ From 936a05bf8c64d03822405af61ac9f7e0e946ccd0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:16:29 +0200 Subject: [PATCH 1057/1892] 4.5 RN --- .../current_method_configuration_levels.rst | 2 +- configuration_guides/query_timeout_minutes.rst | 2 +- releases/4.5.rst | 6 ++---- releases/index.rst | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index a023a07e8..834dce3ff 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -304,7 +304,7 @@ Flag List - ``100000`` * - ``QueryTimeoutMinutes`` - Anyone - - Cluster + - Session - When set to 1—4320 minutes(72 hours), the flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. - integer - ``0`` (no query timeout) diff --git a/configuration_guides/query_timeout_minutes.rst b/configuration_guides/query_timeout_minutes.rst index 988307111..60e880ef0 100644 --- a/configuration_guides/query_timeout_minutes.rst +++ b/configuration_guides/query_timeout_minutes.rst @@ -7,5 +7,5 @@ Query Timeout Minutes The ``QueryTimeoutMinutes`` flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. * **Data type** - integer -* **Default value** - ``0`` +* **Default value** - ``0`` (no query timeout) * **Allowed values** - 1—4320 (1 minute up to 72 hours) \ No newline at end of file diff --git a/releases/4.5.rst b/releases/4.5.rst index 975ea88e2..6dbd67dc7 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -36,9 +36,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for real-time monitoring, enabling administrators to assess and ensure the optimal health and performance of the database +► Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for monitoring, enabling administrators to assess and ensure the optimal health and performance of the database -► A new :ref:`Query Timeout Per Service<query_timeout_minutes>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops +► A new :ref:`Query Timeout<query_timeout_minutes>` session flag designed to identify queries that have exceeded a specified time limit. Once the flag value is reached, the query automatically stops ► Optimized ``JOIN`` operation for improved performance with large tables @@ -47,8 +47,6 @@ Known Issues * :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. -* Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression - Version 4.5 resolved Issues --------------------------- diff --git a/releases/index.rst b/releases/index.rst index d3792cefe..d5df7e92d 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -6,9 +6,9 @@ Release Notes :ref:`Version 4.5 - December 5, 2023<4.5>` -* Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for real-time monitoring, enabling administrators to assess and ensure the optimal health and performance of the database +* Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for monitoring, enabling administrators to assess and ensure the optimal health and performance of the database -* A new :ref:`Query Timeout Per Service<query_timeout_minutes>` cluster flag that is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops +* A new :ref:`Query Timeout<query_timeout_minutes>` session flag designed to identify queries that have exceeded a specified time limit. Once the flag value is reached, the query automatically stops :ref:`Version 4.4 - September 28, 2023<4.4>` From 8ccc3ef8fda6a309378c66f8357ece298474e3a2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 14:27:03 +0200 Subject: [PATCH 1058/1892] query timeout --- configuration_guides/query_timeout_minutes.rst | 2 +- releases/4.5.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/query_timeout_minutes.rst b/configuration_guides/query_timeout_minutes.rst index 60e880ef0..f553d8127 100644 --- a/configuration_guides/query_timeout_minutes.rst +++ b/configuration_guides/query_timeout_minutes.rst @@ -4,7 +4,7 @@ Query Timeout Minutes ************************************************** -The ``QueryTimeoutMinutes`` flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. +The ``QueryTimeoutMinutes`` session flag is designed to identify queries that have exceeded a specified time limit. Once the flag value is reached, the query automatically stops. * **Data type** - integer * **Default value** - ``0`` (no query timeout) diff --git a/releases/4.5.rst b/releases/4.5.rst index 6dbd67dc7..d3b6982e3 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -45,7 +45,7 @@ New Features and Enhancements Known Issues ------------ -* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>`. +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` Version 4.5 resolved Issues From 8de4b78740b7aff5bd4e7056de02f8a074e83c64 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Dec 2023 15:11:02 +0200 Subject: [PATCH 1059/1892] Update index.rst --- index.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/index.rst b/index.rst index cab1acf8b..b1b243787 100644 --- a/index.rst +++ b/index.rst @@ -66,15 +66,14 @@ If you couldn't find what you're looking for, we're always happy to help. Visit getting_started/index installation_guides/index upgrade_guide/index - data_ingestion/index + operational_guides/index + configuration_guides/index + architecture/index + sqream_studio_5.7.0/index connecting_to_sqream/index + data_ingestion/index external_storage_platforms/index - loading_and_unloading_data/index feature_guides/index - operational_guides/index - sqream_studio_5.7.0/index - architecture/index - configuration_guides/index reference/index data_type_guides/index releases/index From a5406bbc51a8fdb774028b764ecc449fcc1e4022 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Dec 2023 11:18:14 +0200 Subject: [PATCH 1060/1892] Update index.rst --- index.rst | 76 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/index.rst b/index.rst index b1b243787..5b4618924 100644 --- a/index.rst +++ b/index.rst @@ -8,43 +8,45 @@ SQream DB Documentation SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQream DB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| Topic | Description | -+===================================================+========================================================================================================================================+ -| **Getting Started** | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`preparing_your_machine_to_install_sqream` | Set up your local machine according to SQream’s recommended pre-installation configurations. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`executing_statements_in_sqream` | Provides more information about the available methods for executing statements in SQream. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`performing_basic_sqream_operations` | Provides more information on performing basic operations. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`hardware_guide` | Describes SQream’s mandatory and recommended hardware settings, designed for a technical audience. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Installation Guides** | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`installing_and_launching_sqream` | Refers to SQream’s installation guides. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`sqream_studio_installation` | Refers to all installation guides required for installations related to Studio. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Ingesting Data** | -+--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`csv` | :ref:`avro` | | -+--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`parquet` | :ref:`orc` | | -+--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Connecting to SQream** | -+--------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`client_drivers` | Describes how to use the SQream client drivers and client applications with SQream. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **External Storage Platforms** | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`s3` | Describes how to insert data over a native S3 connector. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`hdfs` | Describes how to configure an HDFS environment for the user sqream and is only relevant for users with an HDFS environment. | -+---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| Topic | Description | ++=============================================================+========================================================================================================================================+ +| **Getting Started** | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`preparing_your_machine_to_install_sqream` | Set up your local machine according to SQream’s recommended pre-installation configurations. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`executing_statements_in_sqream` | Provides more information about the available methods for executing statements in SQream. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`performing_basic_sqream_operations` | Provides more information on performing basic operations. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hardware_guide` | Describes SQream’s mandatory and recommended hardware settings, designed for a technical audience. | ++---------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Installation Guides** | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`installing_and_launching_sqream` | Refers to SQream’s installation guides. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`sqream_studio_installation` | Refers to all installation guides required for installations related to Studio. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **Ingesting Data** | ++--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`csv` | :ref:`avro` | | ++--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`parquet` | :ref:`orc` | | ++--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`json` | :ref:`ingesting_from_databases` | | ++--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **Connecting to SQream** | ++--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_drivers` | Describes how to use the SQream client drivers and client applications with SQream. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| **External Storage Platforms** | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`s3` | Describes how to insert data over a native S3 connector. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hdfs` | Describes how to configure an HDFS environment for the user sqream and is only relevant for users with an HDFS environment. | ++-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ .. only:: html From 502365a84d9d7a999663dd1e3616e01293c80834 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 08:06:22 +0200 Subject: [PATCH 1061/1892] Update index.rst --- index.rst | 84 +++++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/index.rst b/index.rst index 5b4618924..4fb2ef4e1 100644 --- a/index.rst +++ b/index.rst @@ -1,52 +1,52 @@ .. _index: ************************* -SQream DB Documentation +SQreamDB Documentation ************************* -SQream DB is a columnar analytic SQL database management system. SQream DB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQream DB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQream DB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. +SQreamDB is a columnar analytic SQL database management system. SQreamDB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQreamDB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQreamDB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| Topic | Description | -+=============================================================+========================================================================================================================================+ -| **Getting Started** | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`preparing_your_machine_to_install_sqream` | Set up your local machine according to SQream’s recommended pre-installation configurations. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`executing_statements_in_sqream` | Provides more information about the available methods for executing statements in SQream. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`performing_basic_sqream_operations` | Provides more information on performing basic operations. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`hardware_guide` | Describes SQream’s mandatory and recommended hardware settings, designed for a technical audience. | -+---------------------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------+ -| **Installation Guides** | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`installing_and_launching_sqream` | Refers to SQream’s installation guides. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`sqream_studio_installation` | Refers to all installation guides required for installations related to Studio. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Ingesting Data** | -+--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`csv` | :ref:`avro` | | -+--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`parquet` | :ref:`orc` | | -+--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`json` | :ref:`ingesting_from_databases` | | -+--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **Connecting to SQream** | -+--------------------------+----------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`client_drivers` | Describes how to use the SQream client drivers and client applications with SQream. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| **External Storage Platforms** | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`s3` | Describes how to insert data over a native S3 connector. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`hdfs` | Describes how to configure an HDFS environment for the user sqream and is only relevant for users with an HDFS environment. | -+-------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| Topic | Description | ++=============================================================+==========================================================================================================================================+ +| **Getting Started** | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`preparing_your_machine_to_install_sqream` | Set up your local machine according to SQreamDB’s recommended pre-installation configurations. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`executing_statements_in_sqream` | Provides more information about the available methods for executing statements in SQreamDB. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`performing_basic_sqream_operations` | Provides more information on performing basic operations. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hardware_guide` | Describes SQreamDB’s mandatory and recommended hardware settings, designed for a technical audience. | ++---------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------+ +| **Installation Guides** | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`installing_and_launching_sqream` | Refers to SQreamDB’s installation guides. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`sqream_studio_installation` | Refers to all installation guides required for installations related to Studio. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| **Ingesting Data** | ++--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`csv` | :ref:`avro` | | ++--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`parquet` | :ref:`orc` | | ++--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`json` | :ref:`ingesting_from_databases` | | ++--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| **Connecting to SQreamDB** | ++--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_platforms` | Describes how to install and connect a variety of third party connection platforms and tools. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`client_drivers` | Describes how to use the SQreamDB client drivers and client applications with SQreamDB. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| **External Storage Platforms** | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`s3` | Describes how to insert data over a native S3 connector. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`hdfs` | Describes how to configure an HDFS environment for the user sqream and is only relevant for users with an HDFS environment. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ .. only:: html @@ -55,7 +55,7 @@ SQream DB is a columnar analytic SQL database management system. SQream DB suppo .. rubric:: Need help? -If you couldn't find what you're looking for, we're always happy to help. Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/>`_ for additional support. +If you couldn't find what you're looking for, we're always happy to help. Visit `SQreamDB's support portal <https://sqream.atlassian.net/servicedesk/>`_ for additional support. .. toctree:: From 6974f5e54848aa49ff8da73794f65ff0272a1559 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 08:38:41 +0200 Subject: [PATCH 1062/1892] Studio --- index.rst | 2 +- .../configuring_your_instance_of_sqream.rst | 0 ...ing_and_managing_roles_and_permissions.rst | 0 ...ts_and_running_queries_from_the_editor.rst | 86 ++++++++----------- .../getting_started.rst | 2 +- .../index.rst | 4 +- ...orkers_and_services_from_the_dashboard.rst | 0 .../viewing_logs.rst | 0 8 files changed, 42 insertions(+), 52 deletions(-) rename {sqream_studio_5.7.0 => sqream_studio}/configuring_your_instance_of_sqream.rst (100%) rename {sqream_studio_5.7.0 => sqream_studio}/creating_assigning_and_managing_roles_and_permissions.rst (100%) rename {sqream_studio_5.7.0 => sqream_studio}/executing_statements_and_running_queries_from_the_editor.rst (85%) rename {sqream_studio_5.7.0 => sqream_studio}/getting_started.rst (97%) rename {sqream_studio_5.7.0 => sqream_studio}/index.rst (86%) rename {sqream_studio_5.7.0 => sqream_studio}/monitoring_workers_and_services_from_the_dashboard.rst (100%) rename {sqream_studio_5.7.0 => sqream_studio}/viewing_logs.rst (100%) diff --git a/index.rst b/index.rst index 4fb2ef4e1..e6155a857 100644 --- a/index.rst +++ b/index.rst @@ -71,7 +71,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit operational_guides/index configuration_guides/index architecture/index - sqream_studio_5.7.0/index + sqream_studio/index connecting_to_sqream/index data_ingestion/index external_storage_platforms/index diff --git a/sqream_studio_5.7.0/configuring_your_instance_of_sqream.rst b/sqream_studio/configuring_your_instance_of_sqream.rst similarity index 100% rename from sqream_studio_5.7.0/configuring_your_instance_of_sqream.rst rename to sqream_studio/configuring_your_instance_of_sqream.rst diff --git a/sqream_studio_5.7.0/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst similarity index 100% rename from sqream_studio_5.7.0/creating_assigning_and_managing_roles_and_permissions.rst rename to sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst diff --git a/sqream_studio_5.7.0/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst similarity index 85% rename from sqream_studio_5.7.0/executing_statements_and_running_queries_from_the_editor.rst rename to sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index 2a2a9475e..6f0cb7ad6 100644 --- a/sqream_studio_5.7.0/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -1,6 +1,6 @@ .. _executing_statements_and_running_queries_from_the_editor: -.. _editor_top_5.4.7: +.. _editor_top: ******************************************************** Executing Statements and Running Queries from the Editor @@ -24,23 +24,23 @@ The following is a brief description of the Editor panels: - Element - Description * - 1 - - :ref:`Toolbar<studio_5.4.7_editor_toolbar>` + - :ref:`Toolbar<studio_editor_toolbar>` - Used to select the active database you want to work on, limit the number of rows, save query, etc. * - 2 - - :ref:`Database Tree and System Queries panel<studio_5.4.7_editor_db_tree>` + - :ref:`Database Tree and System Queries panel<studio_editor_db_tree>` - Shows a hierarchy tree of databases, views, tables, and columns * - 3 - - :ref:`Statement panel<studio_5.4.7_editor_statement_area>` + - :ref:`Statement panel<studio_editor_statement_area>` - Used for writing queries and statements * - 4 - - :ref:`Results panel<studio_5.4.7_editor_results>` + - :ref:`Results panel<studio_editor_results>` - Shows query results and execution information. -.. _top_5.4.7: +.. _top: -.. _studio_5.4.7_editor_toolbar: +.. _studio_editor_toolbar: Executing Statements from the Toolbar ===================================== @@ -78,10 +78,10 @@ You can access the following from the Toolbar pane: For more information on stopping active statements, see the :ref:`STOP_STATEMENT<stop_statement>` command. -:ref:`Back to Executing Statements and Running Queries from the Editor<editor_top_5.4.7>` -.. _studio_5.4.7_editor_db_tree: + +.. _studio_editor_db_tree: Performing Statement-Related Operations from the Database Tree ============================================================== @@ -89,9 +89,6 @@ Performing Statement-Related Operations from the Database Tree From the Database Tree you can perform statement-related operations and show metadata (such as a number indicating the amount of rows in the table). - - - The database object functions are used to perform the following: * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. @@ -191,21 +188,21 @@ The database object functions are used to perform the following: * - Function - Description * - Insert statement - - Generates an `INSERT <https://docs.sqream.com/en/latest/reference/sql/sql_statements/dml_commands/insert.html#insert>`_ statement for the selected table in the editing area. + - Generates an :ref:`INSERT<insert>` statement for the selected table in the editing area. * - Delete statement - - Generates a `DELETE <https://docs.sqream.com/en/latest/reference/sql/sql_statements/dml_commands/delete.html#delete>`_ statement for the selected table in the editing area. + - Generates a :ref:`DELETE<delete>` statement for the selected table in the editing area. * - Create Table As statement - - Generates a `CREATE TABLE AS <https://docs.sqream.com/en/latest/reference/sql/sql_statements/ddl_commands/create_table_as.html#create-table-as>`_ statement for the selected table in the editing area. + - Generates a :ref:`CREATE TABLE AS<create_table_as>` statement for the selected table in the editing area. * - Rename statement - - Generates an `RENAME TABLE AS <https://docs.sqream.com/en/latest/reference/sql/sql_statements/ddl_commands/rename_table.html#rename-table>`_ statement for renaming the selected table in the editing area. + - Generates an :ref:`RENAME TABLE AS<rename_table>` statement for renaming the selected table in the editing area. * - Adding column statement - - Generates an `ADD COLUMN <https://docs.sqream.com/en/latest/reference/sql/sql_statements/ddl_commands/add_column.html#add-column>`_ statement for adding columns to the selected table in the editing area. + - Generates an :ref:`ADD COLUMN<add_column>` statement for adding columns to the selected table in the editing area. * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See `Seeing System Objects as DDL <https://docs.sqream.com/en/latest/operational_guides/seeing_system_objects_as_ddl.html>`_. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See :ref:`Seeing System Objects as DDL <seeing_system_objects_as_ddl>`. * - DDL Optimizer - - The `DDL Optimizer <https://docs.sqream.com/en/latest/sqream_studio_5.4.7/executing_statements_and_running_queries_from_the_editor.html#optimizing-database-tables-using-the-ddl-optimizer>`_ lets you analyze database tables and recommends possible optimizations. + - The :ref:`DDL Optimizer<executing_statements_and_running_queries_from_the_editor>` lets you analyze database tables and recommends possible optimizations. Optimizing Database Tables Using the DDL Optimizer -------------------------------------------------- @@ -231,7 +228,7 @@ The following table describes the DDL Optimizer screen: Clicking **Run Optimizer** adds a tab to the Statement panel showing the optimized results of the selected object. -For more information, see `Optimization and Best Practices <https://docs.sqream.com/en/latest/operational_guides/optimization_best_practices.html>`_. +For more information, see :ref:`Optimization and Best Practices<sql_best_practices>`. Executing Pre-Defined Queries from the System Queries Panel ----------------------------------------------------------- @@ -246,7 +243,7 @@ The **System Queries** panel lets you execute predefined queries and includes th Clicking an item pastes the query into the Statement pane, and you can undo a previous operation by pressing **Ctrl + Z**. -.. _studio_5.4.7_editor_statement_area: +.. _studio_editor_statement_area: Writing Statements and Queries from the Statement Panel ======================================================= @@ -291,13 +288,13 @@ You can also rename the default tab name by double-clicking it and typing a new .. :kbd:`Ctrl` + :kbd:`↓` - Switch to previous tab -.. _studio_editor_results_5.4.7: +.. _studio_editor_results: + -:ref:`Back to Executing Statements and Running Queries from the Editor<editor_top_5.4.7>` .. _studio_5.4.7_editor_results: -.. _results_panel_5.4.7: +.. _results_panel: Viewing Statement and Query Results from the Results Panel ========================================================== @@ -314,17 +311,17 @@ The following is a brief description of the Results panel views highlighted in t * - Element - Description - * - :ref:`Results view<results_view_5.4.7>` + * - :ref:`Results view<results_view>` - Lets you view search query results. - * - :ref:`Execution Details view<execution_details_view_5.4.7>` + * - :ref:`Execution Details view<execution_details_view>` - Lets you analyze your query for troubleshooting and optimization purposes. - * - :ref:`SQL view<sql_view_5.4.7>` + * - :ref:`SQL view<sql_view>` - Lets you see the SQL view. -.. _results_view_5.4.7: +.. _results_view: + -:ref:`Back to Executing Statements and Running Queries from the Editor<editor_top_5.4.7>` Searching Query Results in the Results View ------------------------------------------- @@ -344,7 +341,7 @@ Saving Results to the Clipboard The **Save results to clipboard** function lets you save your results to the clipboard to paste into another text editor or into Excel for further analysis. -.. _save_results_to_local_file_5.4.7: +.. _save_results_to_local_file: Saving Results to a Local File ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -353,7 +350,7 @@ The **Save results to local file** functions lets you save your search query res In the Results view you can also run parallel statements, as described in **Running Parallel Statements** below. -.. _running_parallel_statements_5.4.7: +.. _running_parallel_statements: Running Parallel Statements ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -372,27 +369,24 @@ The following shows the syntax for running parallel statements: $ $$ -:ref:`Back to Viewing Statement and Query Results from the Results Panel<results_panel_5.4.7>` -.. _execution_details_view_5.4.7: -.. _execution_tree_5.4.7: +.. _execution_details_view: + +.. _execution_tree: Execution Details View ---------------------- -The **Execution Details View** section describes the following: +Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. + +.. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. + .. contents:: :local: :depth: 1 - -Overview -^^^^^^^^ -Clicking **Execution Details View** displays the **Execution Tree**, which is a chronological tree of processes that occurred to execute your queries. The purpose of the Execution Tree is to analyze all aspects of your query for troubleshooting and optimization purposes, such as resolving queries with an exceptionally long runtime. - -.. note:: The **Execution Details View** button is enabled only when a query takes longer than five seconds. From this screen you can scroll in, out, and around the execution tree with the mouse to analyze all aspects of your query. You can navigate around the execution tree by dragging or by using the mini-map in the bottom right corner. @@ -489,17 +483,13 @@ This can be seen in the **timeSum** column as follows: * **Rows highlighted orange** - medium runtime * **Rows highlighted yellow** - shortest runtime -:ref:`Back to Viewing Statement and Query Results from the Results Panel<results_panel_5.4.7>` -.. _sql_view_5.4.7: + +.. _sql_view: Viewing Wrapped Strings in the SQL View --------------------------------------- The SQL View panel allows you to more easily view certain queries, such as a long string that appears on one line. The SQL View makes it easier to see by wrapping it so that you can see the entire string at once. It also reformats and organizes query syntax entered in the Statement panel for more easily locating particular segments of your queries. The SQL View is identical to the **Format SQL** feature in the Toolbar, allowing you to retain your originally constructed query while viewing a more intuitively structured snapshot of it. -.. _save_results_to_clipboard_5.4.7: - -:ref:`Back to Viewing Statement and Query Results from the Results Panel<results_panel_5.4.7>` - -:ref:`Back to Executing Statements and Running Queries from the Editor<editor_top_5.4.7>` +.. _save_results_to_clipboard: diff --git a/sqream_studio_5.7.0/getting_started.rst b/sqream_studio/getting_started.rst similarity index 97% rename from sqream_studio_5.7.0/getting_started.rst rename to sqream_studio/getting_started.rst index dad6e613b..e69eef421 100644 --- a/sqream_studio_5.7.0/getting_started.rst +++ b/sqream_studio/getting_started.rst @@ -1,7 +1,7 @@ .. _getting_started: ****************************************************** -Getting Started with SQream Acceleration Studio 5.7.0 +Getting Started with SQream Acceleration Studio ****************************************************** Setting Up and Starting Studio diff --git a/sqream_studio_5.7.0/index.rst b/sqream_studio/index.rst similarity index 86% rename from sqream_studio_5.7.0/index.rst rename to sqream_studio/index.rst index 96e25eaac..ca9eefbba 100644 --- a/sqream_studio_5.7.0/index.rst +++ b/sqream_studio/index.rst @@ -1,10 +1,10 @@ .. _sqream_studio_: ******************************** -SQream Acceleration Studio 5.7.0 +SQreamDB Acceleration Studio ******************************** -The SQreamDB Acceleration Studio 5.7.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. +The SQreamDB Acceleration Studio 5.8.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. .. toctree:: :maxdepth: 1 diff --git a/sqream_studio_5.7.0/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst similarity index 100% rename from sqream_studio_5.7.0/monitoring_workers_and_services_from_the_dashboard.rst rename to sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst diff --git a/sqream_studio_5.7.0/viewing_logs.rst b/sqream_studio/viewing_logs.rst similarity index 100% rename from sqream_studio_5.7.0/viewing_logs.rst rename to sqream_studio/viewing_logs.rst From 958215c8cc3a4865982dc9640d0f293e50c5a40d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 08:59:39 +0200 Subject: [PATCH 1063/1892] RN --- releases/4.3.rst | 2 ++ upgrade_guide/version_upgrade_configurations.rst | 13 +++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/releases/4.3.rst b/releases/4.3.rst index b56a89964..fd8244ceb 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -151,6 +151,8 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t * ``VARCHAR`` is no longer supported for new customers, effective from version 2022.1.3. * The ``TEXT`` data type is replacing the ``VARCHAR`` and ``NVARCHAR`` data types. +.. _upgrade_to_4.3: + Upgrading to v4.3 ----------------- diff --git a/upgrade_guide/version_upgrade_configurations.rst b/upgrade_guide/version_upgrade_configurations.rst index e4ccbd63b..1dc0bcc18 100644 --- a/upgrade_guide/version_upgrade_configurations.rst +++ b/upgrade_guide/version_upgrade_configurations.rst @@ -15,10 +15,15 @@ Upgrade-Related Configuration Changes - Configurations and Changes * - 4.4 - 49 - - + - New Releases: + * Pysqream 5.0.0 Connector is released + + * JDBC 5.0.0 Connector is released * - 4.3 - 49 - - + - Configuration: + * Two new :ref:`AWS S3<s3>` object access style and endpoint URL with Virtual Private Cloud (VPC) configuration flags: ``AwsEndpointOverride``, ``AwsObjectAccessStyle`` + * **REHL 8.x** is now officially supported * - 4.2 - 46 - New Releases: @@ -31,6 +36,10 @@ Upgrade-Related Configuration Changes * Apache Spark 5.0.0 Connector is released * The ``INT96`` data type is deprecated + + Configuration: + + * :ref:`Access control permissions<access_control_permissions>` in SQreamDB have been expanded. Learn how to reconfigure access control permissions when :ref:`upgrading from version 4.2<upgrade_to_4.3>` * - 4.1 - 45 - New Releases: From cc8eb08a7d6107b721adc1e28308bfda41277928 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 10:56:50 +0200 Subject: [PATCH 1064/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index fc8d87e65..3df177304 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -4,18 +4,16 @@ Recommended Pre-Installation Configuration ********************************************* -Before :ref:`installing SQream DB<installing_sqream_db_docker>`, SQream recommends you to tune your system for better performance and stability. - -This page provides recommendations for production deployments of SQream and describes the following: +Before installing SQreamDB, it is recommended that you to tune your system for better performance and stability. .. contents:: :local: :depth: 1 -Recommended BIOS Settings -========================== +Recommended Basic Input/Output System Settings +=============================================== -The first step when setting your pre-installation configurations is to use the recommended BIOS settings. +The first step when setting your pre-installation configurations is to use the recommended basic input/output system (BIOS) settings. The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. @@ -89,13 +87,19 @@ If any doubt arises, consult the documentation for your server or your hardware Installing the Operating System =================================================== -Once the BIOS settings have been set, you must install the operating system. Either the CentOS (versions 7.6-7.9) or RHEL (versions 7.x-8.x) must be installed before installing the SQream database, by either the customer or a SQream representative. +Before You Begin +------------------- + +* Your system must have at least 200 gigabytes of free space on the root directory. + +* You must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. + +Once the BIOS settings have been set, you must install the operating system. Either CentOS 7.9 or RHEL 7.9-8.8 must be installed before installing the SQreamDB database, by either the customer or a SQream representative. Verify the exact RHEL7/RHEL8 version with Storage vendor to avoid drivers incompatibility. **To install the operating system:** #. Select a language (English recommended). -#. From **Software Selection**, select **Minimal**. -#. Select the **Development Tools** group checkbox. +#. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. #. Continue the installation. #. Set up the necessary drives and users as per the installation process. @@ -124,7 +128,7 @@ The root user is created and the OS shell is booted up. Configuring the Operating System =================================================== -Once you've installted your operation system, you can configure it. When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. +Once you've installed your operation system, you can configure it. When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Logging In to the Server -------------------------------- From 0bbdde4ad7b051a21f508c05ee99a62582f01df0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 12:46:11 +0200 Subject: [PATCH 1065/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 121 +++++++++++++----- 1 file changed, 87 insertions(+), 34 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 3df177304..8d009f70c 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -128,31 +128,29 @@ The root user is created and the OS shell is booted up. Configuring the Operating System =================================================== -Once you've installed your operation system, you can configure it. When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Logging In to the Server -------------------------------- -You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created while installing the operating system above. +You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created during the installation of the operating system. -Automatically Creating a SQream User ------------------------------------- - -**To automatically create a SQream user:** +Automatically Creating a ``sqream`` User +------------------------------------------ -#. If a SQream user was created during installation, verify that the same ID is used on every server: +#. If a ``sqream`` user was created during installation, verify that the same ID is used on every server: .. code-block:: console $ sudo id sqream - The ID **1000** is used on each server in the following example: + The ID **1000** is used on each server, as in the following example: .. code-block:: console $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) -2. If the ID's are different, delete the SQream user and SQream group from both servers: +2. If the ID's are different, delete the ``sqream`` user and ``sqream`` group from both servers: .. code-block:: console @@ -164,36 +162,46 @@ Automatically Creating a SQream User $ sudo rm /var/spool/mail/sqream -Manually Creating a SQream User --------------------------------- - -**To manually create a SQream user:** +Manually Creating a ``sqream`` User +------------------------------------ -SQream enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create during the operating system installation procedure. +SQreamDB enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create users during the operating system installation procedure. + +#. Verify that a **1111** UID does not already exists: -1. Add a user with an identical UID on all cluster nodes: + .. code-block:: + + $ cat /etc/passwd |grep 1111 + +#. Verify that a **1111** GID does not already exists: + + .. code-block:: + + $ cat /etc/group |grep 1111 + +#. Add a user with an identical UID on all cluster nodes: .. code-block:: console $ useradd -u 1111 sqream -2. Add the user **sqream** to the **wheel** group. +#. Add the user ``sqream`` to the ``wheel`` group. .. code-block:: console $ sudo usermod -aG wheel sqream - You can remove the SQream user from the **wheel** group when the installation and configuration are complete: + You can remove the ``sqream`` user from the ``wheel`` group when the installation and configuration are complete: .. code-block:: console $ passwd sqream -3. Log out and log back in as **sqream**. +#. Log out and log back in as ``sqream``. - .. note:: If you deleted the **sqream** user and recreated it with different ID, to avoid permission errors, you must change its ownership to /home/sqream. + .. note:: If you deleted the ``sqream`` user and recreated it with different ID, to avoid permission errors, you must change its ownership to ``/home/sqream``. -4. Change the **sqream** user's ownership to /home/sqream: +6. Change the ``sqream`` user's ownership to ``/home/sqream``: .. code-block:: console @@ -202,9 +210,7 @@ SQream enables you to manually create users. This section shows you how to manua Setting Up A Locale -------------------------------- -SQream enables you to set up a locale. In this example, the locale used is your own location. - -**To set up a locale:** +SQreamDB enables you to set up a locale. In this example, the locale used is your own location. 1. Set the language of the locale: @@ -218,28 +224,75 @@ SQream enables you to set up a locale. In this example, the locale used is your $ sudo timedatectl set-timezone Asia/Jerusalem -If needed, you can run the **timedatectl list-timezones** command to see your current time-zone. +If needed, you can run the ``timedatectl list-timezones`` command to see your current time-zone. -Installing the Required Packages --------------------------------- +Installing Required Software +--------------------------------- + +**Installing EPEL Repository:** -You can install the required packages by running the following command: +**CentOS7/RHEL8** .. code-block:: console - $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq - + $ sudo yum install epel-release -Installing the Recommended Tools --------------------------------- +**RHEL7** + +.. code-block:: console + + $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -You can install the recommended tools by running the following command: +**RHEL8** .. code-block:: console - $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - + $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + +**Enabling Additional Red Hat Repositories:** + +**RHEL7** + +.. code-block:: console + + $ sudo subscription-manager repos --enable rhel-7-server-optional-rpms + +**RHEL8** + +.. code-block:: console + + $ sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms + $ sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms + $ sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms + +**Installing Required Packages:** + +**RHEL7/CentOS7** + +.. code-block:: console + + $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel + +**RHEL8** + +.. code-block:: console + + $ sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo + +**Installing Recommended Tools:** + +**RHEL7/CentOS7** + +.. code-block:: console + + $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + +**RHEL8** + +.. code-block:: console + + $ sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix Installing Python 3.6.7 -------------------------------- From e227943ea7c01f580844e87f511fbc4e19ddef35 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:07:00 +0200 Subject: [PATCH 1066/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 8d009f70c..45102e52f 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -294,8 +294,9 @@ Installing Required Software $ sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix -Installing Python 3.6.7 --------------------------------- +**Installing Python:** + +For SQreamDb version 4.3 or older, install Python 3.6.7. 1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: @@ -338,6 +339,50 @@ Installing Python 3.6.7 .. code-block:: console $ python3 + +For SQreamDB version 4.4 or newer, install Python 3.9.13. + +1. Download the Python 3.9.13 source code tarball file from the following URL into the **/home/sqream** directory: + + .. code-block:: console + + $ wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz + +2. Extract the Python 3.9.13 source code into your current directory: + + .. code-block:: console + + $ tar -xf Python-3.9.13.tar.xz + +3. Navigate to the Python 3.9.13 directory: + + .. code-block:: console + + $ cd Python-3.9.13 + +4. Run the **./configure** script: + + .. code-block:: console + + $ ./configure + +5. Build the software: + + .. code-block:: console + + $ make -j30 + +6. Install the software: + + .. code-block:: console + + $ sudo make install + +7. Verify that Python 3.9.13 has been installed: + + .. code-block:: console + + $ python3 Installing NodeJS on CentOS -------------------------------- From 5cc4c9688eaa30f72b46c699c3393c21f3add41d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:18:09 +0200 Subject: [PATCH 1067/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 45102e52f..e942172fe 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -437,7 +437,7 @@ Installing NodeJS on Ubuntu $ sudo npm install pm2 -g Installing NodeJS Offline -------------------------------------------- +------------------------------- **To install NodeJS Offline** @@ -445,13 +445,13 @@ Installing NodeJS Offline .. code-block:: console - $ wget https://nodejs.org/dist/v12.13.0/node-v12.13.0-linux-x64.tar.xz + $ wget https://nodejs.org/dist/latest-v14.x/node-v14.21.3-linux-x64.tar.xz -2. Move the node-v12.13.0-linux-x64 file to the */usr/local* directory. +2. Move the node-v14.21.3-linux-x64 file to the */usr/local* directory. .. code-block:: console - $ sudo mv node-v12.13.0-linux-x64 /usr/local + $ sudo mv node-v14.21.3-linux-x64 /usr/local 3. Navigate to the */usr/bin/* directory: @@ -459,23 +459,23 @@ Installing NodeJS Offline $ cd /usr/bin -4. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/node node* directory: +4. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/node node* directory: .. code-block:: console - $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/node node + $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/node node -5. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/npm npm* directory: +5. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npm npm* directory: .. code-block:: console - $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/npm npm + $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm -6. Create a symbolic link to the */local/node-v12.13.0-linux-x64/bin/npx npx* directory: +6. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npx npx* directory: .. code-block:: console - $ sudo ln -s ../local/node-v12.13.0-linux-x64/bin/npx npx + $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx 7. Verify that the node versions for the above are correct: From 9394213ee3dd96e6b49adeae8b75f94608f1a4ac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 14:19:55 +0200 Subject: [PATCH 1068/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 61 +++---------------- 1 file changed, 9 insertions(+), 52 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index e942172fe..772e836e5 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -412,29 +412,6 @@ Installing NodeJS on CentOS .. code-block:: console $ sudo npm install pm2 -g - -Installing NodeJS on Ubuntu --------------------------------- - -**To install the node.js file on Ubuntu:** - -1. Download the `setup_12.x file <https://deb.nodesource.com/setup_12.x>`__ as a root user logged in shell: - - .. code-block:: console - - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Install the node.js file: - - .. code-block:: console - - $ sudo apt-get install -y nodejs - -3. Install npm and make it available for all users: - - .. code-block:: console - - $ sudo npm install pm2 -g Installing NodeJS Offline ------------------------------- @@ -484,9 +461,7 @@ Installing NodeJS Offline $ node --version Installing the pm2 Service Offline -------------------------------------------- - -**To install the pm2 Service Offline** +------------------------------------ 1. On a machine with internet access, install the following: @@ -498,30 +473,30 @@ Installing the pm2 Service Offline .. code-block:: console - $ cd /usr/local/node-v12.13.0-linux-x64/lib/node_modules + $ cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules $ tar -czvf pm2_x86.tar.gz pm2 -3. Copy the **pm2_x86.tar.gz** file to a server without access to the internet and extract it. +3. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. :: -4. Move the **pm2** folder to the */usr/local/node-v12.13.0-linux-x64/lib/node_modules* directory: +4. Move the ``pm2`` folder to the ``/usr/local/node-v14.21.3-linux-x64/lib/node_modules`` directory: .. code-block:: console - $ sudo mv pm2 /usr/local/node-v12.13.0-linux-x64/lib/node_modules + $ sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules -5. Navigate back to the */usr/bin* directory: +5. Navigate back to the ``/usr/bin`` directory: .. code-block:: console $ cd /usr/bin again -6. Create a symbolink to the **pm2** service: +6. Create a symbolink to the ``pm2`` service: .. code-block:: console - $ sudo ln -s /usr/local/node-v12.22.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + $ sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 7. Verify that installation was successful: @@ -529,7 +504,7 @@ Installing the pm2 Service Offline $ pm2 list - .. note:: This must be done as a **sqream** user, and not as a **sudo** user. + .. note:: The following step must be done as a ``sqream`` user, and not as a ``sudo`` user. 8. Verify that the node version is correct: @@ -813,12 +788,6 @@ CUDA Driver Prerequisites $ sudo yum install -y gcc - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install gcc - Updating the Kernel Headers -------------------------------- @@ -832,12 +801,6 @@ Updating the Kernel Headers $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install linux-headers-$(uname -r) - 2. Install **wget** one of the following operating systems: * On RHEL/CentOS: @@ -845,12 +808,6 @@ Updating the Kernel Headers .. code-block:: console $ sudo yum install wget - - * On Ubuntu: - - .. code-block:: console - - $ sudo apt-get install wget Disabling Nouveau -------------------------------- From ff81f093d49eaf97b33cbbf41c0b0cd1527fff3f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Dec 2023 16:01:00 +0200 Subject: [PATCH 1069/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 198 ++++++++++-------- 1 file changed, 109 insertions(+), 89 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 772e836e5..ed2efdda8 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -387,8 +387,6 @@ For SQreamDB version 4.4 or newer, install Python 3.9.13. Installing NodeJS on CentOS -------------------------------- -**To install the node.js on CentOS:** - 1. Download the `setup_12.x file <https://rpm.nodesource.com/setup_12.x>`__ as a root user logged in shell: .. code-block:: console @@ -416,8 +414,6 @@ Installing NodeJS on CentOS Installing NodeJS Offline ------------------------------- -**To install NodeJS Offline** - 1. Download the NodeJS source code tarball file from the following URL into the **/home/sqream** directory: .. code-block:: console @@ -513,13 +509,9 @@ Installing the pm2 Service Offline $ node -v Configuring the Network Time Protocol -------------------------------------------- - -This section describes how to configure your **Network Time Protocol (NTP)**. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. - -**To configure your NTP:** +-------------------------------------- + +This Network Time Protocol (NTP) configuration is intended for use on systems running RHEL7 and CentOS7 exclusively. 1. Install the NTP file. @@ -544,21 +536,21 @@ If you don't have internet access, see `Configure NTP Client to Synchronize with .. code-block:: console $ sudo ntpq -p + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. Configuring the Network Time Protocol Server -------------------------------------------- -If your organization has an NTP server, you can configure it. - -**To configure your NTP server:** +If your organization has a Network Time Protocol (NTP) server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled. -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the outuput. +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the output: .. code-block:: console $ echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf -2. Restart the service. +2. Restart the service: .. code-block:: console @@ -588,9 +580,30 @@ If your organization has an NTP server, you can configure it. Next DST change: DST ends (the clock jumps one hour backwards) at Sun 2019-11-03 01:59:59 EDT Sun 2019-11-03 01:00:00 EST - -Configuring the Server to Boot Without the UI ---------------------------------------------- + +Configuring Chrony for RHEL8 Only +---------------------------------- + +#. Start the Chrony service: + +..code-block:: + + $ sudo systemctl start chronyd + +#. Enable the Chrony service to start automatically at boot time: + +..code-block:: + + $ sudo systemctl enable chronyd + +#. Check the status of the Chrony service: + +..code-block:: + + $ sudo systemctl status chronyd + +Configuring the Server to Boot Without Linux the UI +---------------------------------------------------- You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: @@ -603,7 +616,7 @@ Running this command activates the **NO-UI** server mode. Configuring the Security Limits -------------------------------- -The security limits refers to the number of open files, processes, etc. +The security limits refer to the number of open files, processes, etc. You can configure the security limits by running the **echo -e** command as a root user logged in shell: @@ -613,28 +626,24 @@ You can configure the security limits by running the **echo -e** command as a ro .. code-block:: console - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nroot soft nproc 1000000\nroot hard nproc 1000000\nroot soft nofile 1000000\nroot hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf Configuring the Kernel Parameters --------------------------------- -**To configure the kernel parameters:** - 1. Insert a new line after each kernel parameter: .. code-block:: console $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf - .. note:: In the past, the **vm.zone_reclaim_mode** parameter was set to **7.** In the latest Sqream version, the vm.zone_reclaim_mode parameter must be set to **0**. If it is not set to **0**, when a numa node runs out of memory, the system will get stuck and will be unable to pull memory from other numa nodes. - -2. Check the maximum value of the **fs.file**. +2. Check the maximum value of the ``fs.file``. .. code-block:: console $ sysctl -n fs.file-max -3. If the maximum value of the **fs.file** is smaller than **2097152**, run the following command: +3. If the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: .. code-block:: console @@ -653,11 +662,9 @@ Configuring the Kernel Parameters $ sudo reboot Configuring the Firewall --------------------------------- - -The example in this section shows the open ports for four sqreamd sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. +-------------------------- -**To configure the firewall:** +The example in this section shows the open ports for four ``sqreamd`` sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. 1. Start the service and enable FirewallID on boot: @@ -692,26 +699,27 @@ The example in this section shows the open ports for four sqreamd sessions. If m .. code-block:: console + $ sudo systemctl stop firewalld $ sudo systemctl disable firewalld -Disabling selinux --------------------------------- +Disabling SELinux +------------------- -**To disable selinux:** +Disabling SELinux is a recommended action. -1. Show the status of **selinux**: +1. Show the status of ``selinux``: .. code-block:: console $ sudo sestatus -2. If the output is not **disabled**, edit the **/etc/selinux/config** file: +2. If the output is not ``disabled``, edit the ``/etc/selinux/config`` file: .. code-block:: console $ sudo vim /etc/selinux/config -3. Change **SELINUX=enforcing** to **SELINUX=disabled**. +3. Change ``SELINUX=enforcing`` to ``SELINUX=disabled``: The above changes will only take effect after rebooting the server. @@ -721,12 +729,10 @@ Disabling selinux $ sudo setenforce 0 -Configuring the /etc/hosts File --------------------------------- - -**To configure the /etc/hosts file:** +Configuring the ``/etc/hosts`` File +------------------------------------ -1. Edit the **/etc/hosts** file: +1. Edit the ``/etc/hosts`` file: .. code-block:: console @@ -741,9 +747,7 @@ Configuring the /etc/hosts File $ <server2 ip> <server_name> Configuring the DNS --------------------------------- - -**To configure the DNS:** +-------------------- 1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: @@ -759,14 +763,14 @@ Configuring the DNS $ DNS2="8.8.8.8" Installing the Nvidia CUDA Driver -=================================================== +================================== After configuring your operating system, you must install the Nvidia CUDA driver. .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. CUDA Driver Prerequisites --------------------------------- +--------------------------- 1. Verify that the NVIDIA card has been installed and is detected by the system: @@ -774,47 +778,45 @@ CUDA Driver Prerequisites $ lspci | grep -i nvidia -2. Check which version of gcc has been installed: +2. Check which version of ``gcc`` has been installed: .. code-block:: console $ gcc --version -3. If gcc has not been installed, install it for one of the following operating systems: - - * On RHEL/CentOS: +3. If ``gcc`` has not been installed, install it for RHEL or CentOS: .. code-block:: console $ sudo yum install -y gcc Updating the Kernel Headers --------------------------------- +----------------------------- -**To update the kernel headers:** - -1. Update the kernel headers on one of the following operating systems: - - * On RHEL/CentOS: +1. Update the kernel headers on RHEL or CentOS: .. code-block:: console $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) +2. Make sure kernel-devel and kernel-headers match installed kernel: + + .. code-block:: console + + $ uname -r + $ rpm -qa |grep kernel-devel-$(uname -r) + $ rpm -qa |grep kernel-headers-$(uname -r) + 2. Install **wget** one of the following operating systems: - - * On RHEL/CentOS: .. code-block:: console $ sudo yum install wget Disabling Nouveau --------------------------------- +------------------ -You can disable Nouveau, which is the default driver. - -**To disable Nouveau:** +You can disable Nouveau, which is the default operating system driver. 1. Check if the Nouveau driver has been loaded: @@ -833,28 +835,24 @@ You can disable Nouveau, which is the default driver. options nouveau modeset=0 EOF -3. Regenerate the kernel **initramfs** directory set: +3. Regenerate the kernel ``initramfs`` directory set: - 1. Modify the **initramfs** directory set: + a. Modify the ``initramfs`` directory set: .. code-block:: console $ sudo dracut --force - 2. Reboot the server: + b. Reboot the server: .. code-block:: console $ sudo reboot Installing the CUDA Driver --------------------------------- - -This section describes how to install the CUDA driver. +---------------------------- -.. note:: The version of the driver installed on the customer's server must be equal or higher than the driver included in the Sqream release package. Contact a Sqream customer service representative to identify the correct version to install. - -The **Installing the CUDA Driver** section describes the following: +The version of the driver installed on the customer's server must be equal or higher than the driver included in the SqreamDB release package. Contact a `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ to identify the correct version to install. .. contents:: :local: @@ -865,55 +863,77 @@ Installing the CUDA Driver from the Repository Installing the CUDA driver from the Repository is the recommended installation method. -.. warning:: For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQream package. For questions related to which driver to install, contact SQream Customer Support. +For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. -**To install the CUDA driver from the Repository:** +**To install the CUDA driver from the Repository (recommended):** 1. Install the CUDA dependencies for one of the following operating systems: - * For RHEL: + * For RHEL7: .. code-block:: console $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + * For RHEL8: + + .. code-block:: console + + $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + * For CentOS: .. code-block:: console $ sudo yum install epel-release -2. Install the CUDA dependencies from the **epel** repository: +2. (Optional) Install the CUDA dependencies from the ``epel`` repository: .. code-block:: console $ sudo yum install dkms libvdpau - Installing the CUDA depedendencies from the **epel** repository is only required for installing **runfile**. + Installing the CUDA depedendencies from the ``epel`` repository is only required for installing ``runfile``. 3. Download and install the required local repository: - * **Intel - 11.4.3 repository for RHEL7**: - - .. code-block:: console + * **CentOS7/RHEL7 cuda 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + + .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **Intel - CUDA 12.2 for RHEL8**: + .. code-block:: console + + $ sudo yum clean all + $ sudo yum -y install nvidia-driver-latest-dkms + + * **RHEL8.6 cuda 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - .. code-block:: console + .. code-block:: console + + $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + $ sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - $ wget https://developer.download.nvidia.com/compute/cuda/12.2.0/local_installers/cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.x86_64.rpm + * **RHEL8.8 cuda 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** - $ sudo rpm -i cuda-repo-rhel8-12-2-local-12.2.0_535.54.03-1.x86_64.rpm + .. code-block:: console + + $ wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + $ sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + + .. code-block:: console + + $ sudo dnf clean all + $ sudo dnf -y module install nvidia-driver:latest-dkms - * **IBM Power9 - CUDA 10.1 for RHEL7**: + * **IBM Power9 - CUDA 10.1 for RHEL7:** .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm 4. Install the CUDA drivers: From 58e2d25689cd4deb0eb338d14b00835d9547bd23 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Dec 2023 10:09:39 +0200 Subject: [PATCH 1070/1892] SQDB Installation Prerequisites --- architecture/index.rst | 2 +- ...mended_pre-installation_configurations.rst | 39 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/architecture/index.rst b/architecture/index.rst index 83111b8cd..17c27e984 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -1,7 +1,7 @@ .. _architecture: ******************* -System Architecture +Architecture ******************* The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index ed2efdda8..790c9e001 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -769,7 +769,7 @@ After configuring your operating system, you must install the Nvidia CUDA driver .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. -CUDA Driver Prerequisites +Before You Begin --------------------------- 1. Verify that the NVIDIA card has been installed and is detected by the system: @@ -778,7 +778,7 @@ CUDA Driver Prerequisites $ lspci | grep -i nvidia -2. Check which version of ``gcc`` has been installed: +2. Verify that ``gcc`` has been installed: .. code-block:: console @@ -824,9 +824,9 @@ You can disable Nouveau, which is the default operating system driver. $ lsmod | grep nouveau - If the Nouveau driver has been loaded, the command above generates output. + If the Nouveau driver has been loaded, the command above generates output. If the Nouveau driver has not been loaded, you may skip step 2 and 3. -2. Blacklist the Nouveau drivers to disable them: +2. Blacklist the Nouveau driver to disable it: .. code-block:: console @@ -852,7 +852,7 @@ You can disable Nouveau, which is the default operating system driver. Installing the CUDA Driver ---------------------------- -The version of the driver installed on the customer's server must be equal or higher than the driver included in the SqreamDB release package. Contact a `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ to identify the correct version to install. +For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. .. contents:: :local: @@ -863,10 +863,6 @@ Installing the CUDA Driver from the Repository Installing the CUDA driver from the Repository is the recommended installation method. -For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. - -**To install the CUDA driver from the Repository (recommended):** - 1. Install the CUDA dependencies for one of the following operating systems: * For RHEL7: @@ -956,23 +952,28 @@ For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver* $ nvidia-smi -.. note:: If you do not have access to internet, you can set up a local repository offline. +6. Enable NVIDIA-persistenced mode: + + .. code-block:: console + + $ sudo systemctl start nvidia-persistenced + $ sudo systemctl enable nvidia-persistenced -You can prepare the CUDA driver offline from a server connected to the CUDA repo by running the following commands as a *root* user: +You can prepare the CUDA driver offline from a server connected to the CUDA repo by running the following commands as a ``root`` user: -6. Query all the packages installed in your system, and verify that cuda-repo has been installed: +7. Query all the packages installed in your system, and verify that cuda-repo has been installed: .. code-block:: console $ rpm -qa |grep cuda-repo -7. Navigate to the correct repository: +8. Navigate to the correct repository: .. code-block:: console $ cd /etc/yum.repos.d/ -8. List in long format and print lines matching a pattern for the cuda file: +9. List in long format and print lines matching a pattern for the cuda file: .. code-block:: console @@ -984,7 +985,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ cuda-10-1-local.repo -9. Edit the **/etc/yum.repos.d/cuda-10-1-local.repo** file: +10. Edit the **/etc/yum.repos.d/cuda-10-1-local.repo** file: .. code-block:: console @@ -996,19 +997,19 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ name=cuda-10-1-local -10. Clone the repository to a location where it can be copied from: +11. Clone the repository to a location where it can be copied from: .. code-block:: console $ reposync -g -l -m --repoid=cuda-10-1-local --download_path=/var/cuda-repo-10.1-local -11. Copy the repository to the installation server and create the repository: +12. Copy the repository to the installation server and create the repository: .. code-block:: console $ createrepo -g comps.xml /var/cuda-repo-10.1-local -12. Add a repo configuration file in **/etc/yum.repos.d/** by editing the **/etc/yum.repos.d/cuda-10.1-local.repo** repository: +13. Add a repo configuration file in **/etc/yum.repos.d/** by editing the **/etc/yum.repos.d/cuda-10.1-local.repo** repository: .. code-block:: console @@ -1019,7 +1020,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ gpgcheck=1 $ gpgkey=file:///var/cuda-repo-10-1-local/7fa2af80.pub -13. Install the CUDA drivers by installing the most current DKMS (Dynamic Kernel Module Support) NVIDIA driver as a root user logged in shell: +14. Install the CUDA drivers by installing the most current DKMS (Dynamic Kernel Module Support) NVIDIA driver as a root user logged in shell: .. code-block:: console From d44c572d0b33e058c0982d11e8162d44c6f0541a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Dec 2023 13:57:43 +0200 Subject: [PATCH 1071/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 135 +++++++++--------- 1 file changed, 70 insertions(+), 65 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 790c9e001..e46777d4d 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -28,7 +28,7 @@ If any doubt arises, consult the documentation for your server or your hardware - Rationale * - **Management console access** - **Connected** - - Connection to OOB required to preserve continuous network uptime. + - Connection to Out-of-band (OOB) required to preserve continuous network uptime. * - **All drives** - **Connected and displayed on RAID interface** - Prerequisite for cluster or OS installation. @@ -73,7 +73,7 @@ If any doubt arises, consult the documentation for your server or your hardware - Setting a higher voltage for DIMMs may increase performance. * - **Memory Operating Mode** - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQream DB. + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQreamDB. * - **HPe**: **Memory power savings mode** - **Maximum performance** - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. @@ -85,7 +85,7 @@ If any doubt arises, consult the documentation for your server or your hardware - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. Installing the Operating System -=================================================== +================================ Before You Begin ------------------- @@ -94,7 +94,9 @@ Before You Begin * You must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. -Once the BIOS settings have been set, you must install the operating system. Either CentOS 7.9 or RHEL 7.9-8.8 must be installed before installing the SQreamDB database, by either the customer or a SQream representative. Verify the exact RHEL7/RHEL8 version with Storage vendor to avoid drivers incompatibility. +* Once the BIOS settings have been set, you must install the operating system. Either CentOS 7.9 or RHEL 7.9-8.8 must be installed before installing the SQreamDB database, by either the customer or a SQreamDB representative. + +* Verify the exact RHEL7/RHEL8 version with Storage vendor to avoid driver incompatibility. **To install the operating system:** @@ -762,10 +764,10 @@ Configuring the DNS $ DNS1="4.4.4.4" $ DNS2="8.8.8.8" -Installing the Nvidia CUDA Driver +Installing the NVIDIA CUDA Driver ================================== -After configuring your operating system, you must install the Nvidia CUDA driver. +After configuring your operating system, you must install the NVIDIA CUDA driver. .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. @@ -852,7 +854,7 @@ You can disable Nouveau, which is the default operating system driver. Installing the CUDA Driver ---------------------------- -For A100 GPU and other A series GPUs, you must install the **cuda 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. +For A100 GPU and other A series GPUs, you must install the **CUDA 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. .. contents:: :local: @@ -893,7 +895,7 @@ Installing the CUDA driver from the Repository is the recommended installation m 3. Download and install the required local repository: - * **CentOS7/RHEL7 cuda 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** .. code-block:: console @@ -905,14 +907,14 @@ Installing the CUDA driver from the Repository is the recommended installation m $ sudo yum clean all $ sudo yum -y install nvidia-driver-latest-dkms - * **RHEL8.6 cuda 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** .. code-block:: console $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm $ sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **RHEL8.8 cuda 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console @@ -961,7 +963,7 @@ Installing the CUDA driver from the Repository is the recommended installation m You can prepare the CUDA driver offline from a server connected to the CUDA repo by running the following commands as a ``root`` user: -7. Query all the packages installed in your system, and verify that cuda-repo has been installed: +7. Query all the packages installed in your system, and verify that ``cuda-repo`` has been installed: .. code-block:: console @@ -973,7 +975,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ cd /etc/yum.repos.d/ -9. List in long format and print lines matching a pattern for the cuda file: +9. List in long format and print lines matching a pattern for the CUDA file: .. code-block:: console @@ -985,7 +987,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ cuda-10-1-local.repo -10. Edit the **/etc/yum.repos.d/cuda-10-1-local.repo** file: +10. Edit the ``/etc/yum.repos.d/cuda-10-1-local.repo`` file: .. code-block:: console @@ -1009,7 +1011,7 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ createrepo -g comps.xml /var/cuda-repo-10.1-local -13. Add a repo configuration file in **/etc/yum.repos.d/** by editing the **/etc/yum.repos.d/cuda-10.1-local.repo** repository: +13. Add a repo configuration file in ``/etc/yum.repos.d/`` by editing the ``/etc/yum.repos.d/cuda-10.1-local.repo`` repository: .. code-block:: console @@ -1020,18 +1022,19 @@ You can prepare the CUDA driver offline from a server connected to the CUDA repo $ gpgcheck=1 $ gpgkey=file:///var/cuda-repo-10-1-local/7fa2af80.pub -14. Install the CUDA drivers by installing the most current DKMS (Dynamic Kernel Module Support) NVIDIA driver as a root user logged in shell: +14. Install the CUDA drivers by installing the most current Dynamic Kernel Module Support (DKMS) NVIDIA driver as a root user logged in shell: .. code-block:: console + $ sudo bash $ sudo yum -y install nvidia-driver-latest-dkms +15. If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. + Tuning Up NVIDIA Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -This section describes how to tune up NVIDIA performance. - -.. note:: The procedures in this section are relevant to Intel only. +The procedures in this section are relevant to Intel only. .. contents:: :local: @@ -1199,22 +1202,18 @@ The server is ready for the SQream software installation. $ open files (-n) 1000000 Enabling Core Dumps -=================================================== +==================== -After installing the Nvidia CUDA driver, you can enable your core dumps. While SQream recommends enabling your core dumps, it is optional. - -The **Enabling Core Dumps** section describes the following: +After installing the NVIDIA CUDA driver, you can enable your core dumps. While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB to be able to analyze your core dumps, they must be ``gdb`` compatible. .. contents:: :local: :depth: 1 -Checking the abrtd Status ---------------------------------------------------- - -**To check the abrtd status:** +Checking the ``abrtd`` Status +---------------------------- -1. Check if **abrtd** is running: +1. Check if ``abrtd`` is running: .. code-block:: console @@ -1232,9 +1231,7 @@ Checking the abrtd Status $ sudo chkconfig abrtd off Setting the Limits ---------------------------------------------------- - -**To set the limits:** +-------------------- 1. Set the limits: @@ -1242,27 +1239,27 @@ Setting the Limits $ ulimit -c -2. If the output is **0**, add the following lines to the **limits.conf** file (/etc/security): +2. If the output is ``0``, add the following lines to the ``/etc/security/limits.conf`` file: .. code-block:: console $ * soft core unlimited $ * hard core unlimited -3. Log out and log in to apply the limit changes. +3. To apply the limit changes, log out and log back in. Creating the Core Dumps Directory ---------------------------------------------------- +----------------------------------- -**To set the core dumps directory:** +Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the ``/tmp/core_dumps`` directory. If necessary, replace path according to your own environment and disk space. -1. Make the **/tmp/core_dumps** directory: +1. Make the ``/tmp/core_dumps`` directory: .. code-block:: console $ mkdir /tmp/core_dumps -2. Set the ownership of the **/tmp/core_dumps** directory: +2. Set the ownership of the ``/tmp/core_dumps`` directory: .. code-block:: console @@ -1273,15 +1270,12 @@ Creating the Core Dumps Directory .. code-block:: console $ sudo chmod -R 777 /tmp/core_dumps - -.. warning:: Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the */tmp/core_dumps* directory. You must replace path according to your own environment and disk space. + -Setting the Output Directory of the /etc/sysctl.conf File ------------------------------------------------------------------ +Setting the Output Directory of the ``/etc/sysctl.conf`` File +------------------------------------------------------------- -**To set the output directory of the /etc/sysctl.conf file:** - -1. Edit the **/etc/sysctl.conf** file: +1. Open the ``/etc/sysctl.conf`` file in the Vim text editor: .. code-block:: console @@ -1292,7 +1286,7 @@ Setting the Output Directory of the /etc/sysctl.conf File .. code-block:: console $ kernel.core_uses_pid = 1 - $ kernel.core_pattern = /<tmp/core_dumps>/core-%e-%s-%u-%g-%p-%t + $ kernel.core_pattern = /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t $ fs.suid_dumpable = 2 3. To apply the changes without rebooting the server, run the following: @@ -1313,36 +1307,47 @@ Setting the Output Directory of the /etc/sysctl.conf File $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t -5. Verify that the core dumping works: - - .. code-block:: console - - $ select abort_server(); - Verifying that the Core Dumps Work --------------------------------------------------- -You can verify that the core dumps work only after installing and running SQream. This causes the server to crash and a new core.xxx file to be included in the folder that is written in **/etc/sysctl.conf** - -**To verify that the core dumps work:** +You can verify that the core dumps work only after installing and running SQreamDB. This causes the server to crash and a new ``core.xxx`` file to be included in the folder that is written in ``/etc/sysctl.conf``. -1. Stop and restart all SQream services. +1. Stop and restart all SQreamDB services. :: -2. Connect to SQream with ClientCmd and run the following command: +2. Connect to SQreamDB with ClientCmd and run the following command: .. code-block:: console $ select abort_server(); +Verify Your SQreamDb Installation +------------------------------------ + +.. code-block:: console + + cat /etc/os-release #check OS release + + id sqream #make sure sqream user exists and has same id on all cluster members servers. + + mount #please verify that the storage is mounted + + nvidia-smi #make sure driver is insalled properly + + sysctl -n fs.file-max #should be more or equalto 2097152 + + ulimit -c -u -n (run this command as user sqream) + Desired output: + core file size (blocks, -c) unlimited + max user processes (-u) 1000000 + open files (-n) 1000000 + Troubleshooting Core Dumping ---------------------------------------------------- +------------------------------ This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. -**To troubleshoot core dumping:** - 1. Reboot the server. :: @@ -1351,7 +1356,7 @@ This section describes the troubleshooting procedure to be followed if all param .. code-block:: console - $ sudo chmod -R 777 /tmp/core_dumps + $ sudo chmod -R 777 /tmp/core_dumps 3. Verify that the limits have been set correctly: @@ -1366,29 +1371,29 @@ This section describes the troubleshooting procedure to be followed if all param $ core file size (blocks, -c) unlimited $ open files (-n) 1000000 -4. If all parameters have been configured correctly, but running **ulimit -c** outputs **0**, run the following: +4. If all parameters have been configured correctly, but running ``ulimit -c`` outputs ``0``, run the following: .. code-block:: console $ sudo vim /etc/profile -5. Search for line and tag it with the **hash** symbol: +5. Search for line and tag it with the ``hash`` symbol: .. code-block:: console $ ulimit -S -c 0 > /dev/null 2>&1 -6. Log out and log in. +6. Log out and log back in. :: -7. Run the ulimit -c command: +7. Run the ``ulimit -c`` command: .. code-block:: console $ ulimit -c command -8. If the line is not found in **/etc/profile** directory, do the following: +8. If the line is not found in ``/etc/profile`` directory, do the following: a. Run the following command: @@ -1402,4 +1407,4 @@ This section describes the troubleshooting procedure to be followed if all param $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 - c. If the line is found, tag it with the **hash** symbol and reboot the server. + c. If the line is found, tag it with the ``hash`` symbol and reboot the server. From e7ee2939b36e093a9eddfaeca75178d9801753d3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:05:27 +0200 Subject: [PATCH 1072/1892] Update conf.py --- conf.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/conf.py b/conf.py index 0b09c5545..c641f8989 100644 --- a/conf.py +++ b/conf.py @@ -20,13 +20,13 @@ # -- Project information ----------------------------------------------------- -project = 'SQream DB' -copyright = '2023 SQream' -author = 'SQream Documentation' +project = 'SQreamDB' +copyright = '2023 SQreamDB' +author = 'SQreamDB Documentation' # The full version, including alpha/beta/rc tags -release = '4.5' +release = '4.6' From 47e5d1291d2100e9625e0706dcbb350b1d20533f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:25:13 +0200 Subject: [PATCH 1073/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index e46777d4d..c77a5b2f1 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -32,7 +32,7 @@ If any doubt arises, consult the documentation for your server or your hardware * - **All drives** - **Connected and displayed on RAID interface** - Prerequisite for cluster or OS installation. - * - **RAID volumes.** + * - **RAID volumes** - **Configured according to project guidelines. Must be rebooted to take effect.** - Clustered to increase logical volume and provide redundancy. * - **Fan speed Thermal Configuration.** From 16ea6c4f74947ec2bd56fe0a0a0f28639ebe7de8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Dec 2023 14:41:23 +0200 Subject: [PATCH 1074/1892] Pre installation configuration --- ...mended_pre-installation_configurations.rst | 317 ++++++------------ operational_guides/index.rst | 1 + operational_guides/query_split.rst | 23 ++ 3 files changed, 131 insertions(+), 210 deletions(-) create mode 100644 operational_guides/query_split.rst diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index c77a5b2f1..af5d63239 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -1,7 +1,7 @@ .. _recommended_pre-installation_configurations: ********************************************* -Recommended Pre-Installation Configuration +Pre-Installation Configuration ********************************************* Before installing SQreamDB, it is recommended that you to tune your system for better performance and stability. @@ -90,127 +90,108 @@ Installing the Operating System Before You Begin ------------------- -* Your system must have at least 200 gigabytes of free space on the root directory. +* Your system must have at least 200 gigabytes of free space on the root ``/`` mount. -* You must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. +* For a multi-node cluster, you must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. -* Once the BIOS settings have been set, you must install the operating system. Either CentOS 7.9 or RHEL 7.9-8.8 must be installed before installing the SQreamDB database, by either the customer or a SQreamDB representative. +* Once the BIOS settings have been set, you must install the operating system. -* Verify the exact RHEL7/RHEL8 version with Storage vendor to avoid driver incompatibility. +* A typical SQreamDB installation requires RHEL7.9/CentOS 7.9 or RHEL8.X (RHEL8.8 recommended) -**To install the operating system:** +* Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. + +Installation +---------------- #. Select a language (English recommended). #. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. -#. Continue the installation. -#. Set up the necessary drives and users as per the installation process. - - Using Debugging Tools is recommended for future problem-solving if necessary. -Selecting the **Development Tools** group installs the following tools: + Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign - * autoconf - * automake - * binutils - * bison - * flex - * gcc - * gcc-c++ - * gettext - * libtool - * make - * patch - * pkgconfig - * redhat-rpm-config - * rpm-build - * rpm-sign +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. -The root user is created and the OS shell is booted up. + The OS shell is booted up. Configuring the Operating System -=================================================== - -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. - -Logging In to the Server --------------------------------- +================================== -You can log in to the server using the server's IP address and password for the **root** user. The server's IP address and **root** user were created during the installation of the operating system. +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. -Automatically Creating a ``sqream`` User ------------------------------------------- +Creating a ``sqream`` User +---------------------------- -#. If a ``sqream`` user was created during installation, verify that the same ID is used on every server: +The ``sqream`` user must have the same UID and GID on all servers in your cluster. - .. code-block:: console +In case user IDs are not the same, and no important data resides under ``/home/sqream``, a best practice is deleting the ``sqream`` user and sqream group from both servers and create new ones with the same ID, as suggested in the following example: - $ sudo id sqream - - The ID **1000** is used on each server, as in the following example: - - .. code-block:: console +.. code-block:: console - $ uid=1000(sqream) gid=1000(sqream) groups=1000(sqream) + sudo userdel sqream + sudo rm /var/spool/mail/sqream -2. If the ID's are different, delete the ``sqream`` user and ``sqream`` group from both servers: +Before adding a user with a specific UID and GID, it is imperative to verify that these IDs do not already exist. - .. code-block:: console - - $ sudo userdel sqream +Follow these steps to create a ``sqream`` user. Keep in mind that ``1111`` is a UID example. -3. Recreate it using the same ID: +1. Verify that a ``1111`` UID does not already exists: .. code-block:: console - - $ sudo rm /var/spool/mail/sqream - -Manually Creating a ``sqream`` User ------------------------------------- - -SQreamDB enables you to manually create users. This section shows you how to manually create a user with the UID **1111**. You cannot manually create users during the operating system installation procedure. - -#. Verify that a **1111** UID does not already exists: - - .. code-block:: - $ cat /etc/passwd |grep 1111 + cat /etc/passwd |grep 1111 -#. Verify that a **1111** GID does not already exists: +2. Verify that a ``1111`` GID does not already exists: - .. code-block:: + .. code-block:: console - $ cat /etc/group |grep 1111 + cat /etc/group |grep 1111 -#. Add a user with an identical UID on all cluster nodes: +3. Add a user with an identical UID on all cluster nodes: .. code-block:: console - $ useradd -u 1111 sqream + useradd -u 1111 sqream -#. Add the user ``sqream`` to the ``wheel`` group. +4. Add the user ``sqream`` to the ``wheel`` group. .. code-block:: console - $ sudo usermod -aG wheel sqream + sudo usermod -aG wheel sqream You can remove the ``sqream`` user from the ``wheel`` group when the installation and configuration are complete: .. code-block:: console - $ passwd sqream + passwd sqream -#. Log out and log back in as ``sqream``. +5. Log out and log back in as ``sqream``. - .. note:: If you deleted the ``sqream`` user and recreated it with different ID, to avoid permission errors, you must change its ownership to ``/home/sqream``. +.. note:: If you deleted the ``sqream`` user and recreated it with different ID, to avoid permission errors, you must change its ownership to ``/home/sqream``. 6. Change the ``sqream`` user's ownership to ``/home/sqream``: .. code-block:: console - $ sudo chown -R sqream:sqream /home/sqream + sudo chown -R sqream:sqream /home/sqream Setting Up A Locale --------------------------------- +----------------------- SQreamDB enables you to set up a locale. In this example, the locale used is your own location. @@ -252,6 +233,8 @@ Installing Required Software $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm +Do not miss the below step or you will fail to install some mandatory required packages later! + **Enabling Additional Red Hat Repositories:** **RHEL7** @@ -298,7 +281,7 @@ Installing Required Software **Installing Python:** -For SQreamDb version 4.3 or older, install Python 3.6.7. +**For SQreamDb version 4.3 or older, install Python 3.6.7.** 1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: @@ -322,7 +305,7 @@ For SQreamDb version 4.3 or older, install Python 3.6.7. .. code-block:: console - $ ./configure + $ ./configure --enable-loadable-sqlite-extensions 5. Build the software: @@ -340,9 +323,9 @@ For SQreamDb version 4.3 or older, install Python 3.6.7. .. code-block:: console - $ python3 + $ python3 --version -For SQreamDB version 4.4 or newer, install Python 3.9.13. +**For SQreamDB version 4.4 or newer, install Python 3.9.13.** 1. Download the Python 3.9.13 source code tarball file from the following URL into the **/home/sqream** directory: @@ -366,7 +349,7 @@ For SQreamDB version 4.4 or newer, install Python 3.9.13. .. code-block:: console - $ ./configure + $ ./configure --enable-loadable-sqlite-extensions 5. Build the software: @@ -384,11 +367,14 @@ For SQreamDB version 4.4 or newer, install Python 3.9.13. .. code-block:: console - $ python3 + $ python3 --version Installing NodeJS on CentOS -------------------------------- +NodeJS required only In case when UI runs on the same server as SqreamDB +If not, skip this step. + 1. Download the `setup_12.x file <https://rpm.nodesource.com/setup_12.x>`__ as a root user logged in shell: .. code-block:: console @@ -458,6 +444,14 @@ Installing NodeJS Offline $ node --version +8. To install the ``pm2`` process management: + + .. code-block:: console + + sudo npm install pm2 -g + +If sudo npm install pm2 -g fails, install pm2 offline: + Installing the pm2 Service Offline ------------------------------------ @@ -488,7 +482,7 @@ Installing the pm2 Service Offline .. code-block:: console - $ cd /usr/bin again + $ cd /usr/bin 6. Create a symbolink to the ``pm2`` service: @@ -588,26 +582,26 @@ Configuring Chrony for RHEL8 Only #. Start the Chrony service: -..code-block:: +.. code-block:: console $ sudo systemctl start chronyd #. Enable the Chrony service to start automatically at boot time: -..code-block:: +.. code-block:: $ sudo systemctl enable chronyd #. Check the status of the Chrony service: -..code-block:: +.. code-block:: $ sudo systemctl status chronyd Configuring the Server to Boot Without Linux the UI ---------------------------------------------------- -You can configure your server to boot without a UI in cases when it is not required (recommended) by running the following command: +We recommend that you configure your server to boot without a Linux GUI by running the following command: .. code-block:: console @@ -620,8 +614,6 @@ Configuring the Security Limits The security limits refer to the number of open files, processes, etc. -You can configure the security limits by running the **echo -e** command as a root user logged in shell: - .. code-block:: console $ sudo bash @@ -645,7 +637,7 @@ Configuring the Kernel Parameters $ sysctl -n fs.file-max -3. If the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: +3. **Only** if the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: .. code-block:: console @@ -668,6 +660,20 @@ Configuring the Firewall The example in this section shows the open ports for four ``sqreamd`` sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. +Required ports: + +8080 - UI port +443 - UI over HTTPS ( requires nginx installation ) +3105 - SqreamDB metadataserver service +3108 - SqreamDB serverpicker service +3109 - SqreamDB serverpicker service over ssl +5000 - SqreamDB first worker default port +5100 - SqreamDB first worker over ssl default port +5001 - SqreamDB second worker default port +5101 - SqreamDB second worker over ssl default port + +Same logic applies to all additional SQreamDB Worker ports. + 1. Start the service and enable FirewallID on boot: .. code-block:: console @@ -747,29 +753,14 @@ Configuring the ``/etc/hosts`` File $ 127.0.0.1 localhost $ <server1 ip> <server_name> $ <server2 ip> <server_name> - -Configuring the DNS --------------------- - -1. Run the **ifconfig** commasnd to check your NIC name. In the following example, **eth0** is the NIC name: - - .. code-block:: console - - $ sudo vim /etc/sysconfig/network-scripts/ifcfg-eth0 - -2. Replace the DNS lines from the example above with your own DNS addresses : - - .. code-block:: console - - $ DNS1="4.4.4.4" - $ DNS2="8.8.8.8" + Installing the NVIDIA CUDA Driver ================================== After configuring your operating system, you must install the NVIDIA CUDA driver. - .. warning:: If your UI runs on the server, the server must be stopped before installing the CUDA drivers. + .. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. Before You Begin --------------------------- @@ -808,17 +799,11 @@ Updating the Kernel Headers $ uname -r $ rpm -qa |grep kernel-devel-$(uname -r) $ rpm -qa |grep kernel-headers-$(uname -r) - -2. Install **wget** one of the following operating systems: - - .. code-block:: console - - $ sudo yum install wget Disabling Nouveau ------------------ -You can disable Nouveau, which is the default operating system driver. +Disable Nouveau, which is the default operating system driver. 1. Check if the Nouveau driver has been loaded: @@ -854,7 +839,13 @@ You can disable Nouveau, which is the default operating system driver. Installing the CUDA Driver ---------------------------- -For A100 GPU and other A series GPUs, you must install the **CUDA 11.4.3 driver**. The version of the driver installed on the customer server must be equal to or higher than the one used to build the SQreamDB package. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. +For A100 GPU and other A series GPUs, you must install the **CUDA 11.4.3 driver**. + +For H100 GPU ( and other H series ) cuda minimum 11.8 should be installed! +For L40S GPU ( and other L series ) cuda minimum 12.0 should be installed! +Our current recommendation cuda 12.2.1 + +For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. .. contents:: :local: @@ -926,113 +917,19 @@ Installing the CUDA driver from the Repository is the recommended installation m $ sudo dnf clean all $ sudo dnf -y module install nvidia-driver:latest-dkms +Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 + * **IBM Power9 - CUDA 10.1 for RHEL7:** .. code-block:: console $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - - -4. Install the CUDA drivers: - - a. Clear the YUM cache: - - .. code-block:: console - - $ sudo yum clean all - - b. Install the most current DKMS (Dynamic Kernel Module Support) NVIDIA driver: - - .. code-block:: console - - $ sudo yum -y install nvidia-driver-latest-dkms - -5. Verify that the installation was successful: - - .. code-block:: console - - $ nvidia-smi - -6. Enable NVIDIA-persistenced mode: - - .. code-block:: console - - $ sudo systemctl start nvidia-persistenced - $ sudo systemctl enable nvidia-persistenced - -You can prepare the CUDA driver offline from a server connected to the CUDA repo by running the following commands as a ``root`` user: - -7. Query all the packages installed in your system, and verify that ``cuda-repo`` has been installed: - - .. code-block:: console - - $ rpm -qa |grep cuda-repo - -8. Navigate to the correct repository: - - .. code-block:: console - - $ cd /etc/yum.repos.d/ - -9. List in long format and print lines matching a pattern for the CUDA file: - - .. code-block:: console - - $ ls -l |grep cuda - - The following is an example of the correct output: - - .. code-block:: console - - $ cuda-10-1-local.repo - -10. Edit the ``/etc/yum.repos.d/cuda-10-1-local.repo`` file: - - .. code-block:: console - - $ vim /etc/yum.repos.d/cuda-10-1-local.repo - - The following is an example of the correct output: - - .. code-block:: console - - $ name=cuda-10-1-local - -11. Clone the repository to a location where it can be copied from: - - .. code-block:: console - - $ reposync -g -l -m --repoid=cuda-10-1-local --download_path=/var/cuda-repo-10.1-local - -12. Copy the repository to the installation server and create the repository: - - .. code-block:: console - - $ createrepo -g comps.xml /var/cuda-repo-10.1-local - -13. Add a repo configuration file in ``/etc/yum.repos.d/`` by editing the ``/etc/yum.repos.d/cuda-10.1-local.repo`` repository: - - .. code-block:: console - - $ [cuda-10.1-local] - $ name=cuda-10.1-local - $ baseurl=file:///var/cuda-repo-10.1-local - $ enabled=1 - $ gpgcheck=1 - $ gpgkey=file:///var/cuda-repo-10-1-local/7fa2af80.pub - -14. Install the CUDA drivers by installing the most current Dynamic Kernel Module Support (DKMS) NVIDIA driver as a root user logged in shell: - - .. code-block:: console - - $ sudo bash - $ sudo yum -y install nvidia-driver-latest-dkms -15. If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. +If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. Tuning Up NVIDIA Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The procedures in this section are relevant to Intel only. diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 989d32435..e7be1a5e4 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -18,6 +18,7 @@ This section summarizes the following operational guides: foreign_tables delete_guide logging + query_split monitoring_query_performance security saved_queries diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst new file mode 100644 index 000000000..3ef3fe130 --- /dev/null +++ b/operational_guides/query_split.rst @@ -0,0 +1,23 @@ +.. _query_split: + +**************************** +Query Split +**************************** + +The split query operation optimizes long-running queries by executing them in parallel on different GPUs, thereby reducing overall run time. It's crucial to note that not every query may benefit from this approach, as the splitting mechanism introduces some overhead runtime. Additionally, it's emphasized that splitting can only be performed in the UI, leveraging Meta-scripting, a feature currently exclusive to the UI environment. + +The four stages of using the query split operation are: + +* Creating an empty table that would hold the results of the query +* + +.. contents:: + :local: + :depth: 1 + +Syntax +======== + +.. code-block:: sql + +#Creating a table \ No newline at end of file From 940659d3bf6c935516dddb4b1434c2dd91b510f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:20:41 +0200 Subject: [PATCH 1075/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 217 +++++++----------- 1 file changed, 78 insertions(+), 139 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index af5d63239..3789b5aeb 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -938,15 +938,13 @@ The procedures in this section are relevant to Intel only. :depth: 1 To Tune Up NVIDIA Performance when Driver Installed from the Repository -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -**To tune up NVIDIA performance when the driver was installed from the repository:** +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Check the service status: .. code-block:: console - $ sudo systemctl status nvidia-persistenced + sudo systemctl status nvidia-persistenced If the service exists, it will be stopped be default. @@ -954,57 +952,48 @@ To Tune Up NVIDIA Performance when Driver Installed from the Repository .. code-block:: console - $ sudo systemctl start nvidia-persistenced + sudo systemctl start nvidia-persistenced 3. Verify that no errors have occurred: .. code-block:: console - $ sudo systemctl status nvidia-persistenced + sudo systemctl status nvidia-persistenced 4. Enable the service to start up on boot: .. code-block:: console - $ sudo systemctl enable nvidia-persistenced + sudo systemctl enable nvidia-persistenced 5. For **H100/A100**, add the following lines: .. code-block:: console - $ nvidia-persistenced - - .. note:: The following are mandatory for IBM: - - .. code-block:: console - - $ sudo systemctl start nvidia-persistenced - $ sudo systemctl enable nvidia-persistenced + nvidia-persistenced 6. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: .. code-block:: console - $ nvidia-smi + nvidia-smi .. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. To Tune Up NVIDIA Performance when Driver Installed from the Runfile -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -**To tune up NVIDIA performance when the driver was installed from the runfile:** - -1. Change the permissions on the **rc.local** file to **executable**: +1. Change the permissions on the ``rc.local`` file to ``executable``: .. code-block:: console - $ sudo chmod +x /etc/rc.local + sudo chmod +x /etc/rc.local -2. Edit the **/etc/yum.repos.d/cuda-10-1-local.repo** file: +2. Edit the ``/etc/yum.repos.d/cuda-10-1-local.repo`` file: .. code-block:: console - $ sudo vim /etc/rc.local + sudo vim /etc/rc.local 3. Add the following lines: @@ -1012,96 +1001,37 @@ To Tune Up NVIDIA Performance when Driver Installed from the Runfile .. code-block:: console - $ nvidia-persistenced + nvidia-persistenced * **For IBM (mandatory)**: .. code-block:: console - $ sudo systemctl start nvidia-persistenced - $ sudo systemctl enable nvidia-persistenced + sudo systemctl start nvidia-persistenced + sudo systemctl enable nvidia-persistenced * **For K80**: .. code-block:: console - $ nvidia-persistenced - $ nvidia-smi -pm 1 - $ nvidia-smi -acp 0 - $ nvidia-smi --auto-boost-permission=0 - $ nvidia-smi --auto-boost-default=0 + nvidia-persistenced + nvidia-smi -pm 1 + nvidia-smi -acp 0 + nvidia-smi --auto-boost-permission=0 + nvidia-smi --auto-boost-default=0 -4. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: +4. Reboot the server and run the ``NVIDIA System Management Interface (NVIDIA SMI)``: .. code-block:: console - $ nvidia-smi + nvidia-smi .. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. - -Disabling Automatic Bug Reporting Tools -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -**To disable automatic bug reporting tools:** - -1. Run the following **abort** commands: - - .. code-block:: console - - $ for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - -The server is ready for the SQream software installation. - -2. Run the following checks: - - a. Check the OS release: - - .. code-block:: console - - $ cat /etc/os-release - - b. Verify that a SQream user exists and has the same ID on all cluster member services: - - .. code-block:: console - - $ id sqream - - c. Verify that the storage is mounted: - - .. code-block:: console - - $ mount - - d. Verify that the driver has been installed correctly: - - .. code-block:: console - - $ nvidia-smi - - e. Check the maximum value of the **fs.file**: - - .. code-block:: console - - $ sysctl -n fs.file-max - - f. Run the following command as a SQream user: - - .. code-block:: console - - $ ulimit -c -u -n - - The following shows the desired output: - - .. code-block:: console - - $ core file size (blocks, -c) unlimited - $ max user processes (-u) 1000000 - $ open files (-n) 1000000 - + Enabling Core Dumps ==================== -After installing the NVIDIA CUDA driver, you can enable your core dumps. While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB to be able to analyze your core dumps, they must be ``gdb`` compatible. +While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB support to be able to analyze your core dumps, they must be ``gdb`` compatible. .. contents:: :local: @@ -1120,12 +1050,7 @@ Checking the ``abrtd`` Status .. code-block:: console - $ sudo service abrtd stop - $ sudo chkconfig abrt-ccpp off - $ sudo chkconfig abrt-oops off - $ sudo chkconfig abrt-vmcore off - $ sudo chkconfig abrt-xorg off - $ sudo chkconfig abrtd off + for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done Setting the Limits -------------------- @@ -1145,7 +1070,7 @@ Setting the Limits 3. To apply the limit changes, log out and log back in. -Creating the Core Dumps Directory +Creating the Core Dump Directory ----------------------------------- Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the ``/tmp/core_dumps`` directory. If necessary, replace path according to your own environment and disk space. @@ -1154,55 +1079,55 @@ Because the core dump file may be the size of total RAM on the server, verify th .. code-block:: console - $ mkdir /tmp/core_dumps + mkdir /tmp/core_dumps 2. Set the ownership of the ``/tmp/core_dumps`` directory: .. code-block:: console - $ sudo chown sqream.sqream /tmp/core_dumps + sudo chown sqream.sqream /tmp/core_dumps 3. Grant read, write, and execute permissions to all users: .. code-block:: console - $ sudo chmod -R 777 /tmp/core_dumps + sudo chmod -R 777 /tmp/core_dumps -Setting the Output Directory of the ``/etc/sysctl.conf`` File +Setting the Output Directory on the ``/etc/sysctl.conf`` File ------------------------------------------------------------- 1. Open the ``/etc/sysctl.conf`` file in the Vim text editor: .. code-block:: console - $ sudo vim /etc/sysctl.conf + sudo vim /etc/sysctl.conf 2. Add the following to the bottom of the file: .. code-block:: console - $ kernel.core_uses_pid = 1 - $ kernel.core_pattern = /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - $ fs.suid_dumpable = 2 + kernel.core_uses_pid = 1 + kernel.core_pattern = /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + fs.suid_dumpable = 2 3. To apply the changes without rebooting the server, run the following: .. code-block:: console - $ sudo sysctl -p + sudo sysctl -p 4. Check that the core output directory points to the following: .. code-block:: console - $ sudo cat /proc/sys/kernel/core_pattern + sudo cat /proc/sys/kernel/core_pattern The following shows the correct generated output: .. code-block:: console - $ /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t Verifying that the Core Dumps Work --------------------------------------------------- @@ -1217,28 +1142,45 @@ You can verify that the core dumps work only after installing and running SQream .. code-block:: console - $ select abort_server(); + select abort_server(); -Verify Your SQreamDb Installation +Verify Your SQreamDB Installation ------------------------------------ -.. code-block:: console +1. Verify that the ``sqream`` user exists and has the same ID on all cluster servers. - cat /etc/os-release #check OS release + .. code-block:: console - id sqream #make sure sqream user exists and has same id on all cluster members servers. + id sqream - mount #please verify that the storage is mounted +2. please verify that the storage is mounted on all cluster servers. - nvidia-smi #make sure driver is insalled properly + .. code-block:: console - sysctl -n fs.file-max #should be more or equalto 2097152 + mount - ulimit -c -u -n (run this command as user sqream) - Desired output: - core file size (blocks, -c) unlimited - max user processes (-u) 1000000 - open files (-n) 1000000 +3. make sure that the driver is properly installed. + + .. code-block:: console + + nvidia-smi + +4. Verify that the kernel file-handles allocation is greater than or equal to ``2097152``: + + .. code-block:: console + + sysctl -n fs.file-max + +5. Verify limits (run this command as a ``sqream`` user): + + .. code-block:: console + + ulimit -c -u -n + + Desired output: + core file size (blocks, -c) unlimited + max user processes (-u) 1000000 + open files (-n) 1000000 Troubleshooting Core Dumping ------------------------------ @@ -1253,32 +1195,31 @@ This section describes the troubleshooting procedure to be followed if all param .. code-block:: console - $ sudo chmod -R 777 /tmp/core_dumps + sudo chmod -R 777 /tmp/core_dumps 3. Verify that the limits have been set correctly: .. code-block:: console - $ ulimit -c + ulimit -c If all parameters have been configured correctly, the correct output is: .. code-block:: console - $ core file size (blocks, -c) unlimited - $ open files (-n) 1000000 + core file size (blocks, -c) unlimited 4. If all parameters have been configured correctly, but running ``ulimit -c`` outputs ``0``, run the following: .. code-block:: console - $ sudo vim /etc/profile + sudo vim /etc/profile -5. Search for line and tag it with the ``hash`` symbol: +5. Search for the following line and disable it using the ``#`` symbol: .. code-block:: console - $ ulimit -S -c 0 > /dev/null 2>&1 + ulimit -S -c 0 > /dev/null 2>&1 6. Log out and log back in. @@ -1288,20 +1229,18 @@ This section describes the troubleshooting procedure to be followed if all param .. code-block:: console - $ ulimit -c command + ulimit -a -8. If the line is not found in ``/etc/profile`` directory, do the following: +8. If the line is not found in ``/etc/profile``, do the following: a. Run the following command: .. code-block:: console - $ sudo vim /etc/init.d/functions + sudo vim /etc/init.d/functions - b. Search for the following: + b. Search for the following line disable it using the ``#`` symbol and reboot the server. .. code-block:: console - $ ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 - - c. If the line is found, tag it with the ``hash`` symbol and reboot the server. + ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 From 17ce8fe63cb4852bd60ff168a51b7bf8e3595ae7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Dec 2023 15:38:49 +0200 Subject: [PATCH 1076/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 276 +++++++++--------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 3789b5aeb..d8c92d65f 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -141,10 +141,10 @@ The ``sqream`` user must have the same UID and GID on all servers in your cluste In case user IDs are not the same, and no important data resides under ``/home/sqream``, a best practice is deleting the ``sqream`` user and sqream group from both servers and create new ones with the same ID, as suggested in the following example: -.. code-block:: console + .. code-block:: console - sudo userdel sqream - sudo rm /var/spool/mail/sqream + sudo userdel sqream + sudo rm /var/spool/mail/sqream Before adding a user with a specific UID and GID, it is imperative to verify that these IDs do not already exist. @@ -199,13 +199,13 @@ SQreamDB enables you to set up a locale. In this example, the locale used is you .. code-block:: console - $ sudo localectl set-locale LANG=en_US.UTF-8 + sudo localectl set-locale LANG=en_US.UTF-8 2. Set the time stamp (time and date) of the locale: .. code-block:: console - $ sudo timedatectl set-timezone Asia/Jerusalem + sudo timedatectl set-timezone Asia/Jerusalem If needed, you can run the ``timedatectl list-timezones`` command to see your current time-zone. @@ -217,21 +217,21 @@ Installing Required Software **CentOS7/RHEL8** -.. code-block:: console + .. code-block:: console - $ sudo yum install epel-release + sudo yum install epel-release **RHEL7** -.. code-block:: console + .. code-block:: console - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm **RHEL8** -.. code-block:: console + .. code-block:: console - $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm Do not miss the below step or you will fail to install some mandatory required packages later! @@ -239,45 +239,45 @@ Do not miss the below step or you will fail to install some mandatory required p **RHEL7** -.. code-block:: console + .. code-block:: console - $ sudo subscription-manager repos --enable rhel-7-server-optional-rpms + sudo subscription-manager repos --enable rhel-7-server-optional-rpms **RHEL8** -.. code-block:: console + .. code-block:: console - $ sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms - $ sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms - $ sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms + sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms + sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms + sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms **Installing Required Packages:** **RHEL7/CentOS7** -.. code-block:: console + .. code-block:: console - $ sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel + sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel **RHEL8** -.. code-block:: console + .. code-block:: console - $ sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo + sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo **Installing Recommended Tools:** **RHEL7/CentOS7** -.. code-block:: console + .. code-block:: console - $ sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix **RHEL8** -.. code-block:: console + .. code-block:: console - $ sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix + sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix **Installing Python:** @@ -287,43 +287,43 @@ Do not miss the below step or you will fail to install some mandatory required p .. code-block:: console - $ wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz + wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz 2. Extract the Python 3.6.7 source code into your current directory: .. code-block:: console - $ tar -xf Python-3.6.7.tar.xz + tar -xf Python-3.6.7.tar.xz 3. Navigate to the Python 3.6.7 directory: .. code-block:: console - $ cd Python-3.6.7 + cd Python-3.6.7 4. Run the **./configure** script: .. code-block:: console - $ ./configure --enable-loadable-sqlite-extensions + ./configure --enable-loadable-sqlite-extensions 5. Build the software: .. code-block:: console - $ make -j30 + make -j30 6. Install the software: .. code-block:: console - $ sudo make install + sudo make install 7. Verify that Python 3.6.7 has been installed: .. code-block:: console - $ python3 --version + python3 --version **For SQreamDB version 4.4 or newer, install Python 3.9.13.** @@ -331,43 +331,43 @@ Do not miss the below step or you will fail to install some mandatory required p .. code-block:: console - $ wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz + wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz 2. Extract the Python 3.9.13 source code into your current directory: .. code-block:: console - $ tar -xf Python-3.9.13.tar.xz + tar -xf Python-3.9.13.tar.xz 3. Navigate to the Python 3.9.13 directory: .. code-block:: console - $ cd Python-3.9.13 + cd Python-3.9.13 4. Run the **./configure** script: .. code-block:: console - $ ./configure --enable-loadable-sqlite-extensions + ./configure --enable-loadable-sqlite-extensions 5. Build the software: .. code-block:: console - $ make -j30 + make -j30 6. Install the software: .. code-block:: console - $ sudo make install + sudo make install 7. Verify that Python 3.9.13 has been installed: .. code-block:: console - $ python3 --version + python3 --version Installing NodeJS on CentOS -------------------------------- @@ -379,25 +379,25 @@ If not, skip this step. .. code-block:: console - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - 2. Clear the YUM cache and update the local metadata: .. code-block:: console - $ sudo yum clean all && sudo yum makecache fast + sudo yum clean all && sudo yum makecache fast 3. Install the **node.js** file: .. code-block:: console - $ sudo yum install -y nodejs + sudo yum install -y nodejs 4. Install npm and make it available for all users: .. code-block:: console - $ sudo npm install pm2 -g + sudo npm install pm2 -g Installing NodeJS Offline ------------------------------- @@ -406,49 +406,49 @@ Installing NodeJS Offline .. code-block:: console - $ wget https://nodejs.org/dist/latest-v14.x/node-v14.21.3-linux-x64.tar.xz + wget https://nodejs.org/dist/latest-v14.x/node-v14.21.3-linux-x64.tar.xz 2. Move the node-v14.21.3-linux-x64 file to the */usr/local* directory. .. code-block:: console - $ sudo mv node-v14.21.3-linux-x64 /usr/local + sudo mv node-v14.21.3-linux-x64 /usr/local 3. Navigate to the */usr/bin/* directory: .. code-block:: console - $ cd /usr/bin + cd /usr/bin 4. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/node node* directory: .. code-block:: console - $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/node node + sudo ln -s ../local/node-v14.21.3-linux-x64/bin/node node 5. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npm npm* directory: .. code-block:: console - $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm + sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm 6. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npx npx* directory: .. code-block:: console - $ sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx + sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx 7. Verify that the node versions for the above are correct: .. code-block:: console - $ node --version + node --version 8. To install the ``pm2`` process management: .. code-block:: console - sudo npm install pm2 -g + sudo npm install pm2 -g If sudo npm install pm2 -g fails, install pm2 offline: @@ -465,8 +465,8 @@ Installing the pm2 Service Offline .. code-block:: console - $ cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules - $ tar -czvf pm2_x86.tar.gz pm2 + cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules + tar -czvf pm2_x86.tar.gz pm2 3. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. @@ -476,25 +476,25 @@ Installing the pm2 Service Offline .. code-block:: console - $ sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules + sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules 5. Navigate back to the ``/usr/bin`` directory: .. code-block:: console - $ cd /usr/bin + cd /usr/bin 6. Create a symbolink to the ``pm2`` service: .. code-block:: console - $ sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 7. Verify that installation was successful: .. code-block:: console - $ pm2 list + pm2 list .. note:: The following step must be done as a ``sqream`` user, and not as a ``sudo`` user. @@ -502,7 +502,7 @@ Installing the pm2 Service Offline .. code-block:: console - $ node -v + node -v Configuring the Network Time Protocol -------------------------------------- @@ -513,25 +513,25 @@ This Network Time Protocol (NTP) configuration is intended for use on systems ru .. code-block:: console - $ sudo yum install ntp + sudo yum install ntp 2. Enable the **ntpd** program. .. code-block:: console - $ sudo systemctl enable ntpd + sudo systemctl enable ntpd 3. Start the **ntdp** program. .. code-block:: console - $ sudo systemctl start ntpd + sudo systemctl start ntpd 4. Print a list of peers known to the server and a summary of their states. .. code-block:: console - $ sudo ntpq -p + sudo ntpq -p If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. @@ -544,25 +544,25 @@ If your organization has a Network Time Protocol (NTP) server, configure it by a .. code-block:: console - $ echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf + echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf 2. Restart the service: .. code-block:: console - $ sudo systemctl restart ntpd + sudo systemctl restart ntpd 3. Check that synchronization is enabled: .. code-block:: console - $ sudo timedatectl + sudo timedatectl Checking that synchronization is enabled generates the following output: .. code-block:: console - $ Local time: Sat 2019-10-12 17:26:13 EDT + Local time: Sat 2019-10-12 17:26:13 EDT Universal time: Sat 2019-10-12 21:26:13 UTC RTC time: Sat 2019-10-12 21:26:13 Time zone: America/New_York (EDT, -0400) @@ -582,30 +582,30 @@ Configuring Chrony for RHEL8 Only #. Start the Chrony service: -.. code-block:: console + .. code-block:: console - $ sudo systemctl start chronyd + sudo systemctl start chronyd #. Enable the Chrony service to start automatically at boot time: -.. code-block:: + .. code-block:: - $ sudo systemctl enable chronyd + sudo systemctl enable chronyd #. Check the status of the Chrony service: -.. code-block:: + .. code-block:: - $ sudo systemctl status chronyd + sudo systemctl status chronyd Configuring the Server to Boot Without Linux the UI ---------------------------------------------------- We recommend that you configure your server to boot without a Linux GUI by running the following command: -.. code-block:: console + .. code-block:: console - $ sudo systemctl set-default multi-user.target + sudo systemctl set-default multi-user.target Running this command activates the **NO-UI** server mode. @@ -614,13 +614,13 @@ Configuring the Security Limits The security limits refer to the number of open files, processes, etc. -.. code-block:: console + .. code-block:: console - $ sudo bash + sudo bash -.. code-block:: console + .. code-block:: console - $ echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nroot soft nproc 1000000\nroot hard nproc 1000000\nroot soft nofile 1000000\nroot hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nroot soft nproc 1000000\nroot hard nproc 1000000\nroot soft nofile 1000000\nroot hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf Configuring the Kernel Parameters --------------------------------- @@ -629,31 +629,31 @@ Configuring the Kernel Parameters .. code-block:: console - $ echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf 2. Check the maximum value of the ``fs.file``. .. code-block:: console - $ sysctl -n fs.file-max + sysctl -n fs.file-max 3. **Only** if the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: .. code-block:: console - $ echo "fs.file-max=2097152" >> /etc/sysctl.conf + echo "fs.file-max=2097152" >> /etc/sysctl.conf 4. Run the following command: .. code-block:: console - $ sudo echo “net.ipv4.ip_forward = 1” >> /etc/sysctl.conf + sudo echo “net.ipv4.ip_forward = 1” >> /etc/sysctl.conf 5. Reboot your system: .. code-block:: console - $ sudo reboot + sudo reboot Configuring the Firewall -------------------------- @@ -678,37 +678,37 @@ Same logic applies to all additional SQreamDB Worker ports. .. code-block:: console - $ systemctl start firewalld + systemctl start firewalld 2. Add the following ports to the permanent firewall: .. code-block:: console - $ firewall-cmd --zone=public --permanent --add-port=8080/tcp - $ firewall-cmd --zone=public --permanent --add-port=3105/tcp - $ firewall-cmd --zone=public --permanent --add-port=3108/tcp - $ firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp - $ firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp - $ firewall-cmd --permanent --list-all + firewall-cmd --zone=public --permanent --add-port=8080/tcp + firewall-cmd --zone=public --permanent --add-port=3105/tcp + firewall-cmd --zone=public --permanent --add-port=3108/tcp + firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + firewall-cmd --permanent --list-all 3. Reload the firewall: .. code-block:: console - $ firewall-cmd --reload + firewall-cmd --reload 4. Enable FirewallID on boot: .. code-block:: console - $ systemctl enable firewalld + systemctl enable firewalld If you do not need the firewall, you can disable it: .. code-block:: console - $ sudo systemctl stop firewalld - $ sudo systemctl disable firewalld + sudo systemctl stop firewalld + sudo systemctl disable firewalld Disabling SELinux ------------------- @@ -719,13 +719,13 @@ Disabling SELinux is a recommended action. .. code-block:: console - $ sudo sestatus + sudo sestatus 2. If the output is not ``disabled``, edit the ``/etc/selinux/config`` file: .. code-block:: console - $ sudo vim /etc/selinux/config + sudo vim /etc/selinux/config 3. Change ``SELINUX=enforcing`` to ``SELINUX=disabled``: @@ -735,7 +735,7 @@ Disabling SELinux is a recommended action. .. code-block:: console - $ sudo setenforce 0 + sudo setenforce 0 Configuring the ``/etc/hosts`` File ------------------------------------ @@ -744,15 +744,15 @@ Configuring the ``/etc/hosts`` File .. code-block:: console - $ sudo vim /etc/hosts + sudo vim /etc/hosts 2. Call your local host: .. code-block:: console - $ 127.0.0.1 localhost - $ <server1 ip> <server_name> - $ <server2 ip> <server_name> + 127.0.0.1 localhost + <server1 ip> <server_name> + <server2 ip> <server_name> Installing the NVIDIA CUDA Driver @@ -769,36 +769,36 @@ Before You Begin .. code-block:: console - $ lspci | grep -i nvidia + lspci | grep -i nvidia 2. Verify that ``gcc`` has been installed: .. code-block:: console - $ gcc --version + gcc --version 3. If ``gcc`` has not been installed, install it for RHEL or CentOS: - .. code-block:: console + .. code-block:: console - $ sudo yum install -y gcc + sudo yum install -y gcc Updating the Kernel Headers ----------------------------- 1. Update the kernel headers on RHEL or CentOS: - .. code-block:: console + .. code-block:: console - $ sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) 2. Make sure kernel-devel and kernel-headers match installed kernel: - .. code-block:: console + .. code-block:: console - $ uname -r - $ rpm -qa |grep kernel-devel-$(uname -r) - $ rpm -qa |grep kernel-headers-$(uname -r) + uname -r + rpm -qa |grep kernel-devel-$(uname -r) + rpm -qa |grep kernel-headers-$(uname -r) Disabling Nouveau ------------------ @@ -809,7 +809,7 @@ Disable Nouveau, which is the default operating system driver. .. code-block:: console - $ lsmod | grep nouveau + lsmod | grep nouveau If the Nouveau driver has been loaded, the command above generates output. If the Nouveau driver has not been loaded, you may skip step 2 and 3. @@ -817,10 +817,10 @@ Disable Nouveau, which is the default operating system driver. .. code-block:: console - $ cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf - blacklist nouveau - options nouveau modeset=0 - EOF + cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf + blacklist nouveau + options nouveau modeset=0 + EOF 3. Regenerate the kernel ``initramfs`` directory set: @@ -828,13 +828,13 @@ Disable Nouveau, which is the default operating system driver. .. code-block:: console - $ sudo dracut --force + sudo dracut --force b. Reboot the server: .. code-block:: console - $ sudo reboot + sudo reboot Installing the CUDA Driver ---------------------------- @@ -862,25 +862,25 @@ Installing the CUDA driver from the Repository is the recommended installation m .. code-block:: console - $ sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm * For RHEL8: .. code-block:: console - $ sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm * For CentOS: .. code-block:: console - $ sudo yum install epel-release + sudo yum install epel-release 2. (Optional) Install the CUDA dependencies from the ``epel`` repository: .. code-block:: console - $ sudo yum install dkms libvdpau + sudo yum install dkms libvdpau Installing the CUDA depedendencies from the ``epel`` repository is only required for installing ``runfile``. @@ -890,32 +890,32 @@ Installing the CUDA driver from the Repository is the recommended installation m .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - $ sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm .. code-block:: console - $ sudo yum clean all - $ sudo yum -y install nvidia-driver-latest-dkms + sudo yum clean all + sudo yum -y install nvidia-driver-latest-dkms * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - $ sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm - $ sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm .. code-block:: console - $ sudo dnf clean all - $ sudo dnf -y module install nvidia-driver:latest-dkms + sudo dnf clean all + sudo dnf -y module install nvidia-driver:latest-dkms Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 @@ -923,8 +923,8 @@ Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 .. code-block:: console - $ wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - $ sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. @@ -1044,7 +1044,7 @@ Checking the ``abrtd`` Status .. code-block:: console - $ sudo ps -ef |grep abrt + sudo ps -ef |grep abrt 2. If **abrtd** is running, stop it: @@ -1059,14 +1059,14 @@ Setting the Limits .. code-block:: console - $ ulimit -c + ulimit -c 2. If the output is ``0``, add the following lines to the ``/etc/security/limits.conf`` file: .. code-block:: console - $ * soft core unlimited - $ * hard core unlimited + * soft core unlimited + * hard core unlimited 3. To apply the limit changes, log out and log back in. From e0e6c15918e9122d29d9411a2c9071c500d51f19 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Dec 2023 17:45:18 +0200 Subject: [PATCH 1077/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 249 ++++++++---------- 1 file changed, 114 insertions(+), 135 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index d8c92d65f..caa61e54e 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -137,18 +137,18 @@ When configuring the operating system, several basic settings related to creatin Creating a ``sqream`` User ---------------------------- -The ``sqream`` user must have the same UID and GID on all servers in your cluster. +**The sqream user must have the same UID and GID across all servers in your cluster.** -In case user IDs are not the same, and no important data resides under ``/home/sqream``, a best practice is deleting the ``sqream`` user and sqream group from both servers and create new ones with the same ID, as suggested in the following example: +If the ``sqream`` user does not have the same UID and GID across all servers and there is no critical data stored under ``/home/sqream``, it is recommended to delete the ``sqream`` user and sqream group from your servers. Subsequently, create new ones with the same ID, using the following command: .. code-block:: console sudo userdel sqream sudo rm /var/spool/mail/sqream -Before adding a user with a specific UID and GID, it is imperative to verify that these IDs do not already exist. +Before adding a user with a specific UID and GID, it is crucial to verify that such Ids do not already exist. -Follow these steps to create a ``sqream`` user. Keep in mind that ``1111`` is a UID example. +The steps below guide you on creating a ``sqream`` user with an exemplary ID of ``1111``. 1. Verify that a ``1111`` UID does not already exists: @@ -168,7 +168,7 @@ Follow these steps to create a ``sqream`` user. Keep in mind that ``1111`` is a useradd -u 1111 sqream -4. Add the user ``sqream`` to the ``wheel`` group. +4. Add a ``sqream`` user to the ``wheel`` group. .. code-block:: console @@ -182,9 +182,7 @@ Follow these steps to create a ``sqream`` user. Keep in mind that ``1111`` is a 5. Log out and log back in as ``sqream``. -.. note:: If you deleted the ``sqream`` user and recreated it with different ID, to avoid permission errors, you must change its ownership to ``/home/sqream``. - -6. Change the ``sqream`` user's ownership to ``/home/sqream``: +6. If you deleted the ``sqream`` user and recreated it to have a new ID, you must change its ownership to ``/home/sqream`` in order to avoid permission errors. .. code-block:: console @@ -193,7 +191,7 @@ Follow these steps to create a ``sqream`` user. Keep in mind that ``1111`` is a Setting Up A Locale ----------------------- -SQreamDB enables you to set up a locale. In this example, the locale used is your own location. +SQreamDB enables you to set up a locale using your own location. To find out your current time-zone, run the ``timedatectl list-timezones`` command. 1. Set the language of the locale: @@ -206,14 +204,16 @@ SQreamDB enables you to set up a locale. In this example, the locale used is you .. code-block:: console sudo timedatectl set-timezone Asia/Jerusalem - -If needed, you can run the ``timedatectl list-timezones`` command to see your current time-zone. - Installing Required Software --------------------------------- - -**Installing EPEL Repository:** + +.. contents:: + :local: + :depth: 1 + +Installing EPEL Repository +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **CentOS7/RHEL8** @@ -233,9 +233,10 @@ Installing Required Software sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm -Do not miss the below step or you will fail to install some mandatory required packages later! +Enabling Additional Red Hat Repositories +""""""""""""""""""""""""""""""""""""""""" -**Enabling Additional Red Hat Repositories:** +Enabling additional Red Hat repositories is essential to install the required packages in the subsequent procedures. **RHEL7** @@ -251,7 +252,8 @@ Do not miss the below step or you will fail to install some mandatory required p sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms -**Installing Required Packages:** +Installing Required Packages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **RHEL7/CentOS7** @@ -265,7 +267,8 @@ Do not miss the below step or you will fail to install some mandatory required p sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo -**Installing Recommended Tools:** +Installing Recommended Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ **RHEL7/CentOS7** @@ -279,11 +282,12 @@ Do not miss the below step or you will fail to install some mandatory required p sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix -**Installing Python:** +Installing Python +^^^^^^^^^^^^^^^^^^^ **For SQreamDb version 4.3 or older, install Python 3.6.7.** -1. Download the Python 3.6.7 source code tarball file from the following URL into the **/home/sqream** directory: +1. Download the Python 3.6.7 source code tarball file from the following URL into the ``/home/sqream`` directory: .. code-block:: console @@ -301,7 +305,7 @@ Do not miss the below step or you will fail to install some mandatory required p cd Python-3.6.7 -4. Run the **./configure** script: +4. Run the ``./configure`` script: .. code-block:: console @@ -327,7 +331,7 @@ Do not miss the below step or you will fail to install some mandatory required p **For SQreamDB version 4.4 or newer, install Python 3.9.13.** -1. Download the Python 3.9.13 source code tarball file from the following URL into the **/home/sqream** directory: +1. Download the Python 3.9.13 source code tarball file from the following URL into the ``/home/sqream`` directory: .. code-block:: console @@ -345,7 +349,7 @@ Do not miss the below step or you will fail to install some mandatory required p cd Python-3.9.13 -4. Run the **./configure** script: +4. Run the ``./configure`` script: .. code-block:: console @@ -369,40 +373,12 @@ Do not miss the below step or you will fail to install some mandatory required p python3 --version -Installing NodeJS on CentOS --------------------------------- +Installing NodeJS +^^^^^^^^^^^^^^^^^^ -NodeJS required only In case when UI runs on the same server as SqreamDB -If not, skip this step. +NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not, you can skip this step. -1. Download the `setup_12.x file <https://rpm.nodesource.com/setup_12.x>`__ as a root user logged in shell: - - .. code-block:: console - - curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - -2. Clear the YUM cache and update the local metadata: - - .. code-block:: console - - sudo yum clean all && sudo yum makecache fast - -3. Install the **node.js** file: - - .. code-block:: console - - sudo yum install -y nodejs - -4. Install npm and make it available for all users: - - .. code-block:: console - - sudo npm install pm2 -g - -Installing NodeJS Offline -------------------------------- - -1. Download the NodeJS source code tarball file from the following URL into the **/home/sqream** directory: +1. Download the NodeJS source code tarball file from the following URL into the ``/home/sqream`` directory: .. code-block:: console @@ -412,102 +388,93 @@ Installing NodeJS Offline .. code-block:: console - sudo mv node-v14.21.3-linux-x64 /usr/local - -3. Navigate to the */usr/bin/* directory: + sudo mv node-v14.21.3-linux-x64 /usr/local + +3. Navigate to the ``/usr/bin/`` directory: .. code-block:: console - cd /usr/bin + cd /usr/bin -4. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/node node* directory: +4. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/node node`` directory: .. code-block:: console sudo ln -s ../local/node-v14.21.3-linux-x64/bin/node node -5. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npm npm* directory: +5. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/npm npm`` directory: .. code-block:: console - sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm + sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm -6. Create a symbolic link to the */local/node-v14.21.3-linux-x64/bin/npx npx* directory: - - .. code-block:: console - - sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx - -7. Verify that the node versions for the above are correct: +6. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/npx npx`` directory: .. code-block:: console - node --version + sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx -8. To install the ``pm2`` process management: +7. Install the ``pm2`` process management: .. code-block:: console sudo npm install pm2 -g - -If sudo npm install pm2 -g fails, install pm2 offline: - -Installing the pm2 Service Offline ------------------------------------- - -1. On a machine with internet access, install the following: + +8. If installing the ``pm2`` process management fails, install it offline: + + a. On a machine with internet access, install the following: * nodejs * npm * pm2 + + b. Extract the pm2 module to the correct directory: -2. Extract the pm2 module to the correct directory: - - .. code-block:: console - - cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules - tar -czvf pm2_x86.tar.gz pm2 - -3. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. + .. code-block:: console + cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules + tar -czvf pm2_x86.tar.gz pm2 + + c. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. + :: + + d. Move the ``pm2`` folder to the ``/usr/local/node-v14.21.3-linux-x64/lib/node_modules`` directory: -4. Move the ``pm2`` folder to the ``/usr/local/node-v14.21.3-linux-x64/lib/node_modules`` directory: - - .. code-block:: console - - sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules - -5. Navigate back to the ``/usr/bin`` directory: + .. code-block:: console - .. code-block:: console + sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules - cd /usr/bin + e. Navigate back to the ``/usr/bin`` directory: -6. Create a symbolink to the ``pm2`` service: + .. code-block:: console - .. code-block:: console + cd /usr/bin - sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + f. Create a symbolink to the ``pm2`` service: -7. Verify that installation was successful: + .. code-block:: console - .. code-block:: console + sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 - pm2 list + g. Verify that installation was successful without using ``sudo``: - .. note:: The following step must be done as a ``sqream`` user, and not as a ``sudo`` user. + .. code-block:: console -8. Verify that the node version is correct: + pm2 list + + h. Verify that the node versions for the above are correct: - .. code-block:: console + .. code-block:: console - node -v + node --version Configuring the Network Time Protocol -------------------------------------- This Network Time Protocol (NTP) configuration is intended for use on systems running RHEL7 and CentOS7 exclusively. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. 1. Install the NTP file. @@ -532,8 +499,6 @@ This Network Time Protocol (NTP) configuration is intended for use on systems ru .. code-block:: console sudo ntpq -p - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. Configuring the Network Time Protocol Server -------------------------------------------- @@ -631,7 +596,7 @@ Configuring the Kernel Parameters echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf -2. Check the maximum value of the ``fs.file``. +2. Check the maximum value of the ``fs.file``: .. code-block:: console @@ -660,19 +625,32 @@ Configuring the Firewall The example in this section shows the open ports for four ``sqreamd`` sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. -Required ports: +The ports listed below are required, and the same logic applies to all additional SQreamDB Worker ports. -8080 - UI port -443 - UI over HTTPS ( requires nginx installation ) -3105 - SqreamDB metadataserver service -3108 - SqreamDB serverpicker service -3109 - SqreamDB serverpicker service over ssl -5000 - SqreamDB first worker default port -5100 - SqreamDB first worker over ssl default port -5001 - SqreamDB second worker default port -5101 - SqreamDB second worker over ssl default port - -Same logic applies to all additional SQreamDB Worker ports. +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Port + - Use + * - 8080 + - UI port + * - 443 + - UI over HTTPS ( requires nginx installation ) + * - 3105 + - SqreamDB metadataserver service + * - 3108 + - SqreamDB serverpicker service + * - 3109 + - SqreamDB serverpicker service over ssl + * - 5000 + - SqreamDB first worker default port + * - 5100 + - SqreamDB first worker over ssl default port + * - 5001 + - SqreamDB second worker default port + * - 5101 + - SqreamDB second worker over ssl default port 1. Start the service and enable FirewallID on boot: @@ -753,17 +731,16 @@ Configuring the ``/etc/hosts`` File 127.0.0.1 localhost <server1 ip> <server_name> <server2 ip> <server_name> - Installing the NVIDIA CUDA Driver ================================== After configuring your operating system, you must install the NVIDIA CUDA driver. - .. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. +.. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. Before You Begin ---------------------------- +^^^^^^^^^^^^^^^^^ 1. Verify that the NVIDIA card has been installed and is detected by the system: @@ -784,7 +761,7 @@ Before You Begin sudo yum install -y gcc Updating the Kernel Headers ------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 1. Update the kernel headers on RHEL or CentOS: @@ -801,7 +778,7 @@ Updating the Kernel Headers rpm -qa |grep kernel-headers-$(uname -r) Disabling Nouveau ------------------- +^^^^^^^^^^^^^^^^^^^ Disable Nouveau, which is the default operating system driver. @@ -839,17 +816,19 @@ Disable Nouveau, which is the default operating system driver. Installing the CUDA Driver ---------------------------- +.. contents:: + :local: + :depth: 1 + +The current recommendation is for CUDA 12.2.1. + For A100 GPU and other A series GPUs, you must install the **CUDA 11.4.3 driver**. -For H100 GPU ( and other H series ) cuda minimum 11.8 should be installed! -For L40S GPU ( and other L series ) cuda minimum 12.0 should be installed! -Our current recommendation cuda 12.2.1 +For H100 GPU and other H series GPUs, you must install the **CUDA 11.8 driver** or a later version. -For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. +For L40S GPU and other L series GPUs, you must install the **CUDA 12.0 driver** or a later version. -.. contents:: - :local: - :depth: 1 +For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Installing the CUDA Driver from the Repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -898,14 +877,14 @@ Installing the CUDA driver from the Repository is the recommended installation m sudo yum clean all sudo yum -y install nvidia-driver-latest-dkms - * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** .. code-block:: console wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console @@ -919,7 +898,7 @@ Installing the CUDA driver from the Repository is the recommended installation m Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 - * **IBM Power9 - CUDA 10.1 for RHEL7:** + * **IBM Power9 - CUDA 10.1 for RHEL7:** .. code-block:: console From 98ab461daedc048c116e3f7e1b47ec7decc57757 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Dec 2023 13:37:02 +0200 Subject: [PATCH 1078/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index caa61e54e..23b0cd02b 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -607,18 +607,6 @@ Configuring the Kernel Parameters .. code-block:: console echo "fs.file-max=2097152" >> /etc/sysctl.conf - -4. Run the following command: - - .. code-block:: console - - sudo echo “net.ipv4.ip_forward = 1” >> /etc/sysctl.conf - -5. Reboot your system: - - .. code-block:: console - - sudo reboot Configuring the Firewall -------------------------- From a26e49d2c95d1521501949bf9c5572ee5a23dbd5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 08:06:54 +0200 Subject: [PATCH 1079/1892] Update recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 23b0cd02b..827a7c9a9 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -563,7 +563,7 @@ Configuring Chrony for RHEL8 Only sudo systemctl status chronyd -Configuring the Server to Boot Without Linux the UI +Configuring the Server to Boot Without Linux GUI ---------------------------------------------------- We recommend that you configure your server to boot without a Linux GUI by running the following command: @@ -853,14 +853,14 @@ Installing the CUDA driver from the Repository is the recommended installation m 3. Download and install the required local repository: - * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - .. code-block:: console + .. code-block:: console wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - .. code-block:: console + .. code-block:: console sudo yum clean all sudo yum -y install nvidia-driver-latest-dkms @@ -898,14 +898,16 @@ If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA d Tuning Up NVIDIA Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -The procedures in this section are relevant to Intel only. +The following procedures exclusively relate to Intel. .. contents:: :local: :depth: 1 - -To Tune Up NVIDIA Performance when Driver Installed from the Repository -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. + +Tune Up NVIDIA Performance when Driver Installed from the Repository +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1. Check the service status: @@ -913,7 +915,7 @@ To Tune Up NVIDIA Performance when Driver Installed from the Repository sudo systemctl status nvidia-persistenced - If the service exists, it will be stopped be default. + If the service exists, it will be stopped by default. 2. Start the service: @@ -945,10 +947,10 @@ To Tune Up NVIDIA Performance when Driver Installed from the Repository nvidia-smi -.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. + -To Tune Up NVIDIA Performance when Driver Installed from the Runfile -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Tune Up NVIDIA Performance when Driver Installed from the Runfile +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1. Change the permissions on the ``rc.local`` file to ``executable``: @@ -993,7 +995,7 @@ To Tune Up NVIDIA Performance when Driver Installed from the Runfile nvidia-smi -.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. + Enabling Core Dumps ==================== From 53b7307b04a0cee6875cef812627625b9c8b3f22 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 10:55:53 +0200 Subject: [PATCH 1080/1892] Update query_split.rst --- operational_guides/query_split.rst | 78 ++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 3ef3fe130..75fe1a58e 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -8,8 +8,13 @@ The split query operation optimizes long-running queries by executing them in pa The four stages of using the query split operation are: -* Creating an empty table that would hold the results of the query -* +* Creating an empty table with an identical DDL of what would have been the result set table if we were to run the query we wish to split into 4 small queries. This empty table would eventually hold the results of all 4 small queries. + +* Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER`` or ``DATE`` data types, or otherwise, an Identity column. + +* Executing the query split + +* Executing a query that collects the results of all 4 small queries into our empty table. .. contents:: :local: @@ -18,6 +23,73 @@ The four stages of using the query split operation are: Syntax ======== +**Creating an empty table that is based on the query we wish to split:** + +.. code-block:: sql + + CREATE TABLE <final_result_table> AS ( + SELECT <column1> [,...] + FROM <my_table> + WHERE (<false_filter>) + ); + + #A false_filter example: (1=2) + + +**Using the @@SetResult operator to create a minMax variable:** + +The ``minMax`` variable is used to define minimum and maximum values of ``INTEGER``, ``DATE``, or Identity columns by which we can split our query. + .. code-block:: sql + + @@SetResult minMax + SELECT min(<integer_column>) AS min, max(<integer_column>) AS max FROM <my_table> + ; + +**Splitting a query using an INTEGER column:** + +Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. + +.. code-block:: sql + + @@SplitQueryByNumber instances = <number of instances>, from = minMax[0].min, to = minMax[0].max + INSERT INTO <final_result_table> + SELECT <column1> [,...] + FROM <my_table> + WHERE (<false_filter>) + ); + +**Splitting a query using a DATE column:** + +Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. + +.. code-block:: sql + + @@SplitQueryByDate instances = <number of instances>, from = minMax[0].min, to = minMax[0].max + INSERT INTO <final_result_table> + SELECT <column1> [,...] + FROM <my_table> + WHERE (<false_filter>) + ); + +**Outputting the results of our 4 small queries:** + +.. code-block:: sql + + ##Do not use a WHERE clause + + ###Basic execution: + + SELECT * + FROM <final_result_table> + ; + + ###Execution when there are aggregations: + + SELECT <column1>, <column2> [,...], SUM(<column4>) + FROM <my_table> + GROUP BY <column1>, <column2> [,...] + ORDER BY SUM(<column4>) + + ); -#Creating a table \ No newline at end of file From 3fa20e2b127501382a9698703c538fff59df3aab Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:22:46 +0200 Subject: [PATCH 1081/1892] Update query_split.rst --- operational_guides/query_split.rst | 42 ++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 75fe1a58e..5b628efe7 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -10,7 +10,7 @@ The four stages of using the query split operation are: * Creating an empty table with an identical DDL of what would have been the result set table if we were to run the query we wish to split into 4 small queries. This empty table would eventually hold the results of all 4 small queries. -* Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER`` or ``DATE`` data types, or otherwise, an Identity column. +* Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER``, ``DATE``, or ``DATETIME`` data types, or otherwise, an Identity column. * Executing the query split @@ -28,7 +28,7 @@ Syntax .. code-block:: sql CREATE TABLE <final_result_table> AS ( - SELECT <column1> [,...] + SELECT <column_to_split_by> [,...] FROM <my_table> WHERE (<false_filter>) ); @@ -38,12 +38,14 @@ Syntax **Using the @@SetResult operator to create a minMax variable:** -The ``minMax`` variable is used to define minimum and maximum values of ``INTEGER``, ``DATE``, or Identity columns by which we can split our query. +The ``minMax`` variable is used to define minimum and maximum values of ``INTEGER``, ``DATE``, ``DATETIME`` or Identity columns by which we can split our query. .. code-block:: sql @@SetResult minMax - SELECT min(<integer_column>) AS min, max(<integer_column>) AS max FROM <my_table> + SELECT min(<integer_column>) AS min, max(<integer_column>) AS max + FROM <my_table> + [WHERE <condition>] ; **Splitting a query using an INTEGER column:** @@ -54,9 +56,9 @@ Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. @@SplitQueryByNumber instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> - SELECT <column1> [,...] + SELECT <column_to_split_by> [,...] FROM <my_table> - WHERE (<false_filter>) + WHERE <column_to_split_by> between ${from} and ${to} ); **Splitting a query using a DATE column:** @@ -67,29 +69,41 @@ Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. @@SplitQueryByDate instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> - SELECT <column1> [,...] + SELECT <column_to_split_by> [,...] FROM <my_table> - WHERE (<false_filter>) + WHERE <column_to_split_by> between ${from} and ${to} + ); + +**Splitting a query using a DATETIME column:** + +Using the ``@@SplitQueryByDateTime`` operator to create an ``instances`` variable. + +.. code-block:: postgres + + @@SplitQueryByDateTime instances = <number of instances>, from = minMax[0].min, to = minMax[0].max + INSERT INTO <final_result_table> + SELECT <column_to_split_by> [,...] + FROM <my_table> + WHERE <column_to_split_by> between ${from} and ${to} ); **Outputting the results of our 4 small queries:** .. code-block:: sql - ##Do not use a WHERE clause - - ###Basic execution: + #Basic execution for queries which do not use aggregations: SELECT * FROM <final_result_table> ; - ###Execution when there are aggregations: + #Execution for queries which use aggregations: SELECT <column1>, <column2> [,...], SUM(<column4>) - FROM <my_table> + FROM <final_result_table> GROUP BY <column1>, <column2> [,...] ORDER BY SUM(<column4>) - ); + + ##Do not use a WHERE clause From 94ac51d7f016a6c4b509b7e700082ebde1645ab9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 11:38:13 +0200 Subject: [PATCH 1082/1892] Update query_split.rst --- operational_guides/query_split.rst | 45 +++++++++++++++++------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 5b628efe7..ef4b34a5e 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -4,17 +4,7 @@ Query Split **************************** -The split query operation optimizes long-running queries by executing them in parallel on different GPUs, thereby reducing overall run time. It's crucial to note that not every query may benefit from this approach, as the splitting mechanism introduces some overhead runtime. Additionally, it's emphasized that splitting can only be performed in the UI, leveraging Meta-scripting, a feature currently exclusive to the UI environment. - -The four stages of using the query split operation are: - -* Creating an empty table with an identical DDL of what would have been the result set table if we were to run the query we wish to split into 4 small queries. This empty table would eventually hold the results of all 4 small queries. - -* Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER``, ``DATE``, or ``DATETIME`` data types, or otherwise, an Identity column. - -* Executing the query split - -* Executing a query that collects the results of all 4 small queries into our empty table. +The split query operation optimizes long-running queries by executing them in parallel on different GPUs, thereby reducing overall run time. It's crucial to note that not every query may benefit from this approach, as the splitting mechanism introduces some overhead runtime. Additionally, it's emphasized that splitting can only be performed in the UI, leveraging Meta-scripting, a feature currently exclusive to the UI environment. .. contents:: :local: @@ -23,7 +13,10 @@ The four stages of using the query split operation are: Syntax ======== -**Creating an empty table that is based on the query we wish to split:** +Creating an Empty Table That is Based on the Query We Wish to Split +---------------------------------------------------------------------- + +Creating an empty table with an identical DDL of what would have been the result set table if we were to run the query we wish to split into 4 small queries. This empty table would eventually hold the results of all 4 small queries. .. code-block:: sql @@ -36,18 +29,24 @@ Syntax #A false_filter example: (1=2) -**Using the @@SetResult operator to create a minMax variable:** +Using the ``@@SetResult`` Operator to Create a ``minMax`` Variable +-------------------------------------------------------------------- The ``minMax`` variable is used to define minimum and maximum values of ``INTEGER``, ``DATE``, ``DATETIME`` or Identity columns by which we can split our query. - + .. code-block:: sql - + @@SetResult minMax SELECT min(<integer_column>) AS min, max(<integer_column>) AS max FROM <my_table> [WHERE <condition>] ; +Splitting the Query +---------------------- + +Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER``, ``DATE``, or ``DATETIME`` data types, or otherwise, an Identity column. + **Splitting a query using an INTEGER column:** Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. @@ -59,7 +58,8 @@ Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. SELECT <column_to_split_by> [,...] FROM <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); + ) + ; **Splitting a query using a DATE column:** @@ -72,22 +72,27 @@ Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. SELECT <column_to_split_by> [,...] FROM <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); + ) + ; **Splitting a query using a DATETIME column:** Using the ``@@SplitQueryByDateTime`` operator to create an ``instances`` variable. -.. code-block:: postgres +.. code-block:: sql @@SplitQueryByDateTime instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> SELECT <column_to_split_by> [,...] FROM <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); + ) + ; -**Outputting the results of our 4 small queries:** +Outputting the Results of Our 4 Small Queries +----------------------------------------------- + +Executing a query that collects the results of all 4 small queries into our empty table. .. code-block:: sql From 44d322b34c0e9aa7b1c65c3eae012f2fce6da382 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:03:31 +0200 Subject: [PATCH 1083/1892] Update query_split.rst --- operational_guides/query_split.rst | 207 ++++++++++++++++++++++++++++- 1 file changed, 202 insertions(+), 5 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index ef4b34a5e..92d105691 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -26,7 +26,7 @@ Creating an empty table with an identical DDL of what would have been the result WHERE (<false_filter>) ); - #A false_filter example: (1=2) + -- A false_filter example: (1=2) Using the ``@@SetResult`` Operator to Create a ``minMax`` Variable @@ -96,19 +96,216 @@ Executing a query that collects the results of all 4 small queries into our empt .. code-block:: sql - #Basic execution for queries which do not use aggregations: + -- Basic execution for queries which do not use aggregations: SELECT * FROM <final_result_table> ; - #Execution for queries which use aggregations: + -- Execution for queries which use aggregations: - SELECT <column1>, <column2> [,...], SUM(<column4>) + SELECT + <column1>, [,...], + [SUM([DISTINCT] expr) AS <sum_column>], + [SUM(count_column) AS <sum_count_column>], + [SUM(avg_column1) / SUM(avg_column2) AS <avg_column>] FROM <final_result_table> GROUP BY <column1>, <column2> [,...] ORDER BY SUM(<column4>) ); - ##Do not use a WHERE clause + -- Do not use a WHERE clause + +Query Split Operation +========================= + +The execution of the query split operation is fairly simple. After having created an empty result-set table, the ``minMax`` variable, the query split script, and the script that outputs all results into the result-set table, all you have to do is copy and paste all of the scripts into one tab, and run them + +Creating the Required Scripts for Splitting a Query +---------------------------------------------------- + +Use the following table to create your first query split: + +.. code-block:: sql + + CREATE TABLE MyTable ( + id INT, + name TEXT NOT NULL, + age INT, + salary INT, + quantity INT + ); + + -- Inserting data into the table + INSERT INTO MyTable (id, name, age, salary, quantity) + VALUES + (1, 'John', 25, 50000, 10), + (2, 'Jane', 30, 60000, 20), + (3, 'Bob', 28, 55000, 15), + (4, 'Emily', 35, 70000, 18), + (5, 'David', 32, 62000, 22), + (6, 'Sarah', 27, 52000, 12), + (7, 'Michael', 40, 75000, 17), + (8, 'Olivia', 22, 48000, 25), + (9, 'William', 31, 58000, 14), + (10, 'Sophia', 29, 56000, 19), + (11, 'Liam', 26, 51000, 13), + (12, 'Emma', 33, 64000, 16), + (13, 'Daniel', 24, 49000, 23), + (14, 'Ava', 37, 69000, 21), + (15, 'Matthew', 23, 47000, 28), + (16, 'Ella', 34, 67000, 24), + (17, 'James', 28, 55000, 11), + (18, 'Grace', 39, 72000, 26), + (19, 'Benjamin', 30, 60000, 18), + (20, 'Chloe', 25, 50000, 14), + (21, 'Logan', 38, 71000, 20), + (22, 'Mia', 27, 52000, 16), + (23, 'Christopher', 32, 62000, 22), + (24, 'Aiden', 29, 56000, 19), + (25, 'Lily', 36, 68000, 15), + (26, 'Jackson', 31, 58000, 23), + (27, 'Harper', 24, 49000, 12), + (28, 'Ethan', 35, 70000, 17), + (29, 'Isabella', 22, 48000, 25), + (30, 'Carter', 37, 69000, 14), + (31, 'Amelia', 26, 51000, 21), + (32, 'Lucas', 33, 64000, 19), + (33, 'Abigail', 28, 55000, 16), + (34, 'Mason', 39, 72000, 18), + (35, 'Evelyn', 30, 60000, 25), + (36, 'Alexander', 23, 47000, 13), + (37, 'Addison', 34, 67000, 22), + (38, 'Henry', 25, 50000, 20), + (39, 'Avery', 36, 68000, 15), + (40, 'Sebastian', 29, 56000, 24), + (41, 'Layla', 31, 58000, 11), + (42, 'Wyatt', 38, 71000, 26), + (43, 'Nora', 27, 52000, 19), + (44, 'Grayson', 32, 62000, 17), + (45, 'Scarlett', 24, 49000, 14), + (46, 'Gabriel', 35, 70000, 23), + (47, 'Hannah', 22, 48000, 16), + (48, 'Eli', 37, 69000, 25), + (49, 'Paisley', 28, 55000, 18), + (50, 'Owen', 33, 64000, 12); + +Create a complex query: + +.. code-block:: sql + + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + salary > 55000 + GROUP BY + age + ORDER BY + age; + +Create an empty table with the DDL of your final result-set table, using a false filter under the ``WHERE`` clause. + +.. code-block:: sql + + CREATE OR TABLE FinalResult + AS + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + 1=0 + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); + +Use the ``@@SetResult`` operator to create a ``minMax`` variable: + +.. code-block:: sql + + @@ SetResult minMax + SELECT min(id) as min, max(id) as max + FROM mytable + ; + +Create a Split Query: + +.. code-block:: sql + + @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max + INSERT INTO FinalResult + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + id between ${from} and ${to} + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); + +Create a script to collect all of the results into the empty result-set table: + +.. code-block:: sql + + SELECT + age, + SUM(total_people) AS total_people, + SUM(avg_salary) / SUM(avg_salary) AS avg_salary, + SUM(total_quantity) AS total_quantity, + SUM(high_quantity_count) AS high_quantity_count, + SUM(total_salary_age_25_30) AS total_salary_age_25_30 + FROM + FinalResult + GROUP BY + age + ORDER BY + age + ; + +Executing the Query Split +--------------------------- + +#. Open a new tab in your Editor. + +#. Paste the original query you wish to split and put a ``;`` at the end. + +#. Paste the script for creating an empty table and put a ``;`` at the end. + +#. Paste the script for creating a ``minMax`` variable and put a ``;`` at the end. + +#. Paste the script for splitting your query and put a ``;`` at the end. + +#. Paste the script for collecting the results of your small queries into the empty table and put a ``;`` at the end. + +#. In the UI toolbar, verify that the query **Execution** button is set to **All**. + +#. Select **Execute**. + +.. code-block:: sql From 6741bf8515397d3c3bd6377f629be06467c0814e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Dec 2023 15:23:19 +0200 Subject: [PATCH 1084/1892] Update query_split.rst --- operational_guides/query_split.rst | 224 ++++++++++++++++------------- 1 file changed, 121 insertions(+), 103 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 92d105691..0c98c8fab 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -20,13 +20,18 @@ Creating an empty table with an identical DDL of what would have been the result .. code-block:: sql - CREATE TABLE <final_result_table> AS ( - SELECT <column_to_split_by> [,...] - FROM <my_table> - WHERE (<false_filter>) + CREATE TABLE <final_result_table> + AS + ( + SELECT + <column_to_split_by> [,...] + FROM + <my_table> + WHERE + <false_filter> ); - -- A false_filter example: (1=2) + -- A false_filter example: 1=2 Using the ``@@SetResult`` Operator to Create a ``minMax`` Variable @@ -38,7 +43,8 @@ The ``minMax`` variable is used to define minimum and maximum values of ``INTEGE @@SetResult minMax SELECT min(<integer_column>) AS min, max(<integer_column>) AS max - FROM <my_table> + FROM + <my_table> [WHERE <condition>] ; @@ -55,11 +61,14 @@ Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. @@SplitQueryByNumber instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> - SELECT <column_to_split_by> [,...] - FROM <my_table> - WHERE <column_to_split_by> between ${from} and ${to} - ) - ; + ( + SELECT + <column_to_split_by> [,...] + FROM + <my_table> + WHERE + <column_to_split_by> between ${from} and ${to} + ); **Splitting a query using a DATE column:** @@ -69,11 +78,14 @@ Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. @@SplitQueryByDate instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> - SELECT <column_to_split_by> [,...] - FROM <my_table> - WHERE <column_to_split_by> between ${from} and ${to} - ) - ; + ( + SELECT + <column_to_split_by> [,...] + FROM + <my_table> + WHERE + <column_to_split_by> between ${from} and ${to} + ); **Splitting a query using a DATETIME column:** @@ -83,11 +95,13 @@ Using the ``@@SplitQueryByDateTime`` operator to create an ``instances`` variabl @@SplitQueryByDateTime instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> - SELECT <column_to_split_by> [,...] - FROM <my_table> - WHERE <column_to_split_by> between ${from} and ${to} - ) - ; + ( + SELECT + <column_to_split_by> [,...] + FROM + <my_table> + WHERE <column_to_split_by> between ${from} and ${to} + ); Outputting the Results of Our 4 Small Queries ----------------------------------------------- @@ -99,20 +113,24 @@ Executing a query that collects the results of all 4 small queries into our empt -- Basic execution for queries which do not use aggregations: SELECT * - FROM <final_result_table> + FROM + <final_result_table> ; -- Execution for queries which use aggregations: SELECT - <column1>, [,...], - [SUM([DISTINCT] expr) AS <sum_column>], - [SUM(count_column) AS <sum_count_column>], - [SUM(avg_column1) / SUM(avg_column2) AS <avg_column>] - FROM <final_result_table> - GROUP BY <column1>, <column2> [,...] - ORDER BY SUM(<column4>) - ); + <column1>, [,...], + [SUM([DISTINCT] expr) AS <sum_column>], + [SUM(count_column) AS <sum_count_column>], + [SUM(avg_column1) / SUM(avg_column2) AS <avg_column>] + FROM + <final_result_table> + GROUP BY + <column1>, <column2> [,...] + ORDER BY + <column4> + ; -- Do not use a WHERE clause @@ -129,66 +147,66 @@ Use the following table to create your first query split: .. code-block:: sql CREATE TABLE MyTable ( - id INT, - name TEXT NOT NULL, - age INT, - salary INT, - quantity INT - ); + id INT, + name TEXT NOT NULL, + age INT, + salary INT, + quantity INT + ); -- Inserting data into the table INSERT INTO MyTable (id, name, age, salary, quantity) VALUES - (1, 'John', 25, 50000, 10), - (2, 'Jane', 30, 60000, 20), - (3, 'Bob', 28, 55000, 15), - (4, 'Emily', 35, 70000, 18), - (5, 'David', 32, 62000, 22), - (6, 'Sarah', 27, 52000, 12), - (7, 'Michael', 40, 75000, 17), - (8, 'Olivia', 22, 48000, 25), - (9, 'William', 31, 58000, 14), - (10, 'Sophia', 29, 56000, 19), - (11, 'Liam', 26, 51000, 13), - (12, 'Emma', 33, 64000, 16), - (13, 'Daniel', 24, 49000, 23), - (14, 'Ava', 37, 69000, 21), - (15, 'Matthew', 23, 47000, 28), - (16, 'Ella', 34, 67000, 24), - (17, 'James', 28, 55000, 11), - (18, 'Grace', 39, 72000, 26), - (19, 'Benjamin', 30, 60000, 18), - (20, 'Chloe', 25, 50000, 14), - (21, 'Logan', 38, 71000, 20), - (22, 'Mia', 27, 52000, 16), - (23, 'Christopher', 32, 62000, 22), - (24, 'Aiden', 29, 56000, 19), - (25, 'Lily', 36, 68000, 15), - (26, 'Jackson', 31, 58000, 23), - (27, 'Harper', 24, 49000, 12), - (28, 'Ethan', 35, 70000, 17), - (29, 'Isabella', 22, 48000, 25), - (30, 'Carter', 37, 69000, 14), - (31, 'Amelia', 26, 51000, 21), - (32, 'Lucas', 33, 64000, 19), - (33, 'Abigail', 28, 55000, 16), - (34, 'Mason', 39, 72000, 18), - (35, 'Evelyn', 30, 60000, 25), - (36, 'Alexander', 23, 47000, 13), - (37, 'Addison', 34, 67000, 22), - (38, 'Henry', 25, 50000, 20), - (39, 'Avery', 36, 68000, 15), - (40, 'Sebastian', 29, 56000, 24), - (41, 'Layla', 31, 58000, 11), - (42, 'Wyatt', 38, 71000, 26), - (43, 'Nora', 27, 52000, 19), - (44, 'Grayson', 32, 62000, 17), - (45, 'Scarlett', 24, 49000, 14), - (46, 'Gabriel', 35, 70000, 23), - (47, 'Hannah', 22, 48000, 16), - (48, 'Eli', 37, 69000, 25), - (49, 'Paisley', 28, 55000, 18), - (50, 'Owen', 33, 64000, 12); + (1, 'John', 25, 50000, 10), + (2, 'Jane', 30, 60000, 20), + (3, 'Bob', 28, 55000, 15), + (4, 'Emily', 35, 70000, 18), + (5, 'David', 32, 62000, 22), + (6, 'Sarah', 27, 52000, 12), + (7, 'Michael', 40, 75000, 17), + (8, 'Olivia', 22, 48000, 25), + (9, 'William', 31, 58000, 14), + (10, 'Sophia', 29, 56000, 19), + (11, 'Liam', 26, 51000, 13), + (12, 'Emma', 33, 64000, 16), + (13, 'Daniel', 24, 49000, 23), + (14, 'Ava', 37, 69000, 21), + (15, 'Matthew', 23, 47000, 28), + (16, 'Ella', 34, 67000, 24), + (17, 'James', 28, 55000, 11), + (18, 'Grace', 39, 72000, 26), + (19, 'Benjamin', 30, 60000, 18), + (20, 'Chloe', 25, 50000, 14), + (21, 'Logan', 38, 71000, 20), + (22, 'Mia', 27, 52000, 16), + (23, 'Christopher', 32, 62000, 22), + (24, 'Aiden', 29, 56000, 19), + (25, 'Lily', 36, 68000, 15), + (26, 'Jackson', 31, 58000, 23), + (27, 'Harper', 24, 49000, 12), + (28, 'Ethan', 35, 70000, 17), + (29, 'Isabella', 22, 48000, 25), + (30, 'Carter', 37, 69000, 14), + (31, 'Amelia', 26, 51000, 21), + (32, 'Lucas', 33, 64000, 19), + (33, 'Abigail', 28, 55000, 16), + (34, 'Mason', 39, 72000, 18), + (35, 'Evelyn', 30, 60000, 25), + (36, 'Alexander', 23, 47000, 13), + (37, 'Addison', 34, 67000, 22), + (38, 'Henry', 25, 50000, 20), + (39, 'Avery', 36, 68000, 15), + (40, 'Sebastian', 29, 56000, 24), + (41, 'Layla', 31, 58000, 11), + (42, 'Wyatt', 38, 71000, 26), + (43, 'Nora', 27, 52000, 19), + (44, 'Grayson', 32, 62000, 17), + (45, 'Scarlett', 24, 49000, 14), + (46, 'Gabriel', 35, 70000, 23), + (47, 'Hannah', 22, 48000, 16), + (48, 'Eli', 37, 69000, 25), + (49, 'Paisley', 28, 55000, 18), + (50, 'Owen', 33, 64000, 12); Create a complex query: @@ -251,23 +269,23 @@ Create a Split Query: @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max INSERT INTO FinalResult ( - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - id between ${from} and ${to} - AND salary > 55000 - GROUP BY - age - ORDER BY - age - ); + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + id between ${from} and ${to} + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); Create a script to collect all of the results into the empty result-set table: From 8be3d2b4c971e32cf09def86c1b5d0abb9dccbf1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Dec 2023 08:45:10 +0200 Subject: [PATCH 1085/1892] Update create_foreign_table.rst --- .../sql/sql_statements/ddl_commands/create_foreign_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index ded035dc7..c21b5e925 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -95,7 +95,7 @@ Parameters * - ``OFFSET`` - Used to specify the number of rows to skip from the beginning of the result set * - ``CONTINUE_ON_ERROR`` - - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT`` When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false``. + - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction continues despite rejected data and rows containing partially faulty data are skipped entirely. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false``. * - ``ERROR_COUNT`` - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. Default value: ``unlimited``. Value range: 1 to 2147483647. From 9df47de9b85e61da6a41c84013675570957304d7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Dec 2023 08:52:00 +0200 Subject: [PATCH 1086/1892] Update index.rst --- operational_guides/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/operational_guides/index.rst b/operational_guides/index.rst index e7be1a5e4..0a8b15a5c 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -3,6 +3,7 @@ ********************************** Operational Guides ********************************** + The **Operational Guides** section describes processes that SQream users can manage to affect the way their system operates, such as creating storage clusters and monitoring query performance. This section summarizes the following operational guides: From ce0749d1a08529fb263f7ca161e3d2ce993a4d67 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 19 Dec 2023 16:32:15 +0200 Subject: [PATCH 1087/1892] Sign --- operational_guides/index.rst | 1 + reference/sql/sql_functions/scalar_functions/numeric/sign.rst | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 0a8b15a5c..60a345e91 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -27,3 +27,4 @@ This section summarizes the following operational guides: configuration optimization_best_practices hardware_guide + \ No newline at end of file diff --git a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst index b86f9c573..a1f835c4b 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/sign.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/sign.rst @@ -4,7 +4,7 @@ SIGN **** -The ``SIGN`` function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL, and returns an ``INT`` value of -1, 0, or 1, depending on the sign of the input argument. +The ``SIGN`` function takes a single argument, which can be any numeric data type such as INTEGER, FLOAT, or DECIMAL, and returns a value of -1, 0, or 1, depending on the sign of the input argument. @@ -30,7 +30,7 @@ Arguments Return ====== -Returns an ``INT`` value. +The ``SIGN`` function returns the same data type as inserted, with the exception of ``REAL``, which is converted to ``DOUBLE``. Depending on the sign of the input argument, the return is: From 8511e64a4740f9afb353e08f5f363fd35553c11d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Dec 2023 08:59:42 +0200 Subject: [PATCH 1088/1892] Python 3.9 --- .../current_method_modification_methods.rst | 9 +- feature_guides/python_functions.rst | 167 +++++++++--------- 2 files changed, 89 insertions(+), 87 deletions(-) diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index 9c56fb6ea..f3f229a5e 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -9,7 +9,8 @@ Modification Methods :depth: 1 Modifying Your Configuration Using the Worker Configuration File -------------------- +---------------------------------------------------------------------------- + You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. The following is an example of a worker configuration file: @@ -31,7 +32,8 @@ The following is an example of a worker configuration file: You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. Modifying Your Configuration Using a Legacy Configuration File ---------------------- +------------------------------------------------------------------------------ + You can modify your configuration using a legacy configuration file. The Legacy configuration file provides access to the read/write flags. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. @@ -44,5 +46,6 @@ The following is an example of the legacy configuration file: "developerMode": true, "reextentUse": false, "useClientLog": true, - "useMetadataServer": false + "useMetadataServer": false, + "enablePythonUdfs": true } \ No newline at end of file diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 7aaea5051..2aca0a035 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -1,94 +1,38 @@ .. _python_functions: ************************************* -Python UDF (User-Defined Functions) +Python User-Defined Functions ************************************* -User-defined functions (UDFs) are a feature that extends SQream DB's built in SQL functionality. SQream DB's Python UDFs allow developers to create new functionality in SQL by writing the lower-level language implementation in Python. +User-Defined Functions (UDFs) offer streamlined statements, enabling the creation of a function once, storing it in the database, and calling it multiple times within a statement. Additionally, UDFs can be shared among roles, created by a database administrator and utilized by others. Furthermore, they contribute to code simplicity by allowing independent modifications in SQream DB without altering program source code. -.. note:: Starting v2022.1.4, Python UDF are disabled by default in order to enhance product security. Use the ``enablePythonUdfs`` configuration flag in order to enable Python UDF. +To enable UDFs, in your :ref:`legacy configuration file<current_method_modification_methods>`, set the ``enablePythonUdfs`` configuration flag to ``true``. -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 -A simple example -===================== +Before You Begin +================= -Most databases have an :ref:`UPPER` function, including SQream DB. However, assume that this function is missing for the sake of this example. - -You can write a function in Python to uppercase a text value using the :ref:`create_function` syntax. - -.. code-block:: postgres - - CREATE FUNCTION my_upper (x1 text) - RETURNS text - AS $$ - return x1.upper() - $$ LANGUAGE PYTHON; - -Let's break down this example: - -* ``CREATE FUNCTION my_upper`` - :ref:`Create a function<create_function>` called ``my_upper``. This name must be unique in the current database -* ``(x1 text)`` - the function accepts one argument named ``x1`` which is of the SQL type ``TEXT``. All :ref:`data types<data_types>` are supported. -* ``RETURNS text`` - the function returns the same type - ``TEXT``. All :ref:`data types<data_types>` are supported. -* ``AS $$`` - what follows is some code that we don't want to quote, so we use dollar-quoting (``$$``) instead of single quotes (``'``). -* ``return x1.upper()`` - the Python function's body is the argument named ``x1``, uppercased. -* ``$$ LANGUAGE PYTHON`` - this is the end of the function, and it's in the Python language. - -.. rubric:: Running this example - -After creating the function, you can use it in any SQL query. - -For example: +* Ensure you have Python 3.9 or newer installed -.. code-block:: psql - - master=>CREATE TABLE jabberwocky(line text); - executed - master=> INSERT INTO jabberwocky VALUES - . ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') - . ,('All mimsy were the borogoves, '), (' And the mome raths outgrabe. ') - . ,('"Beware the Jabberwock, my son! '), (' The jaws that bite, the claws that catch! ') - . ,('Beware the Jubjub bird, and shun '), (' The frumious Bandersnatch!" '); - executed - master=> SELECT line, my_upper(line) FROM jabberwocky; - line | my_upper - -------------------------------------------------+------------------------------------------------- - 'Twas brillig, and the slithy toves | 'TWAS BRILLIG, AND THE SLITHY TOVES - Did gyre and gimble in the wabe: | DID GYRE AND GIMBLE IN THE WABE: - All mimsy were the borogoves, | ALL MIMSY WERE THE BOROGOVES, - And the mome raths outgrabe. | AND THE MOME RATHS OUTGRABE. - "Beware the Jabberwock, my son! | "BEWARE THE JABBERWOCK, MY SON! - The jaws that bite, the claws that catch! | THE JAWS THAT BITE, THE CLAWS THAT CATCH! - Beware the Jubjub bird, and shun | BEWARE THE JUBJUB BIRD, AND SHUN - The frumious Bandersnatch!" | THE FRUMIOUS BANDERSNATCH!" - -Why use UDFs? -===================== - -* They allow simpler statements - You can create the function once, store it in the database, and call it any number of times in a statement. +* Enable UDFs by setting the ``enablePythonUdfs`` configuration flag to ``true`` in your :ref:`legacy configuration file<current_method_modification_methods>` -* They can be shared - UDFs can be created by a database administrator, and then used by other roles. - -* They can simplify downstream code - UDFs can be modified in SQream DB independently of program source code. - -SQream DB's UDF support +SQreamDB's UDF Support ============================= -Scalar functions +Scalar Functions --------------------- -SQream DB's UDFs are scalar functions. This means that the UDF returns a single data value of the type defined in the ``RETURNS`` clause. For an inline scalar function, the returned scalar value is the result of a single statement. +SQreamDB's UDFs are scalar functions. This means that the UDF returns a single data value of the type defined in the ``RETURNS`` clause. For an inline scalar function, the returned scalar value is the result of a single statement. Python -------------------- - -At this time, SQream DB's UDFs are supported for Python. +--------- -Python 3.6.7 is installed alongside SQream DB, for use exclusively by SQream DB. -You may have a different version of Python installed on your server. +Python is installed alongside SQreamDB, for use exclusively by SQreamDB. You may have a different version of Python installed on your server. -To find which version of Python is installed for use by SQream DB, create and run this UDF: +To find which version of Python is installed for use by SQreamDB, create and run this UDF: .. code-block:: psql @@ -102,17 +46,19 @@ To find which version of Python is installed for use by SQream DB, create and ru master=> SELECT py_version(); py_version ------------------------------------------------------------------------------------- - Python version: 3.6.7 (default, Jul 22 2019, 11:03:54) [GCC 5.4.0]. - Path: /opt/sqream/python-3.6.7-5.4.0 + Python version: 3.9.13 (default, Jul 22 2019, 11:03:54) [GCC 5.4.0]. + Path: /opt/sqream/python-3.9.13 -Using modules +Using Modules --------------------- To import a Python module, use the standard ``import`` syntax in the first lines of the user-defined function. +Working with Existing UDFs +=========================== -Finding existing UDFs in the catalog -======================================== +Finding Existing UDFs in the Catalog +---------------------------------------- The ``user_defined_functions`` catalog view contains function information. @@ -126,8 +72,8 @@ Here's how you'd list all UDFs in the system: master | 1 | my_upper -Getting the DDL for a function -===================================== +Getting Function DDL +---------------------- .. code-block:: psql @@ -142,12 +88,12 @@ Getting the DDL for a function See :ref:`get_function_ddl` for more information. -Error handling -===================== +Handling Errors +----------------- In UDFs, any error that occurs causes the execution of the function to stop. This in turn causes the statement that invoked the function to be canceled. -Permissions and sharing +Permissions and Sharing ============================ To create a UDF, the creator needs the ``CREATE FUNCTION`` permission at the database level. @@ -156,7 +102,7 @@ For example, to grant ``CREATE FUNCTION`` to a non-superuser role: .. code-block:: postgres - GRANT CREATE FUNCTION ON DATABASE master TO mjordan; + GRANT CREATE FUNCTION ON DATABASE master TO role1; To execute a UDF, the role needs the ``EXECUTE FUNCTION`` permission for every function. @@ -170,9 +116,62 @@ For example, to grant the permission to the ``r_bi_users`` role group, run: See more information about permissions in the :ref:`Access control guide<access_control>`. +Example +========= + +Most databases have an :ref:`UPPER` function, including SQream DB. However, assume that this function is missing for the sake of this example. + +You can write a function in Python to uppercase a text value using the :ref:`create_function` syntax. + +.. code-block:: postgres + + CREATE FUNCTION my_upper (x1 text) + RETURNS text + AS $$ + return x1.upper() + $$ LANGUAGE PYTHON; + +Let's break down this example: + +* ``CREATE FUNCTION my_upper`` - :ref:`Create a function<create_function>` called ``my_upper``. This name must be unique in the current database +* ``(x1 text)`` - the function accepts one argument named ``x1`` which is of the SQL type ``TEXT``. All :ref:`data types<data_types>` are supported. +* ``RETURNS text`` - the function returns the same type - ``TEXT``. All :ref:`data types<data_types>` are supported. +* ``AS $$`` - what follows is some code that we don't want to quote, so we use dollar-quoting (``$$``) instead of single quotes (``'``). +* ``return x1.upper()`` - the Python function's body is the argument named ``x1``, uppercased. +* ``$$ LANGUAGE PYTHON`` - this is the end of the function, and it's in the Python language. + +.. rubric:: Running this example + +After creating the function, you can use it in any SQL query. + +For example: + +.. code-block:: psql + + master=>CREATE TABLE jabberwocky(line text); + executed + master=> INSERT INTO jabberwocky VALUES + . ('''Twas brillig, and the slithy toves '), (' Did gyre and gimble in the wabe: ') + . ,('All mimsy were the borogoves, '), (' And the mome raths outgrabe. ') + . ,('"Beware the Jabberwock, my son! '), (' The jaws that bite, the claws that catch! ') + . ,('Beware the Jubjub bird, and shun '), (' The frumious Bandersnatch!" '); + executed + master=> SELECT line, my_upper(line) FROM jabberwocky; + line | my_upper + -------------------------------------------------+------------------------------------------------- + 'Twas brillig, and the slithy toves | 'TWAS BRILLIG, AND THE SLITHY TOVES + Did gyre and gimble in the wabe: | DID GYRE AND GIMBLE IN THE WABE: + All mimsy were the borogoves, | ALL MIMSY WERE THE BOROGOVES, + And the mome raths outgrabe. | AND THE MOME RATHS OUTGRABE. + "Beware the Jabberwock, my son! | "BEWARE THE JABBERWOCK, MY SON! + The jaws that bite, the claws that catch! | THE JAWS THAT BITE, THE CLAWS THAT CATCH! + Beware the Jubjub bird, and shun | BEWARE THE JUBJUB BIRD, AND SHUN + The frumious Bandersnatch!" | THE FRUMIOUS BANDERSNATCH!" + + -Best practices -===================== +Best Practices +=============== Although user-defined functions add flexibility, they may have some performance drawbacks. They are not usually a replacement for subqueries or views. From 824a20928e5ec907bcec94f9954ba59a6402f05c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Dec 2023 09:39:30 +0200 Subject: [PATCH 1089/1892] Delete storing_data_on_parquet.rst --- external_storage_platforms/storing_data_on_parquet.rst | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 external_storage_platforms/storing_data_on_parquet.rst diff --git a/external_storage_platforms/storing_data_on_parquet.rst b/external_storage_platforms/storing_data_on_parquet.rst deleted file mode 100644 index 0aa54dbc4..000000000 --- a/external_storage_platforms/storing_data_on_parquet.rst +++ /dev/null @@ -1,8 +0,0 @@ -.. _storing_data_on_parquet: - -*********************** -Storing Data on Parquet -*********************** -As described in the **Data Ingestion Sources** section, users can insert data into SQream from Parquet files. However, because it is an open-source column-oriented data storage format, users may want to retain their data there instead of inserting it into SQream. This requires SQream users to be able to execute queries on external Parquet files. - - From 516b2315528f6302b3980453dd5a11e8b4fb6dc1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Dec 2023 15:53:35 +0200 Subject: [PATCH 1090/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 8225abf17..fc13ce0ec 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= The **SQLoader** automatically maps data types used in Postgresql, Oracle, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. .. list-table:: Postgresql :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` .. list-table:: Oracle :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` .. list-table:: Teradata :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` .. list-table:: Microsoft SQL Server :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` .. list-table:: SAP HANA :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 517d3a87075a76815049ba1307f01951f52c8e18 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 25 Dec 2023 09:32:51 +0200 Subject: [PATCH 1091/1892] FDW Prerequisites --- data_ingestion/avro.rst | 12 ++++++++++++ data_ingestion/csv.rst | 12 ++++++++++++ data_ingestion/json.rst | 2 +- data_ingestion/orc.rst | 13 ++++++++++++- data_ingestion/parquet.rst | 12 ++++++++++++ 5 files changed, 49 insertions(+), 2 deletions(-) diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index eff3eb951..8fe2b13ff 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -10,6 +10,18 @@ Avro :local: :depth: 1 +Foreign Data Wrapper Prerequisites +=================================== + +Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: + +* **File Existence:** Verify that the file you are ingesting data from exists at the specified path. + +* **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. +* **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. + +* **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. + Making Avro Files Accessible to Workers ======================================= diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 993bcb2a7..2fe6b16a8 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -11,6 +11,18 @@ This guide covers ingesting data from CSV files into SQream DB using the :ref:`c :local: :depth: 1 +Foreign Data Wrapper Prerequisites +=================================== + +Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: + +* **File Existence:** Verify that the file you are ingesting data from exists at the specified path. + +* **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. +* **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. + +* **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. + Prepare CSVs ============ diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index d68af75f2..589966102 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** .. contents:: :local: :depth: 1 Overview ======== JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index 397dd7946..c0dffd842 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -4,12 +4,23 @@ ORC *** +This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE<external_tables>`. + .. contents:: :local: :depth: 1 -This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE<external_tables>`. +Foreign Data Wrapper Prerequisites +=================================== + +Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: + +* **File Existence:** Verify that the file you are ingesting data from exists at the specified path. + +* **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. +* **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. +* **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Prepare the files ================= diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 355d27344..12b409740 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -10,6 +10,18 @@ Ingesting Parquet files into SQream is generally useful when you want to store t :local: :depth: 1 +Foreign Data Wrapper Prerequisites +=================================== + +Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: + +* **File Existence:** Verify that the file you are ingesting data from exists at the specified path. + +* **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. +* **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. + +* **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. + Preparing Your Parquet Files ============================ From 7cd98ab147f90bf32248c05c5a9e548eb4eecc27 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 25 Dec 2023 10:59:57 +0200 Subject: [PATCH 1092/1892] ALTER DEFAULT PERMISSIONS FOREIGN TABLEs --- operational_guides/access_control_permissions.rst | 2 +- .../access_control_commands/alter_default_permissions.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 2883ffee6..8e4469da2 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -333,7 +333,7 @@ schema statement is run. FOR { SCHEMAS | TABLES - | FOREIGN TABLE + | FOREIGN TABLES | VIEWS | COLUMNS | SAVED_QUERIES diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 478bbdf5b..f8e92fd85 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -29,7 +29,7 @@ Syntax FOR { SCHEMAS | TABLES - | FOREIGN TABLE + | FOREIGN TABLES | VIEWS | COLUMNS | SAVED_QUERIES From 0c3c2eca56a7799cffdcd02e8d97cde4c5cc671a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 25 Dec 2023 11:24:36 +0200 Subject: [PATCH 1093/1892] Update create_role.rst --- .../access_control_commands/create_role.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/create_role.rst b/reference/sql/sql_statements/access_control_commands/create_role.rst index 1eb2bba47..6e3b815b1 100644 --- a/reference/sql/sql_statements/access_control_commands/create_role.rst +++ b/reference/sql/sql_statements/access_control_commands/create_role.rst @@ -76,11 +76,11 @@ Creating a user role A user role has permissions to login, and has a password. -.. tip:: Some DBMSs call this *CREATE USER* or *ADD USER* - .. code-block:: postgres CREATE ROLE new_role; GRANT LOGIN to new_role; - GRANT PASSWORD 'Tr0ub4dor&3' to new_role; - GRANT CONNECT ON DATABASE master to new_role; -- Repeat for other desired databases \ No newline at end of file + GRANT PASSWORD 'passw0rd' to new_role; + GRANT CONNECT ON DATABASE master to new_role; -- Repeat for all desired databases + GRANT USAGE ON SERVICE sqream TO new_role; + GRANT ALL ON SCHEMA public; -- It is advisable to grant permissions on at least one schema \ No newline at end of file From a9d2205ffd73162ec5237d2ac64795813479ae90 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 25 Dec 2023 17:08:23 +0200 Subject: [PATCH 1094/1892] Update query_split.rst --- operational_guides/query_split.rst | 275 +++++++++++++---------------- 1 file changed, 124 insertions(+), 151 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 0c98c8fab..6c620c0b7 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -4,7 +4,9 @@ Query Split **************************** -The split query operation optimizes long-running queries by executing them in parallel on different GPUs, thereby reducing overall run time. It's crucial to note that not every query may benefit from this approach, as the splitting mechanism introduces some overhead runtime. Additionally, it's emphasized that splitting can only be performed in the UI, leveraging Meta-scripting, a feature currently exclusive to the UI environment. +The split query operation optimizes long-running queries by executing them in parallel on different GPUs, reducing overall runtime. This involves breaking down a complex query into parallel executions on small data subsets. To ensure an ordered result set aligned with the original complex query, two prerequisites are essential. First, create an empty table mirroring the original result set's structure. Second, define the ``@@SetResult`` operator to split the query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column, as these types are compatible with the operator's ``min`` and ``max`` variables. + +Splitting is exclusive to the UI, utilizing Meta-scripting, a unique UI feature. Keep in mind that not all queries benefit, as this method introduces overhead runtime. .. contents:: :local: @@ -13,10 +15,7 @@ The split query operation optimizes long-running queries by executing them in pa Syntax ======== -Creating an Empty Table That is Based on the Query We Wish to Split ----------------------------------------------------------------------- - -Creating an empty table with an identical DDL of what would have been the result set table if we were to run the query we wish to split into 4 small queries. This empty table would eventually hold the results of all 4 small queries. +Creating an empty table mirroring the original query result set's structure using the same DDL: .. code-block:: sql @@ -29,16 +28,12 @@ Creating an empty table with an identical DDL of what would have been the result <my_table> WHERE <false_filter> - ); + ) -- A false_filter example: 1=2 - -Using the ``@@SetResult`` Operator to Create a ``minMax`` Variable --------------------------------------------------------------------- +Defining the ``@@setresult`` operator to split the original query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column with ``min`` and ``max`` variables. -The ``minMax`` variable is used to define minimum and maximum values of ``INTEGER``, ``DATE``, ``DATETIME`` or Identity columns by which we can split our query. - .. code-block:: sql @@SetResult minMax @@ -46,16 +41,11 @@ The ``minMax`` variable is used to define minimum and maximum values of ``INTEGE FROM <my_table> [WHERE <condition>] - ; - -Splitting the Query ----------------------- - -Deciding by which column to split your query by. Columns to split by can only be of ``INTEGER``, ``DATE``, or ``DATETIME`` data types, or otherwise, an Identity column. - -**Splitting a query using an INTEGER column:** + + +Defining the operator that determines the number of instances (splits) based on the data type of the column by which the query is split: -Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. +* **INTEGER column:** use the ``@@SplitQueryByNumber`` operator .. code-block:: sql @@ -68,11 +58,9 @@ Using the ``@@SplitQueryByNumber`` operator to create an ``instances`` variable. <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); - -**Splitting a query using a DATE column:** + ) -Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. +* **DATE column:** use the ``@@SplitQueryByDate`` operator .. code-block:: sql @@ -85,11 +73,9 @@ Using the ``@@SplitQueryByDate`` operator to create an ``instances`` variable. <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); - -**Splitting a query using a DATETIME column:** + ) -Using the ``@@SplitQueryByDateTime`` operator to create an ``instances`` variable. +* **DATETIME column:** use the ``@@SplitQueryByDateTime`` operator .. code-block:: sql @@ -101,12 +87,9 @@ Using the ``@@SplitQueryByDateTime`` operator to create an ``instances`` variabl FROM <my_table> WHERE <column_to_split_by> between ${from} and ${to} - ); + ) -Outputting the Results of Our 4 Small Queries ------------------------------------------------ - -Executing a query that collects the results of all 4 small queries into our empty table. +Outputting the results of your small queries by running a query that gathers the results of all small queries into the initially created empty table. .. code-block:: sql @@ -130,19 +113,13 @@ Executing a query that collects the results of all 4 small queries into our empt <column1>, <column2> [,...] ORDER BY <column4> - ; -- Do not use a WHERE clause -Query Split Operation -========================= - -The execution of the query split operation is fairly simple. After having created an empty result-set table, the ``minMax`` variable, the query split script, and the script that outputs all results into the result-set table, all you have to do is copy and paste all of the scripts into one tab, and run them - -Creating the Required Scripts for Splitting a Query ----------------------------------------------------- +Example +======== -Use the following table to create your first query split: +To split your first query, create the following table and insert data into it: .. code-block:: sql @@ -208,122 +185,118 @@ Use the following table to create your first query split: (49, 'Paisley', 28, 55000, 18), (50, 'Owen', 33, 64000, 12); -Create a complex query: - -.. code-block:: sql - - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - salary > 55000 - GROUP BY - age - ORDER BY - age; - -Create an empty table with the DDL of your final result-set table, using a false filter under the ``WHERE`` clause. - -.. code-block:: sql - - CREATE OR TABLE FinalResult - AS - ( - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - 1=0 - AND salary > 55000 - GROUP BY - age - ORDER BY - age - ); - -Use the ``@@SetResult`` operator to create a ``minMax`` variable: - -.. code-block:: sql - - @@ SetResult minMax - SELECT min(id) as min, max(id) as max - FROM mytable - ; - -Create a Split Query: - -.. code-block:: sql - - @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max - INSERT INTO FinalResult - ( - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - id between ${from} and ${to} - AND salary > 55000 - GROUP BY - age - ORDER BY - age - ); +Next, we'll split the following query: + + .. code-block:: sql + + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + salary > 55000 + GROUP BY + age + ORDER BY + age; + +1. Prepare the following: + + a. An empty table mirroring the original query result set’s structure with the same DDL, using a false filter under the ``WHERE`` clause: -Create a script to collect all of the results into the empty result-set table: - -.. code-block:: sql - - SELECT - age, - SUM(total_people) AS total_people, - SUM(avg_salary) / SUM(avg_salary) AS avg_salary, - SUM(total_quantity) AS total_quantity, - SUM(high_quantity_count) AS high_quantity_count, - SUM(total_salary_age_25_30) AS total_salary_age_25_30 - FROM - FinalResult - GROUP BY - age - ORDER BY - age - ; - -Executing the Query Split ---------------------------- - -#. Open a new tab in your Editor. + .. code-block:: sql + + CREATE OR TABLE FinalResult + AS + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + 1=0 + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); + + An empty table named ``FinalResult`` is created. + + b. The ``@@setresult`` operator to split the original query: + + .. code-block:: sql + + @@ SetResult minMax + SELECT min(id) as min, max(id) as max + FROM mytable + ; + + c. The operator that determines the number of instances (splits) of your query, based on an ``INTEGER`` column: + + .. code-block:: sql + + @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max + INSERT INTO FinalResult + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + id between ${from} and ${to} + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); + + d. A query that gathers the results of all small queries into the initially created empty table: -#. Paste the original query you wish to split and put a ``;`` at the end. + .. code-block:: sql -#. Paste the script for creating an empty table and put a ``;`` at the end. + SELECT + age, + SUM(total_people) AS total_people, + SUM(avg_salary) / SUM(avg_salary) AS avg_salary, + SUM(total_quantity) AS total_quantity, + SUM(high_quantity_count) AS high_quantity_count, + SUM(total_salary_age_25_30) AS total_salary_age_25_30 + FROM + FinalResult + GROUP BY + age + ORDER BY + age + ; -#. Paste the script for creating a ``minMax`` variable and put a ``;`` at the end. +2. Paste ALL five scripts into one Editor tab. -#. Paste the script for splitting your query and put a ``;`` at the end. +3. Ensure that each script ends with its own ``;``. -#. Paste the script for collecting the results of your small queries into the empty table and put a ``;`` at the end. +4. Ensure that the **Execute** button is set to **All**. -#. In the UI toolbar, verify that the query **Execution** button is set to **All**. +5. Select the **Execute** button. -#. Select **Execute**. + All five scripts are executed, resulting in the splitting of the initial query and a final result set. -.. code-block:: sql +Best Practices +================ From a28718de41e234d185a7f7ffd7270d8cea652f50 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jan 2024 08:07:31 +0200 Subject: [PATCH 1095/1892] Update query_split.rst --- operational_guides/query_split.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 6c620c0b7..7a5adf42f 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -208,6 +208,8 @@ Next, we'll split the following query: 1. Prepare the following: a. An empty table mirroring the original query result set’s structure with the same DDL, using a false filter under the ``WHERE`` clause: + + An empty table named ``FinalResult`` is created. .. code-block:: sql @@ -232,7 +234,7 @@ Next, we'll split the following query: age ); - An empty table named ``FinalResult`` is created. + b. The ``@@setresult`` operator to split the original query: From 90ca2f05b7dc1101e3cdc756ec19d0c12dd7bfbd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jan 2024 08:41:17 +0200 Subject: [PATCH 1096/1892] Update query_split.rst --- operational_guides/query_split.rst | 204 +++++++++++++++-------------- 1 file changed, 105 insertions(+), 99 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 7a5adf42f..1afafb349 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -119,6 +119,13 @@ Outputting the results of your small queries by running a query that gathers the Example ======== +.. contents:: + :local: + :depth: 1 + +Creating a Sample Table and Query +---------------------------------- + To split your first query, create the following table and insert data into it: .. code-block:: sql @@ -187,117 +194,116 @@ To split your first query, create the following table and insert data into it: Next, we'll split the following query: - .. code-block:: sql - - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - salary > 55000 - GROUP BY - age - ORDER BY - age; - -1. Prepare the following: - - a. An empty table mirroring the original query result set’s structure with the same DDL, using a false filter under the ``WHERE`` clause: +.. code-block:: sql + + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + salary > 55000 + GROUP BY + age + ORDER BY + age; + +Splitting the Query +-------------------- + +1. Prepare an empty table mirroring the original query result set’s structure with the same DDL, using a false filter under the ``WHERE`` clause. - An empty table named ``FinalResult`` is created. + An **empty** table named ``FinalResult`` is created. - .. code-block:: sql - - CREATE OR TABLE FinalResult - AS - ( - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - 1=0 - AND salary > 55000 - GROUP BY - age - ORDER BY - age - ); - +.. code-block:: sql + CREATE OR TABLE FinalResult + AS + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + 1=0 + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); + +2. Set the ``@@setresult`` operator to split the original query using ``min`` and ``max`` variables. - b. The ``@@setresult`` operator to split the original query: - - .. code-block:: sql - - @@ SetResult minMax - SELECT min(id) as min, max(id) as max - FROM mytable - ; - - c. The operator that determines the number of instances (splits) of your query, based on an ``INTEGER`` column: - - .. code-block:: sql - - @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max - INSERT INTO FinalResult - ( - SELECT - age, - COUNT(*) AS total_people, - AVG(salary) AS avg_salary, - SUM(quantity) AS total_quantity, - SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, - SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 - FROM - MyTable - WHERE - id between ${from} and ${to} - AND salary > 55000 - GROUP BY - age - ORDER BY - age - ); +.. code-block:: sql + + @@ SetResult minMax + SELECT min(id) as min, max(id) as max + FROM mytable + ; + +3. Set the ``@@SplitQueryByNumber`` operator with the number of instances (splits) of your query (here based on an ``INTEGER`` column), and set the ``between ${from} and ${to}`` clause with the name of the column by which you wish to split your query (here the query is split by the ``id`` column. + +.. code-block:: sql + + @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max + INSERT INTO FinalResult + ( + SELECT + age, + COUNT(*) AS total_people, + AVG(salary) AS avg_salary, + SUM(quantity) AS total_quantity, + SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, + SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 + FROM + MyTable + WHERE + id between ${from} and ${to} + AND salary > 55000 + GROUP BY + age + ORDER BY + age + ); - d. A query that gathers the results of all small queries into the initially created empty table: +4. Create a query that gathers the results of all instances (splits) into the empty table you created in step 1. - .. code-block:: sql +.. code-block:: sql - SELECT - age, - SUM(total_people) AS total_people, - SUM(avg_salary) / SUM(avg_salary) AS avg_salary, - SUM(total_quantity) AS total_quantity, - SUM(high_quantity_count) AS high_quantity_count, - SUM(total_salary_age_25_30) AS total_salary_age_25_30 - FROM - FinalResult - GROUP BY - age - ORDER BY - age - ; + SELECT + age, + SUM(total_people) AS total_people, + SUM(avg_salary) / SUM(avg_salary) AS avg_salary, + SUM(total_quantity) AS total_quantity, + SUM(high_quantity_count) AS high_quantity_count, + SUM(total_salary_age_25_30) AS total_salary_age_25_30 + FROM + FinalResult + GROUP BY + age + ORDER BY + age + ; -2. Paste ALL five scripts into one Editor tab. +5. Arrange ALL five sequential scripts on one Editor tab. -3. Ensure that each script ends with its own ``;``. +6. Ensure that EACH script ends with a ``;``. -4. Ensure that the **Execute** button is set to **All**. +7. Ensure that the **Execute** button is set to **All** so that all five queries are consecutively executed. -5. Select the **Execute** button. +8. Select the **Execute** button. - All five scripts are executed, resulting in the splitting of the initial query and a final result set. + All five scripts are executed, resulting in the splitting of the initial query and a table containing the final result set. Best Practices ================ From e2d2a2463afb8b3165a20eb660b6f7141a4c7816 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jan 2024 16:33:35 +0200 Subject: [PATCH 1097/1892] Update query_split.rst --- operational_guides/query_split.rst | 96 +++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 7 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 1afafb349..e460b59c1 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -32,16 +32,24 @@ Creating an empty table mirroring the original query result set's structure usin -- A false_filter example: 1=2 -Defining the ``@@setresult`` operator to split the original query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column with ``min`` and ``max`` variables. +Defining the ``@@setresult`` operator to split the original query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column with ``min`` and ``max`` variables. If the column you're splitting by is used in a ``WHERE`` clause in the original query, use a ``WHERE`` clause when setting the ``SetResult`` operator as well. .. code-block:: sql @@SetResult minMax - SELECT min(<integer_column>) AS min, max(<integer_column>) AS max + SELECT + MIN(<column>) AS min, + MAX(<column>) AS max FROM <my_table> - [WHERE <condition>] - + [WHERE + <column> BETWEEN + -- Integer Range: + 1 AND 100 + | -- Date Range: + '2022-01-01' AND '2022-12-31' + | -- DateTime Range: + '2022-01-01 01:24:00:000' AND '2022-12-31 08:51:24:000'] Defining the operator that determines the number of instances (splits) based on the data type of the column by which the query is split: @@ -57,7 +65,7 @@ Defining the operator that determines the number of instances (splits) based on FROM <my_table> WHERE - <column_to_split_by> between ${from} and ${to} + <column_to_split_by> BETWEEN ${from} and ${to} ) * **DATE column:** use the ``@@SplitQueryByDate`` operator @@ -72,7 +80,7 @@ Defining the operator that determines the number of instances (splits) based on FROM <my_table> WHERE - <column_to_split_by> between ${from} and ${to} + <column_to_split_by> BETWEEN ${from} and ${to} ) * **DATETIME column:** use the ``@@SplitQueryByDateTime`` operator @@ -86,7 +94,7 @@ Defining the operator that determines the number of instances (splits) based on <column_to_split_by> [,...] FROM <my_table> - WHERE <column_to_split_by> between ${from} and ${to} + WHERE <column_to_split_by> BETWEEN ${from} and ${to} ) Outputting the results of your small queries by running a query that gathers the results of all small queries into the initially created empty table. @@ -308,3 +316,77 @@ Splitting the Query Best Practices ================ +General +-------- + +* When incorporating the ``LIMIT`` clause or any aggregate function in your query, split the query based only on a ``GROUP BY`` column. If no relevant columns are present in the ``GROUP BY`` clause, the query might not be suitable for splitting. If you are not using aggregations, it's best to split the query using a column that appears in the a ``WHERE`` or ``JOIN`` clause. + +* When using the ``JOIN`` key, it is usually better to use the key of the smaller table. + +* For simple queries involving just one table, splitting is unlikely to enhance performance. + +Choosing a Column to Split by +------------------------------ + +The column you split by must be sorted or mostly sorted. Meaning, that even if the column values may not be perfectly ordered, they still follow a general sequence or trend. + +Aggregation Best Practices +-------------------------- + +Aggregation functions, or special functions need to have adjustments in the query that gathers the results of all instances (splits) into the empty table: + +* ``COUNT`` becomes ``SUM`` + +* ``AVERAGE`` is split into two columns in the split query and then merged as ``AVERAGE`` in the output query + + +Special functions should be split into different columns as well - **What special functions?** + +Date as Number best practices +------------------------------- + +When date is stored as number, using the number of workers as the instances number may not result in the expected way. +e.g. if date run from 20210101 to 20210630 splitting to 8 will result in 6 relevant splits, as SQream only checks min and max and splits accordingly (20210630-20210101)/8. we get an instance of empty data with dates ranging from 20210432 to 20210499 (not really dates, but real numbers). +In this case, we need to adjust the number of instance to get the right size splits. In the above example we need to split to 64, and each worker will run 3 splits with actual data. + +Using the ``SetResult`` +------------------------- + +When the column you split by is used in a ``WHERE`` clause in the original query, add it with the ``WHERE`` clause when you set the ``SetResult`` operator. + +.. code-block:: + + @@ SetResult minMax + SELECT min(ship_dates) AS min, max(ship_dates) AS max FROM shipments + /*optional - WHERE ship_dates BETWEEN '1995-01-01' AND '1996-01-01'*/ + ; + +Include? +----------- + +* Setting the column boundaries for the split - This is an optional query, but very useful, and can only be optional if you know in advance the boundaries. + +* The query that outputs the results from the table we created in the first query - This is an optional query, but most use cases will require have it and if we created the first query and used INSERT INTO in the splitting we have to use it. + +* Limit and group by together, can significantly reduce runtime. + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e62e7f5b2dfdc16806edcc0fc09c75a49111347e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jan 2024 11:13:57 +0200 Subject: [PATCH 1098/1892] Update index.rst --- sqream_studio/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqream_studio/index.rst b/sqream_studio/index.rst index ca9eefbba..afdff3457 100644 --- a/sqream_studio/index.rst +++ b/sqream_studio/index.rst @@ -1,7 +1,7 @@ .. _sqream_studio_: ******************************** -SQreamDB Acceleration Studio +Acceleration Studio ******************************** The SQreamDB Acceleration Studio 5.8.0 is a web-based client for use with SQreamDB. Studio provides users with all functionality available from the command line in an intuitive and easy-to-use format. This includes running statements, managing roles and permissions, and managing SQreamDB clusters. From 67a0ecb0caecec6d1063eaa26205969d99ac1c5c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jan 2024 12:30:03 +0200 Subject: [PATCH 1099/1892] Update 4.6.rst --- releases/4.6.rst | 92 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index d3495484f..01d8df1d9 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -4,7 +4,7 @@ Release Notes 4.6 ***************** -The 4.6 release notes were released on XXXXXXXXXXX +The 4.6 release notes were released on January XXX, 2023 .. contents:: :local: @@ -31,36 +31,78 @@ Compatibility Matrix | | * Spark | +-------------------------+------------------------------------------------------------------------+ +New Features and Enhancements +----------------------------- + +► + +Known Issues +------------ + +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.6 resolved Issues +--------------------------- -| SQ-11108 | Slow ``COPY FROM`` statements using ORC files | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-11804 | Slow metadata optimization | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12721 | ``maxConnectionInactivitySeconds`` flag issue when executing Batch Shell Program ETLs | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12799 | Catalog queries may not be terminated | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12965 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13112 | ``GRANT`` query queue issue | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13201 | ``INSERT INTO`` statement error while copying data from non-clustered table to clustered table | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13210, SQ-13426 | Slow query execution time | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13225 | LoopJoin performance enhancement supports ``=``, ``>``, ``<``, and ``<=`` operators | +| **SQ No.** | **Description** | ++====================+================================================================================================+ +| SQ-12872 | Fixed unexpected Worker behavior caused by ``DROP TABLE`` statement | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13322 | Cleanup operation case-sensitivity issue | +| SQ-12873 | Improved metadata key deletion time | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13401 | The JDBC driver causes the log summery of ``INSERT`` statements to fail | +| SQ-12965 | Fixed ``ReadParquet`` chunk producer output | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13453 | Metadata performance issue | +| SQ-13057 | Fixed ``DOUBLE`` casting into ``TEXT`` issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13461 | +| SQ-15691 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13467 | Snapshot issue causes metadata failure | +| SQ-15828 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13566, SQ-13694 | S3 access to bucket failure when using custom endpoint | +| SQ-16044 | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13587 | Large number of worker connections failure | -+--------------------+------------------------------------------------------------------------------------------------+ \ No newline at end of file + +Deprecations +------------------- + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +Upgrading to Version 4.6 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + $ select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + $ ./upgrade_storage <levelDB path> + +7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 5a7c4a195ec6c7fde3398339239464f78baf8197 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:23:12 +0200 Subject: [PATCH 1100/1892] 4.6 RN --- .../sql/sql_syntax/cross_database_query.rst | 166 ++++++++++++++++++ reference/sql/sql_syntax/index.rst | 4 +- releases/4.0_index.rst | 3 +- releases/4.6.rst | 9 +- 4 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 reference/sql/sql_syntax/cross_database_query.rst diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst new file mode 100644 index 000000000..c2ae4c51c --- /dev/null +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -0,0 +1,166 @@ +.. _cross_database_query: + +*************************** +Cross-Database Query +*************************** + +Cross-database queries allow the retrieval and manipulation of data from different databases within a single SQreamDB cluster, through the execution of a single SQL statement or transaction. This capability is crucial when information relevant to a query spans multiple databases. By specifying the database context and employing fully qualified object names, such as database.schema.table, it becomes possible to seamlessly integrate and analyze data distributed across diverse databases. + +To ensure optimal performance, it is advised to refrain from querying more than 10 databases in a single query. + + +Syntax +========== + +.. code-block:: sql + + -- SELECT statement + + SELECT + <column_name1>, + <column_name2>, + ... + FROM + <database_name>.<schema_name>.<table_name> AS <alias1> + JOIN + <database_name>.<schema_name>.<table_name> AS <alias2> + ON + <alias1>.<join_column> = <alias2>.<join_column> + WHERE + <condition1> + AND <condition2> + + -- CREATE TABLE statement + + CREATE TABLE + <database_name>.<schema_name>.<table_name> ( + <column_name1> <data_type1>, + <column_name2> <data_type2>, + ... + ) + + -- CREATE FOREIGN TABLE statement + + CREATE FOREIGN TABLE + <database_name>.<schema_name>.<table_name> ( + <column_name1> <data_type1>, + <column_name2> <data_type2>, + ... + ) + + -- ALTER TABLE statement + + ALTER TABLE + <database_name>.<schema_name>.<table_name> + ADD COLUMN + <new_column_name> <new_column_data_type> + + -- CREATE VIEW statement + + CREATE VIEW + <database_name>.<schema_name>.<view_name> (<column_name1>, <column_name2>, ...) + AS + SELECT + <alias1>.<column_name1>, + <alias1>.<column_name2>, + ... + FROM + <database_name1>.<schema_name1>.<table_name1> AS <alias1> + JOIN + <database_name2>.<schema_name2>.<table_name2> AS <alias2> + ON + <alias1>.<join_column> = <alias2>.<join_column> + WHERE + <condition1> + AND <condition2> + + -- INSERT INTO statement + + INSERT INTO + <database_name>.<schema_name>.<table_name> (<column_name1>, <column_name2>, ...) + VALUES + (<value1>, <value2>, ...) + + -- UPDATE statement + + UPDATE + <database_name>.<schema_name>.<table_name> + SET + <column_name1> = <new_value1>, + <column_name2> = <new_value2> + WHERE + <condition> + + -- DELETE statement + + DELETE FROM + <database_name>.<schema_name>.<table_name> + WHERE + <condition> + + -- TRUNCATE TABLE statement + + TRUNCATE TABLE + <database_name>.<schema_name>.<table_name> + + -- DROP TABLE statement + + DROP TABLE + <database_name>.<schema_name>.<table_name> + + +Parameters +=========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``column_name`` + - The name of a specific column to read or write data from + * - ``database_name`` + - The name of a specific database to read or write data from + * - ``schema_name`` + - The name of a specific schema to read or write data within + * - ``table_name`` + - The name of a specific table to read or write data from + * - ``condition`` + - The condition for performing a specific operation + +Examples +========= + +Querying data from two tables in different databases: + +.. code-block:: sql + + SELECT * + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; + +Querying data from two tables in different schemas and databases: + +.. code-block:: sql + + SELECT * + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active'; + +Querying data from three tables in different databases: + +.. code-block:: sql + + SELECT t1.*, t2.*, t3.* + FROM database1.schema1.table1 t1 + JOIN database2.schema2.table2 t2 + ON t1.id = t2.id + JOIN database3.schema3.table3 t3 + ON t2.id = t3.id + WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; + diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index cced92a61..55792fa8c 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -9,7 +9,7 @@ SQreamDB supports SQL from the ANSI 92 syntax. .. list-table:: :widths: auto :header-rows: 1 - + * - Features - Description * - :ref:`keywords_and_identifiers` @@ -18,6 +18,8 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Literals are fixed values representing specific data types, such as numbers or strings, used directly in SQL statements. * - :ref:`scalar_expressions` - Scalar expressions are single-value computations that operate on one or more values to produce a single result. + * - :ref:`cross_database_query` + - Cross-database queries involve accessing and manipulating data from multiple databases within a single SQL statement or operation. * - :ref:`joins` - Joins combine rows from two or more tables based on a related column to retrieve data from multiple sources in a single result set. * - :ref:`common_table_expressions` diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 785ee501b..c43fb9593 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -17,4 +17,5 @@ 4.2 4.3 4.4 - 4.5 \ No newline at end of file + 4.5 + 4.6 \ No newline at end of file diff --git a/releases/4.6.rst b/releases/4.6.rst index 01d8df1d9..f03ff7766 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► +► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. Known Issues ------------ @@ -55,13 +55,12 @@ Version 4.6 resolved Issues +--------------------+------------------------------------------------------------------------------------------------+ | SQ-13057 | Fixed ``DOUBLE`` casting into ``TEXT`` issue | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15691 | +| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15828 | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16044 | +| SQ-15828 | Fixed slow query runtime due to ``VIEW`` unexpected behavior | +--------------------+------------------------------------------------------------------------------------------------+ + Deprecations ------------------- From 3a5660e36f7235debffb9e74406456e311c7af95 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jan 2024 16:24:45 +0200 Subject: [PATCH 1101/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index f03ff7766..014a1cc1b 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -49,7 +49,7 @@ Version 4.6 resolved Issues +====================+================================================================================================+ | SQ-12872 | Fixed unexpected Worker behavior caused by ``DROP TABLE`` statement | +--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12873 | Improved metadata key deletion time | +| SQ-12873 | Improved the time it takes to delete metadata keys | +--------------------+------------------------------------------------------------------------------------------------+ | SQ-12965 | Fixed ``ReadParquet`` chunk producer output | +--------------------+------------------------------------------------------------------------------------------------+ From 4b53bc7a635714692f8cdb985e5220575249f3e3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Jan 2024 16:16:24 +0200 Subject: [PATCH 1102/1892] 4.6 RN --- .../current_method_configuration_levels.rst | 8 +- reference/sql/sql_functions/index.rst | 16 +++- .../conversion/is_castable.rst | 92 +++++++++++++++++++ .../sql_functions/scalar_functions/index.rst | 5 +- .../sql_statements/dml_commands/copy_from.rst | 8 +- releases/4.6.rst | 10 +- 6 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 834dce3ff..5b05e103a 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -36,7 +36,7 @@ Flag List - Cluster / Session - Description - Data Type - - Default Value + - Default Value and Value Range * - ``binSizes`` - SUPERUSER - Session @@ -302,6 +302,12 @@ Flag List - Prevents a query from processing more memory than the defined value. - uint - ``100000`` + * - ``queueTimeoutMinutes`` + - Anyone + - Session + - Terminates queries that have exceeded a predefined time limit in the queue. + - integer + - Default value: 0. Minimum values: 1 minute. Maximum value: 4320 minutes (72 hours) * - ``QueryTimeoutMinutes`` - Anyone - Session diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 30495bd6a..692a84be4 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -13,7 +13,8 @@ Summary of Functions :local: Built-In Scalar Functions -------------------- +-------------------------- + For more information about built-in scalar functions, see :ref:`scalar_functions`. Bitwise Operations @@ -42,6 +43,7 @@ The following table shows the **bitwise operations** functions: Conditionals ^^^^^^^^^^^^^^ + The following table shows the **conditionals** functions: .. list-table:: @@ -67,6 +69,7 @@ The following table shows the **conditionals** functions: Conversion ^^^^^^^^^^^^ + The following table shows the **conversion** functions: .. list-table:: @@ -83,9 +86,12 @@ The following table shows the **conversion** functions: - Converts a ``DATE`` or ``DATETIME`` to a UNIX Timestamp * - :ref:`chr` - Returns the ASCII character representation of the supplied integer + * - :ref:`is_castable` + - Checks whether a cast operation is possible or supported for a given column and data type and provides an alternative when there is an exception Date and Time ^^^^^^^^^^^^^^^^ + The following table shows the **date and time** functions: .. list-table:: @@ -119,6 +125,7 @@ The following table shows the **date and time** functions: Numeric ^^^^^^^^^^^ + The following table shows the **arithmetic operators**: .. list-table:: Arithmetic Operators @@ -209,6 +216,7 @@ The following table shows the **arithmetic operator** functions: Strings ^^^^^^^^^^^ + The following table shows the **string** functions: .. list-table:: @@ -273,12 +281,14 @@ The following table shows the **string** functions: - Returns an ``INT`` value representing the ASCII code of the leftmost character in a string User-Defined Scalar Functions ---------------------- +------------------------------ + For more information about user-defined scalar functions, see :ref:`scalar_sql_udf`. Aggregate Functions --------------------- + The following table shows the **aggregate** functions: .. list-table:: @@ -329,6 +339,7 @@ For more information about aggregate functions, see :ref:`aggregate_functions`. Window Functions ------------------- + The following table shows the **window** functions: .. list-table:: @@ -368,6 +379,7 @@ For more information about window functions, see :ref:`window_functions`. Workload Management Functions --------------------------------- + The following table shows the **workload management** functions: .. list-table:: diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst new file mode 100644 index 000000000..975887a80 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -0,0 +1,92 @@ +.. _is_castable: + +************ +IS CUSTABLE +************ + +The ``IsCastable`` function checks whether a cast operation is possible or supported for the given column and data type. If the cast is not supported, the ``CASE`` statement handles the exception by providing an alternative. + +Syntax +====== + +.. code-block:: sql + + -- Checks if a cast is supported + + SELECT + IsCastable( + <column_name>, + BOOL + | TINYINT + | SMALLINT + | INT + | BIGINT + | REAL + | DOUBLE + | TEXT + | NUMERIC + | DATE + | DATETIME + ) + FROM + <table_name>; + + -- Returns query result set + + SELECT + <colum_mame>, + CASE + WHEN IsCastable( + <colum_mame>, + BOOL + | TINYINT + | SMALLINT + | INT + | BIGINT + | REAL + | DOUBLE + | TEXT + | NUMERIC + | DATE + | DATETIME + ) + THEN + <colum_mame> :: + BOOL + | TINYINT + | SMALLINT + | INT + | BIGINT + | REAL + | DOUBLE + | TEXT + | NUMERIC + | DATE + | DATETIME + ELSE <expression> + END + FROM + <table_mame>; + +Return +======= + +``IsCastable`` returns: + +* ``true`` when the cast is supported +* ``false`` if the cast is not supported +* Your query result set if used within a ``CASE`` statement + +Example +======= + +.. code-block:: sql + + SELECT number, + CASE + WHEN IsCastable(number, DOUBLE) THEN number :: DOUBLE + ELSE NULL + END + FROM + my_numbers; + diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index 94c1db412..6183682ad 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -1,8 +1,9 @@ .. _scalar_functions: -**************** +*************************** Built-In Scalar Functions -**************** +*************************** + The **Built-In Scalar Functions** page describes functions that return one value per call: .. hlist:: diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 111949c83..d4910b75a 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -60,6 +60,8 @@ Syntax | AWS_ID = '{ AWS ID }' | AWS_SECRET = '{ AWS Secret }' + + | DELETE_SOURCE_ON_SUCCESS = { true | false } offset ::= positive integer @@ -155,7 +157,7 @@ Elements * - ``CONTINUE_ON_ERROR`` - ``false`` - - true, false + - ``true`` | ``false`` - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction will continue despite rejected data. @@ -176,6 +178,10 @@ Elements - None - - Specifies the authentication details for secured S3 buckets + * - ``DELETE_SOURCE_ON_SUCCESS`` + - ``false`` + - ``true`` | ``false`` + - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``ERROR_COUNT`` and ``LIMIT`` parameters. .. _copy_date_parsers: diff --git a/releases/4.6.rst b/releases/4.6.rst index 014a1cc1b..24a2aead2 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -36,6 +36,12 @@ New Features and Enhancements ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning cloud storage but also helps conserve storage space. + +► Cast data types seamlessly with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + Known Issues ------------ @@ -75,7 +81,7 @@ Upgrading to Version 4.6 .. code-block:: console - $ select backup_metadata('out_path'); + select backup_metadata('out_path'); .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. @@ -93,7 +99,7 @@ Upgrading to Version 4.6 .. code-block:: console - $ ./upgrade_storage <levelDB path> + ./upgrade_storage <levelDB path> 7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. From 87d0acae63745acdc405a757e9f2428a8f7a55ec Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jan 2024 11:32:08 +0200 Subject: [PATCH 1103/1892] Update ingesting_data.rst --- data_ingestion/ingesting_data.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index 0fedaec14..2e3f70856 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -30,6 +30,8 @@ SQream supports loading files from the following formats: * Text - CSV, TSV, and PSV * Parquet * ORC +*Avro +*JSON For more information, see the following: From 86af3d8a4baaef26cd3ae46c9c4103700534694b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jan 2024 11:34:24 +0200 Subject: [PATCH 1104/1892] Update ingesting_data.rst --- data_ingestion/ingesting_data.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index 2e3f70856..e069b25be 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -30,8 +30,8 @@ SQream supports loading files from the following formats: * Text - CSV, TSV, and PSV * Parquet * ORC -*Avro -*JSON +* Avro +* JSON For more information, see the following: From e4260e7e548a2bedbbdb4364f5b318d9c1c28456 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 08:11:36 +0200 Subject: [PATCH 1105/1892] Update foreign_tables.rst --- operational_guides/foreign_tables.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 42730434c..0dfe8a41a 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -3,6 +3,7 @@ *********************** Foreign Tables *********************** + Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. SQream DB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. @@ -12,9 +13,11 @@ Although foreign tables can be used without inserting data into SQream DB, one o .. contents:: In this topic: :local: + :depth: 1 Supported Data Formats ===================================== + SQream DB supports foreign tables over: * Text files (e.g. CSV, PSV, TSV) @@ -23,6 +26,7 @@ SQream DB supports foreign tables over: Supported Data Staging ============================================ + SQream can stage data from: * a local filesystem (e.g. ``/mnt/storage/....``) @@ -31,6 +35,7 @@ SQream can stage data from: Using Foreign Tables ============================================== + Use a foreign table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging @@ -43,6 +48,7 @@ We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_ Creating a Foreign Table ----------------------------- + Based on the source file structure, we :ref:`create a foreign table<create_external_table>` with the appropriate structure, and point it to the file. .. code-block:: postgres @@ -90,6 +96,7 @@ Let's peek at the data from the foreign table: Modifying Data from Staging ------------------------------- + One of the main reasons for staging data is to examine the content and modify it before loading. Assume we are unhappy with weight being in pounds because we want to use kilograms instead. We can apply the transformation as part of a query: @@ -140,6 +147,7 @@ Converting a Foreign Table to a Standard Database Table Error Handling and Limitations ================================== + * Error handling in foreign tables is limited. Any error that occurs during source data parsing will result in the statement aborting. * From 5cc3335d51d5d104bab99103e9bda336aa667956 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 08:18:26 +0200 Subject: [PATCH 1106/1892] Update foreign_tables.rst --- operational_guides/foreign_tables.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 0dfe8a41a..c22156a1c 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -20,9 +20,11 @@ Supported Data Formats SQream DB supports foreign tables over: -* Text files (e.g. CSV, PSV, TSV) -* ORC +* Text - CSV, TSV, and PSV * Parquet +* ORC +* Avro +* JSON Supported Data Staging ============================================ @@ -65,10 +67,12 @@ Based on the source file structure, we :ref:`create a foreign table<create_exter College varchar, Salary float ) - USING FORMAT CSV -- Text file - WITH PATH 's3://sqream-demo-data/nba_players.csv' - RECORD DELIMITER '\r\n'; -- DOS delimited file - + WRAPPER csv_fdw + OPTIONS + ( LOCATION = 's3://sqream-demo-data/nba_players.csv', + DELIMITER = '\r\n' -- DOS delimited file + ); + The file format in this case is CSV, and it is stored as an :ref:`s3` object (if the path is on :ref:`hdfs`, change the URI accordingly). We also took note that the record delimiter was a DOS newline (``\r\n``). From 23af59550893b935613dcda5ab95a33bb3977a98 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:17:19 +0200 Subject: [PATCH 1107/1892] Update query_split.rst --- operational_guides/query_split.rst | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index e460b59c1..d953f5c07 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -1,8 +1,8 @@ .. _query_split: -**************************** +************ Query Split -**************************** +************ The split query operation optimizes long-running queries by executing them in parallel on different GPUs, reducing overall runtime. This involves breaking down a complex query into parallel executions on small data subsets. To ensure an ordered result set aligned with the original complex query, two prerequisites are essential. First, create an empty table mirroring the original result set's structure. Second, define the ``@@SetResult`` operator to split the query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column, as these types are compatible with the operator's ``min`` and ``max`` variables. @@ -47,9 +47,9 @@ Defining the ``@@setresult`` operator to split the original query using an ``INT -- Integer Range: 1 AND 100 | -- Date Range: - '2022-01-01' AND '2022-12-31' + 'yyyy-mm-dd' AND 'yyyy-mm-dd' | -- DateTime Range: - '2022-01-01 01:24:00:000' AND '2022-12-31 08:51:24:000'] + 'yyyy-mm-dd hh:mm:ss:SSS' AND 'yyyy-mm-dd hh:mm:ss:SSS'] Defining the operator that determines the number of instances (splits) based on the data type of the column by which the query is split: @@ -80,7 +80,7 @@ Defining the operator that determines the number of instances (splits) based on FROM <my_table> WHERE - <column_to_split_by> BETWEEN ${from} and ${to} + <column_to_split_by> BETWEEN '${from}' and '${to}' ) * **DATETIME column:** use the ``@@SplitQueryByDateTime`` operator @@ -348,18 +348,6 @@ Date as Number best practices When date is stored as number, using the number of workers as the instances number may not result in the expected way. e.g. if date run from 20210101 to 20210630 splitting to 8 will result in 6 relevant splits, as SQream only checks min and max and splits accordingly (20210630-20210101)/8. we get an instance of empty data with dates ranging from 20210432 to 20210499 (not really dates, but real numbers). In this case, we need to adjust the number of instance to get the right size splits. In the above example we need to split to 64, and each worker will run 3 splits with actual data. - -Using the ``SetResult`` -------------------------- - -When the column you split by is used in a ``WHERE`` clause in the original query, add it with the ``WHERE`` clause when you set the ``SetResult`` operator. - -.. code-block:: - - @@ SetResult minMax - SELECT min(ship_dates) AS min, max(ship_dates) AS max FROM shipments - /*optional - WHERE ship_dates BETWEEN '1995-01-01' AND '1996-01-01'*/ - ; Include? ----------- From b4f8bf21fc6cd784a343959514f78986cb3bb655 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:18:01 +0200 Subject: [PATCH 1108/1892] Update query_split.rst --- operational_guides/query_split.rst | 9 --------- 1 file changed, 9 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index d953f5c07..d3b33e01a 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -349,15 +349,6 @@ When date is stored as number, using the number of workers as the instances numb e.g. if date run from 20210101 to 20210630 splitting to 8 will result in 6 relevant splits, as SQream only checks min and max and splits accordingly (20210630-20210101)/8. we get an instance of empty data with dates ranging from 20210432 to 20210499 (not really dates, but real numbers). In this case, we need to adjust the number of instance to get the right size splits. In the above example we need to split to 64, and each worker will run 3 splits with actual data. -Include? ------------ - -* Setting the column boundaries for the split - This is an optional query, but very useful, and can only be optional if you know in advance the boundaries. - -* The query that outputs the results from the table we created in the first query - This is an optional query, but most use cases will require have it and if we created the first query and used INSERT INTO in the splitting we have to use it. - -* Limit and group by together, can significantly reduce runtime. - From 6c3cc31834d928d28238c2607a11b95d92ba0ee9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:11:07 +0200 Subject: [PATCH 1109/1892] Update query_split.rst --- operational_guides/query_split.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index d3b33e01a..5fe1228c6 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -229,13 +229,14 @@ Splitting the Query .. code-block:: sql - CREATE OR TABLE FinalResult + CREATE OR REPLACE TABLE FinalResult AS ( SELECT age, COUNT(*) AS total_people, - AVG(salary) AS avg_salary, + SUM(salary) AS avg_salary, + COUNT(salary) AS avg_salary2, SUM(quantity) AS total_quantity, SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 @@ -269,7 +270,8 @@ Splitting the Query SELECT age, COUNT(*) AS total_people, - AVG(salary) AS avg_salary, + SUM(salary) AS avg_salary, + COUNT(salary) AS avg_salary2, SUM(quantity) AS total_quantity, SUM(CASE WHEN quantity > 20 THEN 1 ELSE 0 END) AS high_quantity_count, SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 @@ -291,7 +293,7 @@ Splitting the Query SELECT age, SUM(total_people) AS total_people, - SUM(avg_salary) / SUM(avg_salary) AS avg_salary, + SUM(avg_salary) / SUM(avg_salary2) AS avg_salary, SUM(total_quantity) AS total_quantity, SUM(high_quantity_count) AS high_quantity_count, SUM(total_salary_age_25_30) AS total_salary_age_25_30 @@ -319,7 +321,9 @@ Best Practices General -------- -* When incorporating the ``LIMIT`` clause or any aggregate function in your query, split the query based only on a ``GROUP BY`` column. If no relevant columns are present in the ``GROUP BY`` clause, the query might not be suitable for splitting. If you are not using aggregations, it's best to split the query using a column that appears in the a ``WHERE`` or ``JOIN`` clause. +* When incorporating the ``LIMIT`` clause or any aggregate function in your query, split the query based only on a ``GROUP BY`` column. If no relevant columns are present in the ``GROUP BY`` clause, the query might not be suitable for splitting. + +* If you are not using aggregations, it's best to split the query using a column that appears in the a ``WHERE`` or ``JOIN`` clause. * When using the ``JOIN`` key, it is usually better to use the key of the smaller table. @@ -337,10 +341,13 @@ Aggregation functions, or special functions need to have adjustments in the quer * ``COUNT`` becomes ``SUM`` -* ``AVERAGE`` is split into two columns in the split query and then merged as ``AVERAGE`` in the output query +* The following statement and functions are split into two columns in the query split and then merged to be executed as one statement or function in the final query: + * ``AVERAGE`` + * User defined functions + * Variance functions + * Standard deviation functions -Special functions should be split into different columns as well - **What special functions?** Date as Number best practices ------------------------------- From f7041d5b751232b623d0415d0559ca22f99cc43a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:24:00 +0200 Subject: [PATCH 1110/1892] Update query_split.rst --- operational_guides/query_split.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 5fe1228c6..c40b5ad72 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -348,7 +348,6 @@ Aggregation functions, or special functions need to have adjustments in the quer * Variance functions * Standard deviation functions - Date as Number best practices ------------------------------- From 492d3f267e1ee16d7626c924d24f1d12f5340960 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 11:46:30 +0200 Subject: [PATCH 1111/1892] Update query_split.rst --- operational_guides/query_split.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index c40b5ad72..4cae5fb65 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -4,7 +4,7 @@ Query Split ************ -The split query operation optimizes long-running queries by executing them in parallel on different GPUs, reducing overall runtime. This involves breaking down a complex query into parallel executions on small data subsets. To ensure an ordered result set aligned with the original complex query, two prerequisites are essential. First, create an empty table mirroring the original result set's structure. Second, define the ``@@SetResult`` operator to split the query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column, as these types are compatible with the operator's ``min`` and ``max`` variables. +The split query operation optimizes long-running queries by executing them in parallel on different GPUs and/or Workers, reducing overall runtime. This involves breaking down a complex query into parallel executions on small data subsets. To ensure an ordered result set aligned with the original complex query, two prerequisites are essential. First, create an empty table mirroring the original result set's structure. Second, define the ``@@SetResult`` operator to split the query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column, as these types are compatible with the operator's ``min`` and ``max`` variables. Splitting is exclusive to the UI, utilizing Meta-scripting, a unique UI feature. Keep in mind that not all queries benefit, as this method introduces overhead runtime. From df74014dc3acd3b2448274962bdea5138c52a8d9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 12:05:26 +0200 Subject: [PATCH 1112/1892] Update query_split.rst --- operational_guides/query_split.rst | 33 ++++++++++++------------------ 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 4cae5fb65..e6e763abd 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -23,14 +23,11 @@ Creating an empty table mirroring the original query result set's structure usin AS ( SELECT - <column_to_split_by> [,...] - FROM - <my_table> + -- Original query.. WHERE <false_filter> ) - - -- A false_filter example: 1=2 + -- A false_filter example: 1=2 Defining the ``@@setresult`` operator to split the original query using an ``INTEGER``, ``DATE``, or ``DATETIME`` column with ``min`` and ``max`` variables. If the column you're splitting by is used in a ``WHERE`` clause in the original query, use a ``WHERE`` clause when setting the ``SetResult`` operator as well. @@ -60,12 +57,10 @@ Defining the operator that determines the number of instances (splits) based on @@SplitQueryByNumber instances = <number of instances>, from = minMax[0].min, to = minMax[0].max INSERT INTO <final_result_table> ( - SELECT - <column_to_split_by> [,...] - FROM - <my_table> - WHERE - <column_to_split_by> BETWEEN ${from} and ${to} + SELECT + -- Original query.. + WHERE + <column_to_split_by> BETWEEN '${from}' and '${to}' ) * **DATE column:** use the ``@@SplitQueryByDate`` operator @@ -76,9 +71,7 @@ Defining the operator that determines the number of instances (splits) based on INSERT INTO <final_result_table> ( SELECT - <column_to_split_by> [,...] - FROM - <my_table> + -- Original query.. WHERE <column_to_split_by> BETWEEN '${from}' and '${to}' ) @@ -91,10 +84,8 @@ Defining the operator that determines the number of instances (splits) based on INSERT INTO <final_result_table> ( SELECT - <column_to_split_by> [,...] - FROM - <my_table> - WHERE <column_to_split_by> BETWEEN ${from} and ${to} + -- Original query.. + WHERE <column_to_split_by> BETWEEN '${from}' and '${to}' ) Outputting the results of your small queries by running a query that gathers the results of all small queries into the initially created empty table. @@ -256,7 +247,7 @@ Splitting the Query .. code-block:: sql @@ SetResult minMax - SELECT min(id) as min, max(id) as max + SELECT min(age) as min, max(age) as max FROM mytable ; @@ -278,13 +269,15 @@ Splitting the Query FROM MyTable WHERE - id between ${from} and ${to} + age between ${from} and ${to} AND salary > 55000 GROUP BY age ORDER BY age ); + + -- SELECT * FROM FinalResult ; 4. Create a query that gathers the results of all instances (splits) into the empty table you created in step 1. From 23bf69bd7d9707edf1e66c5bc807f73c4e3a0bb6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:54:07 +0200 Subject: [PATCH 1113/1892] Update query_split.rst --- operational_guides/query_split.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index e6e763abd..0ebc87e9d 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -276,10 +276,15 @@ Splitting the Query ORDER BY age ); - - -- SELECT * FROM FinalResult ; -4. Create a query that gathers the results of all instances (splits) into the empty table you created in step 1. +4. Gather the results of your query. + +.. code-block:: sql + + SELECT * FROM FinalResult ; + +If we were to split the query +Create a query that gathers the results of all instances (splits) into the empty table you created in step 1. .. code-block:: sql @@ -320,8 +325,6 @@ General * When using the ``JOIN`` key, it is usually better to use the key of the smaller table. -* For simple queries involving just one table, splitting is unlikely to enhance performance. - Choosing a Column to Split by ------------------------------ From 977879f7020122640eaa5babf3a94d314fe31ad0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:55:47 +0200 Subject: [PATCH 1114/1892] Update query_split.rst --- operational_guides/query_split.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 0ebc87e9d..c9eca50fc 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -303,15 +303,15 @@ Create a query that gathers the results of all instances (splits) into the empty age ; -5. Arrange ALL five sequential scripts on one Editor tab. +5. Arrange ALL sequential scripts on one Editor tab. 6. Ensure that EACH script ends with a ``;``. -7. Ensure that the **Execute** button is set to **All** so that all five queries are consecutively executed. +7. Ensure that the **Execute** button is set to **All** so that all queries are consecutively executed. 8. Select the **Execute** button. - All five scripts are executed, resulting in the splitting of the initial query and a table containing the final result set. + All scripts are executed, resulting in the splitting of the initial query and a table containing the final result set. Best Practices ================ From 65f2c6687cbe1e148cce53f36db7ad4a7bf5d85f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:24:20 +0200 Subject: [PATCH 1115/1892] Update query_split.rst --- operational_guides/query_split.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index c9eca50fc..1f2f68f0a 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -88,18 +88,20 @@ Defining the operator that determines the number of instances (splits) based on WHERE <column_to_split_by> BETWEEN '${from}' and '${to}' ) -Outputting the results of your small queries by running a query that gathers the results of all small queries into the initially created empty table. +Gathering results: .. code-block:: sql - - -- Basic execution for queries which do not use aggregations: + + -- Gathering results for queries without aggregations: SELECT * FROM <final_result_table> ; - -- Execution for queries which use aggregations: + -- Gathering results for queries with aggregations and/or AVERAGE statement: + + - AVERAGE: SELECT <column1>, [,...], From 5290fbc028691853db8ff4ad4d518d2cf02b59ff Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 14:54:26 +0200 Subject: [PATCH 1116/1892] Update is_castable.rst --- .../conversion/is_castable.rst | 46 ++++++++++++++++--- 1 file changed, 40 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst index 975887a80..99224c365 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -11,11 +11,10 @@ Syntax .. code-block:: sql - -- Checks if a cast is supported + -- Checking if a cast is supported for literal value: SELECT IsCastable( - <column_name>, BOOL | TINYINT | SMALLINT @@ -23,15 +22,50 @@ Syntax | BIGINT | REAL | DOUBLE + | FLOAT | TEXT | NUMERIC | DATE | DATETIME - ) + | ARRAY + , BOOL + | TINYINT + | SMALLINT + | INT + | BIGINT + | REAL + | DOUBLE + | FLOAT + | TEXT + | NUMERIC + | DATE + | DATETIME + | ARRAY + ) + + -- Checking if cast is supported for columns: + + SELECT + IsCastable( + <column_name>, + BOOL + | TINYINT + | SMALLINT + | INT + | BIGINT + | REAL + | DOUBLE + | FLOAT + | TEXT + | NUMERIC + | DATE + | DATETIME + | ARRAY + ) FROM <table_name>; - -- Returns query result set + -- Returns query result set SELECT <colum_mame>, @@ -73,8 +107,8 @@ Return ``IsCastable`` returns: -* ``true`` when the cast is supported -* ``false`` if the cast is not supported +* 1 when the cast is supported +* 0 if the cast is not supported * Your query result set if used within a ``CASE`` statement Example From f5e5ef1741def4b3c6a2fd0099efb08a37d2629e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jan 2024 15:20:29 +0200 Subject: [PATCH 1117/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index d4910b75a..97b47403f 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -181,7 +181,7 @@ Elements * - ``DELETE_SOURCE_ON_SUCCESS`` - ``false`` - ``true`` | ``false`` - - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``ERROR_COUNT`` and ``LIMIT`` parameters. + - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``OFFSET``, ``ERROR_LOG``, ``REJECTED_DATA``, ``ERROR_COUNT`` and ``LIMIT`` parameters. This parameter is supported for AWS, HADOOP, and GCP. You may only use this parameter with files you have permission to delete. .. _copy_date_parsers: From df4e452f03ada7d583137d7ceee98c2ec9388f25 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 10:53:17 +0200 Subject: [PATCH 1118/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 89 +++++++++++-------- 1 file changed, 52 insertions(+), 37 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 8e4469da2..c0d086196 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -31,12 +31,16 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE FUNCTION`` | Create and drop functions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All database permissions except for a SUPERUSER permission | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Schema** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Grants access to schema objects | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create tables in the schema | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All schema permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Table** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | :ref:`select` from the table | @@ -49,7 +53,7 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Drop and alter on the table | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | All the table permissions | +| ``ALL`` | All table permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Function** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -71,20 +75,28 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Foreign table DDL operations | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All foreign table permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Column** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Column DDL operations | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All column permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Catalog** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All catalog permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Services** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Using a specific service | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All services permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ Syntax ====== @@ -96,7 +108,7 @@ GRANT .. code-block:: postgres - -- Grant permissions at the instance/ storage cluster level: + -- Grant permissions to all databases: GRANT { SUPERUSER @@ -108,38 +120,35 @@ GRANT -- Grant permissions at the database level: GRANT { - { CREATE + CREATE | CONNECT | DDL | SUPERUSER | CREATE FUNCTION } [, ...] | ALL [PERMISSIONS] - } ON DATABASE <database> [, ...] TO <role> [, ...] -- Grant permissions at the schema level: GRANT { - { CREATE + CREATE | DDL | USAGE | SUPERUSER } [, ...] - | ALL [PERMISSIONS] - } + | ALL [PERMISSIONS] ON SCHEMA <schema> [, ...] TO <role> [, ...] -- Grant permissions at the object level: GRANT { - { SELECT + SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] | ALL [PERMISSIONS] - } ON { TABLE <table_name> [, ...] @@ -151,28 +160,28 @@ GRANT } TO <role> [, ...] + -- Grant permissions at the catalog level: GRANT { - { SELECT + SELECT | INSERT | DELETE | UPDATE } [, ...] | ALL [PERMISSIONS] - } ON { - | CATALOG <catalog_name> [, ...] + CATALOG <catalog_name> [, ...] } TO <role> [, ...] - -- Grant execute function permission: + -- Grant function execution permission: GRANT { ALL | EXECUTE | DDL } - ON FUNCTION function_name + ON FUNCTION <function_name> TO role; -- Grant permissions at the column level: @@ -184,10 +193,14 @@ GRANT } ON { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] - | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + COLUMN <column_name> [, ...] + | ALL COLUMNS } + IN + { + TABLE <table_name> [, ...] + | FOREIGN TABLE <foreign_table_name> [, ...] + | VIEW <view_name> [, ...] + | CATALOG <catalog_name> [, ...] } TO <role> [, ...] @@ -213,7 +226,7 @@ REVOKE .. code-block:: postgres - -- Revoke permissions at the instance/ storage cluster level: + -- Revoke permissions from all databases: REVOKE { SUPERUSER @@ -225,63 +238,65 @@ REVOKE -- Revoke permissions at the database level: REVOKE { - { CREATE + CREATE | CONNECT | DDL | SUPERUSER - | CREATE FUNCTION }[, ...] + | CREATE FUNCTION } [, ...] | ALL [PERMISSIONS] - } - ON DATABASE <database> [, ...] + ON DATABASE <database_name> [, ...] FROM <role> [, ...] -- Revoke permissions at the schema level: REVOKE { - { CREATE + CREATE | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS] - } - ON SCHEMA <schema> [, ...] + ON SCHEMA <schema_name> [, ...] FROM <role> [, ...] -- Revoke permissions at the object level: REVOKE { - { SELECT + SELECT | INSERT | DELETE | DDL | UPDATE } [, ...] - | ALL - } + | ALL [PERMISSIONS] ON { - [ TABLE ] <table_name> [, ...] - | ALL TABLES IN SCHEMA <schema_name> [, ...] + TABLE <table_name> [, ...] + | ALL TABLES [, ...] | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS IN SCHEMA <schema_name> [, ...] + | ALL VIEWS [, ...] | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] + | ALL FOREIGN TABLES [, ...] + IN SCHEMA <schema_name> [, ...] } FROM <role> [, ...] + -- Revoke permissions at the catalog level: REVOKE { - { SELECT + SELECT | INSERT | DELETE | UPDATE } [, ...] - | ALL - } + | ALL [PERMISSIONS] ON { - | CATALOG <catalog_name> [, ...] + CATALOG <catalog_name> [, ...] } FROM <role> [, ...] + -- Revoke permissions at the function execution level: + REVOKE + { + -- Revoke permissions at the column level: REVOKE { From 47cf9e087cde77852a3a2e7cdb67b215d2c7a9b5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 11:42:31 +0200 Subject: [PATCH 1119/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 34 +++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index d39924684..de11e8435 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -10,12 +10,12 @@ In general, you should not need to run ``metadata_server`` manually, but it is s This page serves as a reference for the options and parameters. -Positional command line arguments -=================================== +Positional Command Line Arguments +================================== .. code-block:: console - $ metadata_server [ <logging path> [ <listen port> ] ] + metadata_server [ <logging path> [ <listen port> ] ] .. list-table:: :widths: auto @@ -24,23 +24,39 @@ Positional command line arguments * - Argument - Default - Description + * - ``--log_path`` + - ``./metadata_server_log`` + - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. + * - ``--log4_config`` + - None + - Specifies the location of the configuration file for the ``Log4cxx`` logging library. + * - ``--num_deleters`` + - 1 + - Specifies the number of threads to use for the file reaper in a system or program. + * - ``--metadata_path`` + - ``<...sqreamd/leveldb>`` + - Specifies the path to the directory where metadata files are stored for a system or program. + * - ``--help`` + - None + - Used to display a help message or documentation for a particular program or command. * - Logging path - Current directory - Path to store metadata logs into * - Listen port - ``3105`` - TCP listen port. If used, log path must be specified beforehand. + Starting metadata server ============================ Starting temporarily ------------------------------ +--------------------- .. code-block:: console - $ nohup metadata_server & - $ MS_PID=$! + nohup metadata_server -config ~/.sqream/metadata_server_config.json & + MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. @@ -55,15 +71,15 @@ To use a non-default port, specify the logging path as well. .. code-block:: console - nohup metadata_server --log_path=/home/rhendricks/metadata_logs --port=9241 & - $ MS_PID=$! + nohup metadata_server --log_path=/home/rhendricks/metadata_logs 9241 & + MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. .. note:: * Logs are saved to the ``/home/rhendricks/metadata_logs`` directory. * The listening port is 9241 - + Stopping metadata server ---------------------------- From a8997f0521462ef9b53270244088b4e81bc54aea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:12:01 +0200 Subject: [PATCH 1120/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index de11e8435..aae060da9 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -13,17 +13,19 @@ This page serves as a reference for the options and parameters. Positional Command Line Arguments ================================== -.. code-block:: console - - metadata_server [ <logging path> [ <listen port> ] ] - .. list-table:: - :widths: auto + :widths: 2 3 5 :header-rows: 1 * - Argument - Default - Description + * - ``--config`` + - ``/home/omert/.sqream/metadata_server_config.json`` + - The configuration file to use + * - ``--port`` + - ``3105`` + - The metadata_server listening port * - ``--log_path`` - ``./metadata_server_log`` - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. @@ -39,12 +41,6 @@ Positional Command Line Arguments * - ``--help`` - None - Used to display a help message or documentation for a particular program or command. - * - Logging path - - Current directory - - Path to store metadata logs into - * - Listen port - - ``3105`` - - TCP listen port. If used, log path must be specified beforehand. Starting metadata server @@ -71,7 +67,7 @@ To use a non-default port, specify the logging path as well. .. code-block:: console - nohup metadata_server --log_path=/home/rhendricks/metadata_logs 9241 & + nohup metadata_server --log_path=/home/rhendricks/metadata_logs --port=9241 & MS_PID=$! Using ``nohup`` and ``&`` sends metadata server to run in the background. @@ -87,6 +83,6 @@ To stop metadata server: .. code-block:: console - $ kill -9 $MS_PID + kill -9 $MS_PID .. tip:: It is safe to stop any SQream DB component at any time using ``kill``. No partial data or data corruption should occur when using this method to stop the process. From fa8af005075c4b3a44cb37a3a53c5d065696425e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 12:38:36 +0200 Subject: [PATCH 1121/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 57 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index bdc086c06..84e21749f 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -14,7 +14,7 @@ Syntax .. code-block:: console - $ server_picker [ <Metadata server address> <Metadata server port> ] [ <TCP listen port> ] [ <SSL listen port> ] [ <server picker services> ] [ <refresh_interval> ] [ <logging configuration file> ] + server_picker [ <Metadata server address> <Metadata server port> ] [ <TCP listen port> ] [ <SSL listen port> ] [ <server picker services> ] [ <refresh_interval> ] [ <logging configuration file> ] Parameters ------------ @@ -26,34 +26,37 @@ Parameters * - Argument - Default - Description - * - ``Metadata server address`` - - - - IP or hostname to an active :ref:`metadata server<metadata_server_cli_reference>` - * - ``Metadata server port`` - - - - TCP port to an active :ref:`metadata server<metadata_server_cli_reference>` - * - ``TCP listen port`` + * - ``--metadata_server_port`` + - ``3105`` + - The metadata server listening port + * - ``--metadata_server_ip`` + - ``127.0.0.1`` + - The metadata server IP + * - ``--port`` - ``3108`` - - TCP port for server picker to listen on - * - ``SSL listen port`` + - The server picker port + * - ``--ssl_port`` - ``3109`` - - SSL port for server picker to listen on - * - ``server picker services`` - - All services, unless specified otherwise - - Defines which Worker will accept compilation jobs according to services. Accepts 1 or more services separated using a comma - * - ``refresh_interval`` - - 15 seconds - - Examines worker availability based on the specified time interval - * - ``logging configuration file`` - - ``log4`` logging to default log path(/tmp/logs) - - Controls the format and destination of log output - + - The server picker ssl port + * - ``--log4_config`` + - ``/home/sqream/sqream3/etc/server_picker_log_properties`` + - The server picker log4 configuration file to use + * - ``--refresh_interval`` + - ``15`` + - Refresh interval time to check available nodes + * - ``--services`` + - None + - Lists services separated by comma + * - ``--help`` + - None + - Used to display a help message or documentation for a particular program or command + Example --------- .. code-block:: console - $ server_picker 127.0.0.1 3105 3118 3119 sqream23, sqream0 metadata_log_properties + server_picker 127.0.0.1 3105 3118 3119 sqream23, sqream0 metadata_log_properties Starting server picker ============================ @@ -67,8 +70,8 @@ Assuming we have a :ref:`metadata server<metadata_server_cli_reference>` listeni .. code-block:: console - $ nohup server_picker 127.0.0.1 3105 & - $ SP_PID=$! + nohup server_picker 127.0.0.1 3105 & + SP_PID=$! Using ``nohup`` and ``&`` sends server picker to run in the background. @@ -79,8 +82,8 @@ Tell server picker to listen on port 2255 for unsecured connections, and port 22 .. code-block:: console - $ nohup server_picker 127.0.0.1 3105 2255 2266 & - $ SP_PID=$! + nohup server_picker 127.0.0.1 3105 2255 2266 & + SP_PID=$! Using ``nohup`` and ``&`` sends server picker to run in the background. @@ -89,6 +92,6 @@ Stopping server picker .. code-block:: console - $ kill -9 $SP_PID + kill -9 $SP_PID .. tip:: It is safe to stop any SQream DB component at any time using ``kill``. No partial data or data corruption should occur when using this method to stop the process. From 4019487c5e3d927effcf7890423eb5fbdb2e2790 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 13:15:20 +0200 Subject: [PATCH 1122/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index c0d086196..cb8cacb90 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -296,21 +296,32 @@ REVOKE -- Revoke permissions at the function execution level: REVOKE { - + All + | EXECUTE + | DDL + } + ON FUNCTION <function_name> + FROM <role> [, ...] + -- Revoke permissions at the column level: REVOKE { - { SELECT + SELECT | DDL } [, ...] - | ALL [PERMISSIONS]} + | ALL [PERMISSIONS] ON { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] + COLUMN <column_name> [, ...] + | ALL COLUMNS } + IN + { + TABLE <table_name> [, ...] + | FOREIGN TABLE <foreign_table_name> [, ...] + | VIEW <view_name> [, ...] + | CATALOG <catalog_name> [, ...] } FROM <role> [, ...] - + -- Revoke permissions at the service level: REVOKE { @@ -344,13 +355,15 @@ schema statement is run. .. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR modifying_role - [IN schema_name, ...] + [IN schema_name [, ...] FOR { SCHEMAS | TABLES | FOREIGN TABLES | VIEWS | COLUMNS + | CATALOGS + | SERVICES | SAVED_QUERIES } { grant_clause From 66e1137384f48384e958b7ef66ffeaa2dbcd3d98 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 14:40:10 +0200 Subject: [PATCH 1123/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index aae060da9..130e03e3d 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -10,7 +10,7 @@ In general, you should not need to run ``metadata_server`` manually, but it is s This page serves as a reference for the options and parameters. -Positional Command Line Arguments +Command Line Arguments ================================== .. list-table:: @@ -25,7 +25,7 @@ Positional Command Line Arguments - The configuration file to use * - ``--port`` - ``3105`` - - The metadata_server listening port + - The metadata server listening port * - ``--log_path`` - ``./metadata_server_log`` - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. From 45d602dcf2e288330763c6c42816e3b5a4899146 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:30:30 +0200 Subject: [PATCH 1124/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index 84e21749f..b4a44af4a 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -6,15 +6,8 @@ Server Picker SQreamDB's load balancer is called ``server_picker``. -Positional command line arguments -=================================== - -Syntax -------- - -.. code-block:: console - - server_picker [ <Metadata server address> <Metadata server port> ] [ <TCP listen port> ] [ <SSL listen port> ] [ <server picker services> ] [ <refresh_interval> ] [ <logging configuration file> ] +Command Line Arguments +======================== Parameters ------------ @@ -56,7 +49,7 @@ Example .. code-block:: console - server_picker 127.0.0.1 3105 3118 3119 sqream23, sqream0 metadata_log_properties + server_picker --metadata_ip=127.0.0.1 --metadata_server_port=3105 --port=3118 --ssl_port=3119 --services=sqream23,sqream0 --log4_config=/home/sqream/metadata_log_properties --refresh_interval=10 Starting server picker ============================ @@ -70,7 +63,7 @@ Assuming we have a :ref:`metadata server<metadata_server_cli_reference>` listeni .. code-block:: console - nohup server_picker 127.0.0.1 3105 & + nohup server_picker --metadata_server_ip=127.0.0.1 metadata_server_port=3105 & SP_PID=$! Using ``nohup`` and ``&`` sends server picker to run in the background. @@ -82,7 +75,7 @@ Tell server picker to listen on port 2255 for unsecured connections, and port 22 .. code-block:: console - nohup server_picker 127.0.0.1 3105 2255 2266 & + nohup server_picker --metadata_server_ip=127.0.0.1 --metadata_server_port=3105 --port=2255 --ssl_port=2266 & SP_PID=$! Using ``nohup`` and ``&`` sends server picker to run in the background. From 313842812e86ba0c823ef5957f8f517047c05972 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:34:30 +0200 Subject: [PATCH 1125/1892] Update metadata_server.rst --- reference/cli/metadata_server.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 130e03e3d..1393d436a 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -8,8 +8,6 @@ SQream DB's cluster manager/coordinator is called ``metadata_server``. In general, you should not need to run ``metadata_server`` manually, but it is sometimes useful for testing. -This page serves as a reference for the options and parameters. - Command Line Arguments ================================== From 193ef4416839a0ef368d3603bf7363b36cbe175e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jan 2024 16:42:50 +0200 Subject: [PATCH 1126/1892] Update 4.6.rst --- releases/4.6.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.6.rst b/releases/4.6.rst index 24a2aead2..68120e1a7 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -42,6 +42,8 @@ New Features and Enhancements ► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. +► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using non-positional arguments. + Known Issues ------------ From 48abef4c9119f3184685d4c4d318f01f4eb6f81b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jan 2024 09:06:09 +0200 Subject: [PATCH 1127/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 66 +------------------ 1 file changed, 3 insertions(+), 63 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index cb8cacb90..86548f7a4 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -6,7 +6,7 @@ Permissions SQreamDB’s primary permission object is a role. The role operates in a dual capacity as both a user and a group. As a user, a role may have permissions to execute operations like creating tables, querying data, and administering the database. The group attribute may be thought of as a membership. As a group, a role may extend its permissions to other roles defined as its group members. This becomes handy when privileged roles wish to extend their permissions and grant multiple permissions to multiple roles. The information about all system role permissions is stored in the metadata. -There are two types of permissions: global and object-level. Global permissions belong to ``SUPERUSER`` roles, allowing unrestricted access to all system and database activities. Object-level permissions apply to non-``SUPERUSER`` roles and can be assigned to databases, schemas, tables, functions, views, foreign tables, columns, catalogs, and services. +There are two types of permissions: global and object-level. Global permissions belong to ``SUPERUSER`` roles, allowing unrestricted access to all system and database activities. Object-level permissions apply to non-``SUPERUSER`` roles and can be assigned to databases, schemas, tables, functions, views, foreign tables, catalogs, and services. The following table describe the required permissions for performing and executing operations on various SQreamDB objects. @@ -77,14 +77,6 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All foreign table permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| **Column** | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from catalog | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Column DDL operations | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | All column permissions | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Catalog** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | @@ -183,26 +175,6 @@ GRANT } ON FUNCTION <function_name> TO role; - - -- Grant permissions at the column level: - GRANT - { - { SELECT - | DDL } [, ...] - | ALL [PERMISSIONS] - } - ON - { - COLUMN <column_name> [, ...] - | ALL COLUMNS } - IN - { - TABLE <table_name> [, ...] - | FOREIGN TABLE <foreign_table_name> [, ...] - | VIEW <view_name> [, ...] - | CATALOG <catalog_name> [, ...] - } - TO <role> [, ...] -- Grant permissions at the Service level: GRANT @@ -303,25 +275,6 @@ REVOKE ON FUNCTION <function_name> FROM <role> [, ...] - -- Revoke permissions at the column level: - REVOKE - { - SELECT - | DDL } [, ...] - | ALL [PERMISSIONS] - ON - { - COLUMN <column_name> [, ...] - | ALL COLUMNS - } - IN - { - TABLE <table_name> [, ...] - | FOREIGN TABLE <foreign_table_name> [, ...] - | VIEW <view_name> [, ...] - | CATALOG <catalog_name> [, ...] } - FROM <role> [, ...] - -- Revoke permissions at the service level: REVOKE { @@ -361,9 +314,8 @@ schema statement is run. | TABLES | FOREIGN TABLES | VIEWS - | COLUMNS - | CATALOGS - | SERVICES + | CATALOGS + | SERVICES | SAVED_QUERIES } { grant_clause @@ -423,12 +375,6 @@ Grant execute function permission to a role: GRANT EXECUTE ON FUNCTION function_name TO role_name; -Grant column-level permissions to a role: - -.. code-block:: postgres - - GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; - Grant usage permissions on a service to a role: .. code-block:: postgres @@ -475,12 +421,6 @@ Revoke permissions on specific objects (table, view, foreign table, or catalog) REVOKE SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE schema_name.table_name FROM role_name; -Revoke column-level permissions from a role: - -.. code-block:: postgres - - REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE schema_name.table_name FROM role_name; - Revoke usage permissions on a service from a role: .. code-block:: postgres From 7050d92d006d9eea9dd06a4438dbb38bfaca9c81 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Jan 2024 08:02:16 +0200 Subject: [PATCH 1128/1892] Update preparing_your_machine_to_install_sqream.rst --- ...preparing_your_machine_to_install_sqream.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index d57861b1a..b8d807e66 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -1,17 +1,18 @@ .. _preparing_your_machine_to_install_sqream: -**************************** -Preparing Your Machine to Install SQream -**************************** -To prepare your machine to install SQream, do the following: +******************************************* +Preparing Your Machine to Install SQreamDB +******************************************* - * Set up your local machine according to SQream's recommended pre-installation configurations. +To prepare your machine to install SQreamDB, do the following: + + * Set up your local machine according to SQreamDB's recommended pre-installation configurations. :: * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - * Red Hat Enterprise Linux v7.x + * Red Hat Enterprise Linux v7.x / v8.6 - 8.8 * CentOS v7.x @@ -19,7 +20,7 @@ To prepare your machine to install SQream, do the following: * Verify that you have the following: - * An NVIDIA GPU - SQream recommends using a Tesla GPU. + * An NVIDIA GPU - SQreamDB recommends using a Tesla GPU. * An SSH connection to your server. @@ -28,7 +29,7 @@ To prepare your machine to install SQream, do the following: * SUDO permissions for installation and configuration purposes. - * A SQream license - Contact support@sqream.com or your SQream account manager for your license key. + * A SQreamDB license - Contact `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for your license key. For more information, see the following: * :ref:`recommended_pre-installation_configurations` From ef489a2e998e7421372f96a49276b8b0a8b312d4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Jan 2024 08:09:13 +0200 Subject: [PATCH 1129/1892] Update catalog_reference.rst --- reference/catalog_reference.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/catalog_reference.rst b/reference/catalog_reference.rst index d82602192..14b1f2a2d 100644 --- a/reference/catalog_reference.rst +++ b/reference/catalog_reference.rst @@ -47,9 +47,9 @@ Database Management Tables * - :ref:`Permissions<permissions>` - ``table_permissions``, ``database_permissions``, ``schema_permissions``, ``permission_types``, ``udf_permissions``, ``sqream_catalog.table_default_permissions`` * - :ref:`Queries<queries>` - - ``saved_queries`` + - ``savedqueries`` * - :ref:`Roles<roles>` - - ``roles``, ``roles_memeberships`` + - ``roles``, ``role_memberships`` * - :ref:`Schemas<schemas>` - ``schemas`` * - :ref:`Tables<tables>` From 6c527a6f11ccff375b936020e9c51231ee31b68a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Jan 2024 14:48:59 +0200 Subject: [PATCH 1130/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 86548f7a4..250902413 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -125,7 +125,6 @@ GRANT GRANT { CREATE - | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS] @@ -223,7 +222,6 @@ REVOKE REVOKE { CREATE - | DDL | USAGE | SUPERUSER } [, ...] | ALL [PERMISSIONS] @@ -361,7 +359,7 @@ Grant various permissions on a schema to a role: .. code-block:: postgres - GRANT CREATE, DDL, USAGE, SUPERUSER ON SCHEMA schema_name TO role_name; + GRANT CREATE, USAGE, SUPERUSER ON SCHEMA schema_name TO role_name; Grant permissions on specific objects (table, view, foreign table, or catalog) to a role: @@ -413,7 +411,7 @@ Revoke permissions on a schema from a role: .. code-block:: postgres - REVOKE CREATE, DDL, USAGE, SUPERUSER ON SCHEMA schema_name FROM role_name; + REVOKE CREATE, USAGE, SUPERUSER ON SCHEMA schema_name FROM role_name; Revoke permissions on specific objects (table, view, foreign table, or catalog) from a role: From ed60a8f02cca0429746629cacdf7a14c3256d8a9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Jan 2024 15:13:03 +0200 Subject: [PATCH 1131/1892] Update copy_from.rst --- .../sql/sql_statements/dml_commands/copy_from.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 97b47403f..30affe0b7 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -181,7 +181,7 @@ Elements * - ``DELETE_SOURCE_ON_SUCCESS`` - ``false`` - ``true`` | ``false`` - - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``OFFSET``, ``ERROR_LOG``, ``REJECTED_DATA``, ``ERROR_COUNT`` and ``LIMIT`` parameters. This parameter is supported for AWS, HADOOP, and GCP. You may only use this parameter with files you have permission to delete. + - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``OFFSET``, ``ERROR_LOG``, ``REJECTED_DATA``, ``ERROR_COUNT`` and ``LIMIT`` parameters. This parameter is supported for AWS, HADOOP, and GCP. Setting the parameter to "true" will restrict users without delete permissions on their operating system from executing the "COPY FROM" command. .. _copy_date_parsers: @@ -523,6 +523,19 @@ Use ``OFFSET`` to skip rows. COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv', delimiter = '|', offset = 2); +Loading Files Using ``DELETE_SOURCE_ON_SUCCESS`` +------------------------------------------------- + +.. code-block:: sql + + -- Single file: + + COPY t FROM WRAPPER json_fdw OPTIONS (location = '/tmp/wrappers/t.json', DELETE_SOURCE_ON_SUCCESS = true); + + -- Multiple files: + + COPY t FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/wrappers/group*.csv', DELETE_SOURCE_ON_SUCCESS = true); + Loading Files Formatted for Windows (``\r\n``) --------------------------------------------------- From b3384cc732220a1226c6b0f7b2d9592395a6436f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jan 2024 15:32:47 +0200 Subject: [PATCH 1132/1892] SQreamDB configuration files and flags --- .../current_method_configuration_levels.rst | 18 +++++++++++++----- .../current_method_flag_types.rst | 2 +- .../current_method_modification_methods.rst | 4 ++++ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 5b05e103a..be4d2e577 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -4,25 +4,33 @@ Cluster and Session ******************* -When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and are persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. +When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and is persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. Session flags only apply to a specific session and are not persistent. Changes made using session flags are not visible to other users, and once the session ends, the flags return to their default values. -Session flags only apply to a specific session and are not persistent. Changes made using session flags are not visible to other users, and once the session ends, the flags return to their default values. +Setting the flags +================== Syntax -====== +------- + +You may set both cluster and session flags using the following syntax on SQreamDB Acceleration Studio and Console: Cluster flag syntax: -.. code-block:: postgress +.. code-block:: sql ALTER SYSTEM SET <flagName> Session flag syntax: -.. code-block:: postgress +.. code-block:: sql SET <flagName> +Configuration file +------------------- + +You may set session flags within your :ref:`Legacy Configuration File<modifying_your_configuration_using_a_legacy_configuration_file>`. + Flag List ========= diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index 81d139707..d5b1987c5 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -4,7 +4,7 @@ Workers ******* -Workers can be individually configured using a worker configuration file, which allows for persistent modifications to be made. Persistent modification refers to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. +Workers can be individually configured using the :ref:`worker configuration file<modifying_your_configuration_using_the_worker_configuration_file>`, which allows for persistent modifications to be made. Persistent modification refers to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. It is worth noting that the worker configuration file is not subject to frequent changes on a daily basis, providing stability to the system's configuration. diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index f3f229a5e..a36dab0c1 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -8,6 +8,8 @@ Modification Methods :local: :depth: 1 +.. _modifying_your_configuration_using_the_worker_configuration_file: + Modifying Your Configuration Using the Worker Configuration File ---------------------------------------------------------------------------- @@ -31,6 +33,8 @@ The following is an example of a worker configuration file: You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. +.. _modifying_your_configuration_using_a_legacy_configuration_file: + Modifying Your Configuration Using a Legacy Configuration File ------------------------------------------------------------------------------ From 904894f89b288e42b532183c5d230661f31cdd60 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jan 2024 17:00:55 +0200 Subject: [PATCH 1133/1892] Update query_split.rst --- operational_guides/query_split.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 1f2f68f0a..493775e41 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -253,7 +253,7 @@ Splitting the Query FROM mytable ; -3. Set the ``@@SplitQueryByNumber`` operator with the number of instances (splits) of your query (here based on an ``INTEGER`` column), and set the ``between ${from} and ${to}`` clause with the name of the column by which you wish to split your query (here the query is split by the ``id`` column. +3. Set the ``@@SplitQueryByNumber`` operator with the number of instances (splits) of your query (here based on an ``INTEGER`` column), and set the ``between ${from} and ${to}`` clause with the name of the column by which you wish to split your query (here the query is split by the ``age`` column. .. code-block:: sql From d7e902be95cb6671698106d9451a2213e992a032 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 17 Jan 2024 09:38:13 +0200 Subject: [PATCH 1134/1892] Update index.rst --- connecting_to_sqream/client_drivers/Spark/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index e6ce90ade..5125c6cfd 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -59,7 +59,7 @@ The following Spark connection properties are supported by SQream: - 0 - The maximum time in seconds for a JDBC query to execute before timing out. * - ``fetchsize`` - - 1 + - 0 - The number of rows to fetch in a single JDBC fetch operation. * - ``batchsize`` - 1000000 From 6ae7de5ee3ed4976a419196bf4bf1899f0d75072 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Jan 2024 10:02:20 +0200 Subject: [PATCH 1135/1892] Dashboard Page Removal --- sqream_studio/getting_started.rst | 2 - sqream_studio/index.rst | 1 - ...orkers_and_services_from_the_dashboard.rst | 273 ------------------ 3 files changed, 276 deletions(-) delete mode 100644 sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst diff --git a/sqream_studio/getting_started.rst b/sqream_studio/getting_started.rst index e69eef421..1dc2d02e5 100644 --- a/sqream_studio/getting_started.rst +++ b/sqream_studio/getting_started.rst @@ -39,8 +39,6 @@ From here you can navigate between the main areas of the Studio: * - Element - Description - * - :ref:`Dashboard<monitoring_workers_and_services_from_the_dashboard>` - - Lets you monitor system health and manage queues and workers. * - :ref:`Editor<executing_statements_and_running_queries_from_the_editor>` - Lets you select databases, perform statement operations, and write and execute queries. * - :ref:`Logs<viewing_logs>` diff --git a/sqream_studio/index.rst b/sqream_studio/index.rst index afdff3457..ad5e36729 100644 --- a/sqream_studio/index.rst +++ b/sqream_studio/index.rst @@ -11,7 +11,6 @@ The SQreamDB Acceleration Studio 5.8.0 is a web-based client for use with SQream :glob: getting_started - monitoring_workers_and_services_from_the_dashboard executing_statements_and_running_queries_from_the_editor viewing_logs creating_assigning_and_managing_roles_and_permissions diff --git a/sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst b/sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst deleted file mode 100644 index ad0667975..000000000 --- a/sqream_studio/monitoring_workers_and_services_from_the_dashboard.rst +++ /dev/null @@ -1,273 +0,0 @@ -.. _monitoring_workers_and_services_from_the_dashboard: - -.. _back_to_dashboard_: - -************************************************** -Monitoring Workers and Services from the Dashboard -************************************************** - -The **Dashboard** is used for the following: - -* Monitoring system health. -* Viewing, monitoring, and adding defined service queues. -* Viewing and managing worker status and add workers. - -The following is an image of the Dashboard: - -.. image:: /_static/images/dashboard.png - -You can only access the Dashboard if you signed in with a ``SUPERUSER`` role. - -The following is a brief description of the Dashboard panels: - -.. list-table:: - :widths: 10 25 65 - :header-rows: 1 - - * - No. - - Element - - Description - * - 1 - - :ref:`Services panel<services_panel_>` - - Used for viewing and monitoring the defined service queues. - * - 2 - - :ref:`Workers panel<workers_panel_>` - - Monitors system health and shows each Sqreamd worker running in the cluster. - * - 3 - - :ref:`License information<license_information_>` - - Shows the remaining amount of days left on your license. - - -.. _data_storage_panel_: - - - -:ref:`Back to Monitoring Workers and Services from the Dashboard<back_to_dashboard_>` - -.. _services_panel_: - -Subscribing to Workers from the Services Panel ----------------------------------------------- - -Services are used to categorize and associate (also known as **subscribing**) workers to particular services. The **Service** panel is used for viewing, monitoring, and adding defined :ref:`service queues<workload_manager>`. - - - -The following is a brief description of each pane: - -.. list-table:: - :widths: 10 90 - :header-rows: 1 - - * - No. - - Description - * - 1 - - Adds a worker to the selected service. - * - 2 - - Shows the service name. - * - 3 - - Shows a trend graph of queued statements loaded over time. - * - 4 - - Adds a service. - * - 5 - - Shows the currently processed queries belonging to the service/total queries for that service in the system (including queued queries). - -Adding A Service -^^^^^^^^^^^^^^^^ - -You can add a service by clicking **+ Add** and defining the service name. - -.. note:: If you do not associate a worker with the new service, it will not be created. - -You can manage workers from the **Workers** panel. For more information about managing workers, see the following: - -* :ref:`Managing Workers from the Workers Panel<workers_panel_>` -* :ref:`Workers<sqream_console_cli_reference>` - -:ref:`Back to Monitoring Workers and Services from the Dashboard<back_to_dashboard_>` - -.. _workers_panel_: - -Managing Workers from the Workers Panel ---------------------------------------- - -From the **Workers** panel you can do the following: - -* :ref:`View workers <view_workers_>` -* :ref:`Add a worker to a service<add_worker_to_service_>` -* :ref:`View a worker's active query information<view_worker_query_information_>` -* :ref:`View a worker's execution plan<view_worker_execution_plan_>` - -.. _view_workers_: - -Viewing Workers -^^^^^^^^^^^^^^^ - -The **Worker** panel shows each worker (``sqreamd``) running in the cluster. Each worker has a status bar that represents the status over time. The status bar is divided into 20 equal segments, showing the most dominant activity in that segment. - -From the **Scale** dropdown menu you can set the time scale of the displayed information -You can hover over segments in the status bar to see the date and time corresponding to each activity type: - -* **Idle** – the worker is idle and available for statements. -* **Compiling** – the worker is compiling a statement and is preparing for execution. -* **Executing** – the worker is executing a statement after compilation. -* **Stopped** – the worker was stopped (either deliberately or due to an error). -* **Waiting** – the worker was waiting on an object locked by another worker. - -.. _add_worker_to_service_: - -Adding A Worker to A Service -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can add a worker to a service by clicking the **add** button. - - - -Clicking the **add** button shows the selected service's workers. You can add the selected worker to the service by clicking **Add Worker**. Adding a worker to a service does not break associations already made between that worker and other services. - - -.. _view_worker_query_information_: - -Viewing A Worker's Active Query Information -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -You can view a worker's active query information by clicking **Queries**, which displays them in the selected service. - - -Each statement shows the **query ID**, **status**, **service queue**, **elapsed time**, **execution time**, and **estimated completion status**. In addition, each statement can be stopped or expanded to show its execution plan and progress. For more information on viewing a statement's execution plan and progress, see :ref:`Viewing a Worker's Execution Plan <view_worker_execution_plan_>` below. - -Viewing A Worker's Host Utilization -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -While viewing a worker's query information, clicking the **down arrow** expands to show the host resource utilization. - - - -The graphs show the resource utilization trends over time, and the **CPU memory** and **utilization** and the **GPU utilization** values on the right. You can hover over the graph to see more information about the activity at any point on the graph. - -Error notifications related to statements are displayed, and you can hover over them for more information about the error. - - -.. _view_worker_execution_plan_: - -Viewing a Worker's Execution Plan -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Clicking the ellipsis in a service shows the following additional options: - -* **Stop Query** - stops the query. -* **Show Execution Plan** - shows the execution plan as a table. The columns in the **Show Execution Plan** table can be sorted. - -For more information on the current query plan, see :ref:`SHOW_NODE_INFO<show_node_info>`. For more information on checking active sessions across the cluster, see :ref:`SHOW_SERVER_STATUS<show_server_status>`. - -.. include:: /reference/sql/sql_statements/monitoring_commands/show_server_status.rst - :start-line: 67 - :end-line: 84 - -Managing Worker Status -^^^^^^^^^^^^^^^^^^^^^^ - -In some cases you may want to stop or restart workers for maintenance purposes. Each Worker line has a :kbd:`⋮` menu used for stopping, starting, or restarting workers. - - -Starting or restarting workers terminates all queries related to that worker. When you stop a worker, its background turns gray. - - - - -.. |icon-user| image:: /_static/images/studio_icon_user.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-editor| image:: /_static/images/studio_icon_editor.png - :align: middle - -.. |icon-copy| image:: /_static/images/studio_icon_copy.png - :align: middle - -.. |icon-select| image:: /_static/images/studio_icon_select.png - :align: middle - -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - -.. |icon-filter| image:: /_static/images/studio_icon_filter.png - :align: middle - -.. |icon-ddl-edit| image:: /_static/images/studio_icon_ddl_edit.png - :align: middle - -.. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png - :align: middle - -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - -.. |icon-plus| image:: /_static/images/studio_icon_plus.png - :align: middle - -.. |icon-close| image:: /_static/images/studio_icon_close.png - :align: middle - -.. |icon-left| image:: /_static/images/studio_icon_left.png - :align: middle - -.. |icon-right| image:: /_static/images/studio_icon_right.png - :align: middle - -.. |icon-format-sql| image:: /_static/images/studio_icon_format.png - :align: middle - -.. |icon-download-query| image:: /_static/images/studio_icon_download_query.png - :align: middle - -.. |icon-open-query| image:: /_static/images/studio_icon_open_query.png - :align: middle - -.. |icon-execute| image:: /_static/images/studio_icon_execute.png - :align: middle - -.. |icon-stop| image:: /_static/images/studio_icon_stop.png - :align: middle - -.. |icon-dashboard| image:: /_static/images/studio_icon_dashboard.png - :align: middle - -.. |icon-expand| image:: /_static/images/studio_icon_expand.png - :align: middle - -.. |icon-scale| image:: /_static/images/studio_icon_scale.png - :align: middle - -.. |icon-expand-down| image:: /_static/images/studio_icon_expand_down.png - :align: middle - -.. |icon-add| image:: /_static/images/studio_icon_add.png - :align: middle - -.. |icon-add-worker| image:: /_static/images/studio_icon_add_worker.png - :align: middle - -.. |keep-tabs| image:: /_static/images/studio_keep_tabs.png - :align: middle - -:ref:`Back to Monitoring Workers and Services from the Dashboard<back_to_dashboard_>` - - - -.. _license_information_: - -License Information -------------------- - -The license information section shows the following: - - * The amount of time in days remaining on the license. - * The license storage capacity. - -.. image:: /_static/images/license_storage_capacity.png - - -:ref:`Back to Monitoring Workers and Services from the Dashboard<back_to_dashboard_>` From 07abff457a08e56f9d397c4953b9d3dc5da60312 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:06:44 +0200 Subject: [PATCH 1136/1892] Update index.rst --- .../client_drivers/Spark/index.rst | 116 +++++++++--------- 1 file changed, 61 insertions(+), 55 deletions(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index 5125c6cfd..954665441 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -4,40 +4,35 @@ Spark ***** - The Spark connector enables reading and writing data to and from SQreamDB and may be used for large-scale data processing. - .. contents:: :local: :depth: 1 -Installation and Configuration ------------------------------- - Before You Begin -~~~~~~~~~~~~~~~~ +================= -To use Spark with SQream, it is essential that you have the following installed: +To use Spark with SQreamDB, it is essential that you have the following installed: -* SQream version 2022.1.8 or later +* SQreamDB version 2022.1.8 or later * Spark version 3.3.1 or later -* `SQream Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ +* `SQreamDB Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ * :ref:`JDBC<jdbc>` version 4.5.6 or later -Connector Configuration -~~~~~~~~~~~~~~~~~~~~~~~ +Configuration +============= -The Spark JDBC connection properties allow users to configure connections between Spark and databases. These properties enable database access, query execution, and result retrieval, as well as authentication, encryption, and connection pooling. +The Spark JDBC connection properties empower you to customize your Spark connection. These properties facilitate various aspects, including database access, query execution, and result retrieval. Additionally, they provide options for authentication, encryption, and connection pooling. -The following Spark connection properties are supported by SQream: +The following Spark connection properties are supported by SQreamDB: .. list-table:: :widths: auto :header-rows: 1 - * - Item + * - Parameter - Default - Description * - ``url`` @@ -101,77 +96,75 @@ The following Spark connection properties are supported by SQream: - ``false`` - A shorthand for specifying connection properties in the JDBC data source. +Connecting Spark to SQreamDB +---------------------------- - -Connecting Spark to SQream --------------------------- - -The SQream-Spark Connector enables inserting DataFrames into SQream tables and exporting tables or queries as DataFrames for use with Spark. DataFrames are Spark objects used for transferring data from one data source to another. +DataFrames, as Spark objects, play a crucial role in transferring data between different sources. The SQreamDB-Spark Connector facilitates the seamless integration of DataFrames, allowing the insertion of DataFrames into SQreamDB tables. Furthermore, it enables the export of tables or queries as DataFrames, providing compatibility with Spark for versatile data processing. 1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: -.. code-block:: postgres - - ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - - -Example: +.. code-block:: console -.. code-block:: postgres + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} + + + //Example: - ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar -2. To create a SQream session, run the following commands in the Spark Shell: +2. To create a SQreamDB session, run the following commands in the Spark Shell: -.. code-block:: postgres +.. code-block:: console import scala.collection.JavaConverters.mapAsJavaMapConverter val config = Map("spark.master"->"local").asJava import com.sqream.driver.SqreamSession; val sqreamSession=SqreamSession.getSession(config) - -Transferring Data From SQream to Spark --------------------------------------- +Transferring Data +=================== + +Transferring Data From SQreamDB to Spark +------------------------------------------ 1. Create a mapping of Spark options: -.. code-block:: postgres +.. code-block:: console val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava 2. Create a Spark DataFrame: -.. code-block:: postgres +.. code-block:: console val df=sqreamSession.read(options) -Transferring Data From Spark to SQream --------------------------------------- +Transferring Data From Spark to SQreamDB +------------------------------------------ 1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): -.. code-block:: postgres +.. code-block:: console val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava 2. Create a Spark DataFrame: -.. code-block:: postgres +.. code-block:: console import org.apache.spark.sql.SaveMode val df=sqreamSession.write(df, options, SaveMode.Overwrite) -Supported Data Types and Mapping --------------------------------- +Data Types and Mapping +======================== -SQream data types mapped to Spark +SQreamDB data types mapped to Spark .. list-table:: :widths: auto :header-rows: 1 - * - SQream + * - SQreamDB - Spark * - ``BIGINT`` - ``LONGINT`` @@ -194,14 +187,14 @@ SQream data types mapped to Spark * - ``DATETIME`` - ``TimestampType`` -Spark data types mapped to SQream +Spark data types mapped to SQreamDB .. list-table:: :widths: auto :header-rows: 1 * - Spark - - SQream + - SQreamDB * - ``BooleanType`` - ``BOOL`` * - ``ByteType`` @@ -227,11 +220,11 @@ Spark data types mapped to SQream Example -------- +======== JAVA -.. code-block:: postgres +.. code-block:: java import com.sqream.driver.SqreamSession; import org.apache.spark.sql.Dataset; @@ -245,24 +238,37 @@ JAVA HashMap<String, String> config = new HashMap<>(); //spark configuration //optional configuration here: https://spark.apache.org/docs/latest/configuration.html - config.put("spark.master", "local"); + config.put("spark.master", "spark://localhost:7077"); + config.put("spark.dynamicAllocation.enabled", "false"); + + config.put("spark.driver.port", "7077"); + config.put("spark.driver.host", "192.168.0.157"); + config.put("spark.driver.bindAddress", "192.168.0.157"); + SqreamSession sqreamSession = SqreamSession.getSession(config); //spark properties //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html HashMap<String, String> props = new HashMap<>(); - props.put("url", "jdbc:Sqream://192.168.4.51:5000/master;user=sqream;password=sqream;cluster=false;logfile=logsFiles.txt;loggerlevel=DEBUG"); - props.put("dbtable", "test"); + props.put("url", "jdbc:Sqream://192.168.0.157:3108/master;user=sqream;password=1234;cluster=true;"); + + //spark partition// + props.put("dbtable", "public.test_table"); + props.put("partitionColumn","sr_date_sk"); + props.put("numPartitions","2"); + props.put("lowerBound","2450820"); + props.put("upperBound","2452822"); + /*Read from sqream table*/ Dataset<Row> dataFrame = sqreamSession.read(props); + dataFrame.show();/*By default, show() displays only the first 20 rows of the DataFrame. + This can be insufficient when working with large datasets. You can customize the number of rows displayed by passing an argument to show(n).*// + - /*Added to sqream table*/ - sqreamSession.write(dataFrame, props); - sqreamSession.write(dataFrame, props, SaveMode.Overwrite); - + /*Add to sqream table*/ + sqreamSession.write(dataFrame, props, SaveMode.Append); } - } - + } \ No newline at end of file From d03db5f2bd141948aac4f4459b9b1e6166cd38f0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Jan 2024 16:07:10 +0200 Subject: [PATCH 1137/1892] Update index.rst --- connecting_to_sqream/client_drivers/Spark/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index 954665441..5c616e437 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -223,7 +223,7 @@ Example ======== JAVA - + .. code-block:: java import com.sqream.driver.SqreamSession; From 484408dbdd75208a5c6ce84fc33dbe843e163002 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 Jan 2024 11:54:34 +0200 Subject: [PATCH 1138/1892] Saved Query Permissions --- .../access_control_permissions.rst | 32 +++- operational_guides/saved_queries.rst | 142 ++++++------------ .../catalog_reference_catalog_tables.rst | 4 +- .../access_control_commands/grant.rst | 19 ++- .../access_control_commands/revoke.rst | 11 +- .../utility_commands/drop_saved_query.rst | 23 ++- .../utility_commands/execute_saved_query.rst | 32 ++-- .../utility_commands/list_saved_queries.rst | 29 ++-- .../utility_commands/save_query.rst | 37 +++-- .../utility_commands/show_saved_query.rst | 26 ++-- releases/4.6.rst | 2 + 11 files changed, 175 insertions(+), 182 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 250902413..893c93ca3 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -89,6 +89,16 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All services permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Saved Query** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Executing saved query statements and utility functions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Saved query DDL operations | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``USAGE`` | Grants access to saved query objects | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All saved query permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ Syntax ====== @@ -182,6 +192,15 @@ GRANT } ON { SERVICE <service_name> } TO <role> [, ...] + + -- Grant permissions at the Saved Query level: + GRANT { + { SELECT + | DDL + | USAGE } [, ...] + | ALL [PERMISSIONS] } + ON SAVED QUERY <saved_query_name> [, ...] + TO <role> [, ...] -- Allows role2 to use permissions granted to role1 GRANT <role1> [, ...] @@ -281,6 +300,15 @@ REVOKE } ON { SERVICE <service_name> } FROM <role> [, ...] + + -- Revoke permissions at the Saved Query level: + REVOKE { + { SELECT + | DDL + | USAGE } [, ...] + | ALL [PERMISSIONS] } + ON SAVED QUERY <saved_query_name> [, ...] + FROM <role> [, ...] -- Removes access to permissions in role1 by role 2 REVOKE [ADMIN OPTION FOR] <role1> [, ...] @@ -312,8 +340,8 @@ schema statement is run. | TABLES | FOREIGN TABLES | VIEWS - | CATALOGS - | SERVICES + | CATALOGS + | SERVICES | SAVED_QUERIES } { grant_clause diff --git a/operational_guides/saved_queries.rst b/operational_guides/saved_queries.rst index f1a9d4ee3..2aade02e9 100644 --- a/operational_guides/saved_queries.rst +++ b/operational_guides/saved_queries.rst @@ -4,120 +4,72 @@ Saved Queries *********************** +The ``save_query`` command serves to both generate and store an execution plan, offering time savings for the execution of frequently used complex queries. It's important to note that the saved execution plan is closely tied to the structure of its underlying tables. Consequently, if any of the objects mentioned in the query undergo modification, the saved query must be recreated. +Saved queries undergo compilation during their creation. When executed, these queries utilize the precompiled query plan instead of compiling a new plan at query runtime. -Using the ``save_query`` command will both generate and save an execution plan. This allows you to save time when running frequently used complex queries. +Syntax +====== -Note that the saved execution plan is tightly coupled with the structure of its underlying tables, which means that if one or more of the objects mentioned in the query is modified, the saved query must be re-created. +Saved queries related syntax: +.. code-block:: sql -How Saved Queries Work -========================== + -- Saving a query + SELECT SAVE_QUERY(saved_query_name, parameterized_query_string) + + -- Showing a saved query + SELECT SHOW_SAVED_QUERY(saved_query_name) -Saved queries are compiled when they are created. When a saved query is run, this query plan is used instead of compiling a query plan at query time. + -- Listing saved queries + SELECT LIST_SAVED_QUERIES() + + -- Executing a saved query + SELECT EXECUTE_SAVED_QUERY(saved_query_name, [ , argument [ , ... ] ] ) + + -- Dropping a saved query + SELECT DROP_SAVED_QUERY(saved_query_name) + + saved_query_name ::= string_literal + parameterized_query_string ::= string_literal + argument ::= string_literal | number_literal Parameter Support -=========================== +------------------ Query parameters can be used as substitutes for constants expressions in queries. * Parameters cannot be used to substitute identifiers like column names and table names. -* Query parameters of a string datatype (like ``TEXT``) must be of a fixed length, and can be used in equality checks, but not patterns (e.g. :ref:`like`, :ref:`rlike`, etc.) - -Creating a Saved Query -====================== - -A saved query is created using the :ref:`save_query` utility command. - -Saving a Simple Query ---------------------------- +* Query parameters of a string datatype must be of a fixed length and may be used in equality checks but not with patterns such as :ref:`like` and :ref:`rlike`. -.. code-block:: psql +Permissions +============ - SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); - executed - -Saving a Parameterized Query ------------------------------------------- +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Statement / Function + - Permission + * - :ref:`save_query` + - Saving queries requires no special permissions per se, however, it does require from the user to have permissions to access the tables referenced in the query and other query element permissions. The user who saved the query is granted all permissions on the saved query. + * - :ref:`show_saved_query` + - Showing a saved query requires ``SELECT`` permissions on the saved query. + * - :ref:`list_saved_queries` + - Listing saved queries requires no special permissions. + * - :ref:`execute_saved_query` + - Executing a saved query requires ``USAGE`` permissions on the saved query and ``SELECT`` permissions to access the tables referenced in the query. + * - :ref:`drop_saved_query` + - Dropping a saved query requires ``DDL`` permissions on the saved query and ``SELECT`` permissions to access the tables referenced in the query. + +Parameterized Query +==================== Parameterized queries, also known as prepared statements, enable the usage of parameters which may be replaced by actual values when executing the query. They are created and managed in application code, primarily to optimize query execution, enhance security, and allow for the reuse of query templates with different parameter values. -.. code-block:: psql +.. code-block:: sql SELECT SAVE_QUERY('select_by_weight_and_team','SELECT * FROM nba WHERE Weight > ? AND Team = ?'); - -Executing Saved Queries -======================= - -Executing a saved query requires calling it by it's name in a :ref:`execute_saved_query` statement. A saved query with no parameter is called without parameters. - -.. code-block:: psql - - SELECT EXECUTE_SAVED_QUERY('select_all'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - [...] - -Executing a saved query with parameters requires specifying the parameters in the order they appear in the query: - -.. code-block:: psql - - SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); - Name | Team | Number | Position | Age | Height | Weight | College | Salary - ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- - Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 - James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 - Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 - -Listing Saved Queries -======================= - -Saved queries are saved as a database objects. They can be listed in one of two ways: - -Using the :ref:`catalog<catalog_reference>`: - -.. code-block:: psql - - SELECT * FROM sqream_catalog.savedqueries; - name | num_parameters - --------------------------+--------------- - select_all | 0 - select_by_weight | 1 - select_by_weight_and_team | 2 - -Using the :ref:`list_saved_queries` utility function: - -.. code-block:: psql - - SELECT LIST_SAVED_QUERIES(); - saved_query - ------------------------- - select_all - select_by_weight - select_by_weight_and_team - - -Dropping a Saved Query -============================= - -When you're done with a saved query, or would like to replace it with another, you can drop it with :ref:`drop_saved_query`: - -.. code-block:: psql - - SELECT DROP_SAVED_QUERY('select_all'); - executed - SELECT DROP_SAVED_QUERY('select_by_weight_and_team'); - executed - - SELECT LIST_SAVED_QUERIES(); - saved_query - ------------------------- - select_by_weight \ No newline at end of file diff --git a/reference/catalog_reference_catalog_tables.rst b/reference/catalog_reference_catalog_tables.rst index b206ea5b1..ae631d7d7 100644 --- a/reference/catalog_reference_catalog_tables.rst +++ b/reference/catalog_reference_catalog_tables.rst @@ -296,7 +296,7 @@ The following table describes the ``schema_permissions`` data object: Queries ---------------- -The ``savedqueries`` data object identifies the saved_queries in the database, as shown in the following table: +The ``savedqueries`` data object identifies the saved queries in the database, as shown in the following table: .. list-table:: :widths: 20 180 @@ -309,7 +309,7 @@ The ``savedqueries`` data object identifies the saved_queries in the database, a * - ``num_parameters`` - Shows the number of parameters to be replaced at run-time. -For more information, see :ref:`saved_queries<saved_queries>`. +For more information, see :ref:`Saved Queries<saved_queries>`. .. _roles: diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 283ce3f3a..4bc2d22eb 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -122,6 +122,15 @@ Syntax } ON { SERVICE <service_name> } TO <role> [, ...] + + -- Grant permissions at the Saved Query level: + GRANT { + { SELECT + | DDL + | USAGE } [, ...] + | ALL [PERMISSIONS] } + ON SAVED QUERY <saved_query_name> [, ...] + TO <role> [, ...] -- Allows role2 to use permissions granted to role1 GRANT <role1> [, ...] @@ -145,7 +154,7 @@ The following table describes the ``GRANT`` parameters: - Description * - ``role_name`` - The name of the role to grant permissions to - * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name`` + * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name``, ``saved_query_name`` - Object to grant permissions on. * - ``WITH ADMIN OPTION`` - @@ -188,10 +197,10 @@ The following table describes the supported permissions: - Database, Schema, Table - For a role to create and manage objects, it needs the ``CREATE`` and ``USAGE`` permissions at the respective level * - ``USAGE`` - - Schema + - Schema, Saved Query, Services - For a role to see tables in a schema, it needs the ``USAGE`` permissions * - ``SELECT`` - - Table + - Table, Saved Query, View, Catalog, Foreign Table - Allows a user to run :ref:`select` queries on table contents * - ``INSERT`` - Table @@ -203,13 +212,13 @@ The following table describes the supported permissions: - Table - Allows a user to run :ref:`delete`, :ref:`truncate` statements to delete data from a table * - ``DDL`` - - Database, Schema, Table, Function + - Database, Schema, Table, Function, Saved Query, View, Foreign Table - Allows a user to :ref:`alter tables<alter_table>`, rename columns and tables, etc. * - ``EXECUTE`` - Function - Allows a user to execute UDFs * - ``ALL`` - - Cluster, Database, Schema, Table, Function + - Cluster, Database, Schema, Table, Function, Saved Query, Services, Catalog, Foreign Table - All of the above permissions at the respective level .. end include diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index 8491911e9..f4f9b5008 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -111,6 +111,15 @@ Syntax } ON { SERVICE <service_name> } FROM <role> [, ...] + + -- Revoke permissions at the Saved Query level: + REVOKE { + { SELECT + | DDL + | USAGE } [, ...] + | ALL [PERMISSIONS] } + ON SAVED QUERY <saved_query_name> [, ...] + FROM <role> [, ...] -- Removes access to permissions in role1 by role 2 REVOKE [ADMIN OPTION FOR] <role1> [, ...] @@ -131,7 +140,7 @@ Parameters - Description * - ``role_name`` - The name of the role to revoke permissions from - * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name`` + * - ``table_name``, ``database_name``, ``schema_name``, ``function_name``, ``catalog_name``, ``column_name``, ``service_name``, ``saved_query_name`` - Object to revoke permissions from * - ``WITH ADMIN OPTION`` - diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst index f8174edd2..f03bb831d 100644 --- a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst @@ -1,28 +1,22 @@ .. _drop_saved_query: ******************** -DROP_SAVED_QUERY +DROP SAVED QUERY ******************** -``DROP_SAVED_QUERY`` drops a :ref:`previously saved query<save_query>`. +``DROP_SAVED_QUERY`` drops a previously :ref:`saved query<save_query>`. Read more in the :ref:`saved_queries<saved_queries>` guide. See also: :ref:`save_query`, :ref:`execute_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. -Permissions -============= - -Dropping a saved query requires no special permissions. - Syntax ========== -.. code-block:: postgres +.. code-block:: sql drop_saved_query_statement ::= SELECT DROP_SAVED_QUERY(saved_query_name) - ; saved_query_name ::= string_literal @@ -49,7 +43,12 @@ Examples Dropping a previously saved query --------------------------------------- -.. code-block:: psql +.. code-block:: sql + + SELECT DROP_SAVED_QUERY('select_all'); + + +Permissions +============= - t=> SELECT DROP_SAVED_QUERY('select_all'); - executed +Dropping a saved query requires ``DDL`` permissions on the saved query and ``SELECT`` permissions to access the tables referenced in the query. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index fdc626577..dd84348e9 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -1,28 +1,22 @@ .. _execute_saved_query: ******************** -EXECUTE_SAVED_QUERY +EXECUTE SAVED QUERY ******************** -``EXECUTE_SAVED_QUERY`` executes a :ref:`previously saved query<save_query>`. +``EXECUTE_SAVED_QUERY`` executes a previously :ref:`saved query<save_query>`. Read more in the :ref:`saved_queries` guide. See also: :ref:`save_query`, :ref:`drop_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. -Permissions -============= - -Executing a saved query requires ``SELECT`` permissions to access the tables referenced in the query. - Syntax ========== -.. code-block:: postgres +.. code-block:: sql execute_saved_query_statement ::= SELECT EXECUTE_SAVED_QUERY(saved_query_name, [ , argument [ , ... ] ] ) - ; saved_query_name ::= string_literal @@ -89,11 +83,11 @@ Here's a peek at the table contents (:download:`Download nba.csv </_static/sampl Saving and executing a simple query --------------------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_all'); + SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); + + SELECT EXECUTE_SAVED_QUERY('select_all'); Name | Team | Number | Position | Age | Height | Weight | College | Salary -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 @@ -109,11 +103,11 @@ Use parameters to replace them later at execution time. .. tip:: Use dollar quoting (`$$`) to avoid escaping strings. -.. code-block:: psql +.. code-block:: sql - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + + SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); Name | Team | Number | Position | Age | Height | Weight | College | Salary ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 @@ -121,3 +115,7 @@ Use parameters to replace them later at execution time. Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 +Permissions +============= + +Executing a saved query requires ``USAGE`` permissions on the saved query and ``SELECT`` permissions to access the tables referenced in the query. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst index a50bbc43f..f57183de9 100644 --- a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst +++ b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst @@ -1,10 +1,10 @@ .. _list_saved_queries: ******************** -LIST_SAVED_QUERIES +LIST SAVED QUERIES ******************** -``LIST_SAVED_QUERIES`` lists the available :ref:`previously saved queries<save_query>`. +``LIST_SAVED_QUERIES`` lists the available previously :ref:`saved queries<save_query>`. This is an alternative way to using the ``savedqueries`` catalog view. @@ -12,24 +12,18 @@ Read more in the :ref:`saved_queries` guide. See also: :ref:`save_query`, :ref:`execute_saved_query`, :ref:`drop_saved_query`, :ref:`show_saved_query` -Permissions -============= - -Listing the saved queries requires no special permissions. - Syntax ========== -.. code-block:: postgres +.. code-block:: sql list_saved_queries_statement ::= SELECT LIST_SAVED_QUERIES() - ; Returns ========== -List of saved query names, one per row. +A list of saved queries the user has ``SELECT`` permissions on. Parameters ============ @@ -47,16 +41,16 @@ Examples Listing previously saved queries --------------------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT LIST_SAVED_QUERIES(); + SELECT LIST_SAVED_QUERIES(); saved_query ------------------------- select_all select_by_weight select_by_weight_and_team - t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); + SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); saved_query ----------------------------------------------- SELECT * FROM nba WHERE Weight > ? AND Team = ? @@ -67,11 +61,16 @@ Listing saved queries with the catalog Using the :ref:`catalog<catalog_reference>` is also possible: -.. code-block:: psql +.. code-block:: sql - t=> SELECT * FROM sqream_catalog.savedqueries; + SELECT * FROM sqream_catalog.savedqueries; name | num_parameters --------------------------+--------------- select_all | 0 select_by_weight | 1 select_by_weight_and_team | 2 + +Permissions +============= + +Listing saved queries requires no special permissions. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index c65cd48ba..9310e7ce8 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -1,28 +1,22 @@ .. _save_query: ***************** -SAVE_QUERY +SAVE QUERY ***************** -``SAVE_QUERY`` saves a query execution plan. +``SAVE QUERY`` saves a query execution plan. Read more in the :ref:`saved_queries` guide. See also: :ref:`execute_saved_query`, :ref:`drop_saved_query`, :ref:`show_saved_query`, :ref:`list_saved_queries`. -Permissions -============= - -No special permissions are needed to save a query. - Syntax ========== -.. code-block:: postgres +.. code-block:: sql save_query_statement ::= SELECT SAVE_QUERY(saved_query_name, parameterized_query_string) - ; saved_query_name ::= string_literal @@ -66,7 +60,7 @@ Examples Assume a table named ``nba``, with the following structure: -.. code-block:: postgres +.. code-block:: sql CREATE TABLE nba ( @@ -93,11 +87,11 @@ Here's a peek at the table contents (:download:`Download nba.csv </_static/sampl Saving and executing a simple query --------------------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_all'); + SELECT SAVE_QUERY('select_all','SELECT * FROM nba'); + + SELECT EXECUTE_SAVED_QUERY('select_all'); Name | Team | Number | Position | Age | Height | Weight | College | Salary -------------------------+------------------------+--------+----------+-----+--------+--------+-----------------------+--------- Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 @@ -113,14 +107,19 @@ Use parameters to replace them later at execution time. .. tip:: Use dollar quoting (`$$`) to avoid escaping strings. -.. code-block:: psql +.. code-block:: sql - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); + SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + + SELECT EXECUTE_SAVED_QUERY('select_by_weight_and_team', 240, 'Toronto Raptors'); Name | Team | Number | Position | Age | Height | Weight | College | Salary ------------------+-----------------+--------+----------+-----+--------+--------+-------------+-------- Bismack Biyombo | Toronto Raptors | 8 | C | 23 | 6-9 | 245 | | 2814000 James Johnson | Toronto Raptors | 3 | PF | 29 | 6-9 | 250 | Wake Forest | 2500000 Jason Thompson | Toronto Raptors | 1 | PF | 29 | 6-11 | 250 | Rider | 245177 - Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 \ No newline at end of file + Jonas Valanciunas | Toronto Raptors | 17 | C | 24 | 7-0 | 255 | | 4660482 + +Permissions +============= + +Saving queries requires no special permissions per se, however, it does require from the user to have permissions to access the tables referenced in the query and other query element permissions. The user who saved the query is granted all permissions on the saved query. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/show_saved_query.rst b/reference/sql/sql_statements/utility_commands/show_saved_query.rst index 15ac4c1bd..b85265747 100644 --- a/reference/sql/sql_statements/utility_commands/show_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/show_saved_query.rst @@ -1,28 +1,22 @@ .. _show_saved_query: ******************** -SHOW_SAVED_QUERY +SHOW SAVED QUERY ******************** -``SHOW_SAVED_QUERY`` shows the query text for a :ref:`previously saved query<save_query>`. +``SHOW_SAVED_QUERY`` shows the query text for a previously :ref:`saved query<save_query>`. Read more in the :ref:`saved_queries` guide. -See also: ref:`save_query`, :ref:`execute_saved_query`, ref:`drop_saved_query`, ref:`list_saved_queries`. - -Permissions -============= - -Showing a saved query requires no special permissions. +See also: :ref:`save_query`, :ref:`execute_saved_query`, :ref:`drop_saved_query`, :ref:`list_saved_queries`. Syntax ========== -.. code-block:: postgres +.. code-block:: sql show_saved_query_statement ::= SELECT SHOW_SAVED_QUERY(saved_query_name) - ; saved_query_name ::= string_literal @@ -50,12 +44,16 @@ Examples Showing a previously saved query --------------------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); - executed - t=> SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); + SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); + + SELECT SHOW_SAVED_QUERY('select_by_weight_and_team'); saved_query ----------------------------------------------- SELECT * FROM nba WHERE Weight > ? AND Team = ? +Permissions +============= + +Showing a saved query requires ``SELECT`` permissions on the saved query. diff --git a/releases/4.6.rst b/releases/4.6.rst index 68120e1a7..00d254565 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -44,6 +44,8 @@ New Features and Enhancements ► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using non-positional arguments. +► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. + Known Issues ------------ From f83a8ff1c784412593ffd316df7ea976e7be5881 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:11:16 +0200 Subject: [PATCH 1139/1892] Update 4.6.rst --- releases/4.6.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.6.rst b/releases/4.6.rst index 00d254565..df745580f 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -46,6 +46,8 @@ New Features and Enhancements ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. +► + Known Issues ------------ From 3ee7c7787fef363ee8939970039523361db21fb6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 Jan 2024 16:46:40 +0200 Subject: [PATCH 1140/1892] Update current_method_modification_methods.rst --- .../current_method_modification_methods.rst | 62 ++++++++++++------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index a36dab0c1..4442c4dce 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -4,52 +4,66 @@ Modification Methods ************************** -.. contents:: - :local: - :depth: 1 - .. _modifying_your_configuration_using_the_worker_configuration_file: -Modifying Your Configuration Using the Worker Configuration File ----------------------------------------------------------------------------- +Worker Configuration File +-------------------------- You can modify your configuration using the **worker configuration file (config.json)**. Changes that you make to worker configuration files are persistent. Note that you can only set the attributes in your worker configuration file **before** initializing your SQream worker, and while your worker is active these attributes are read-only. -The following is an example of a worker configuration file: +The following is an example of the default worker configuration file: .. code-block:: json { - "cluster": "/home/test_user/sqream_testing_temp/sqreamdb", - "gpu": 0, - "licensePath": "home/test_user/SQream/tests/license.enc", - "machineIP": "127.0.0.1", - "metadataServerIp": "127.0.0.1", - "metadataServerPort": 3105, - "port": 5000, - "useConfigIP": true, - "legacyConfigFilePath": "home/SQream_develop/SqrmRT/utils/json/legacy_congif.json" + "cluster": "/home/sqream/sqream_storage", + "cudaMemQuota": 96, + "gpu": 0, + "cpu": -1, + "legacyConfigFilePath": "sqream_config_legacy.json", + "licensePath": "/etc/sqream/license.enc", + "limitQueryMemoryGB": 30, + "parquetReaderThreads" : 8, + "machineIP": "127.0.0.1", + "metadataServerIp": "127.0.0.1", + "metadataServerPort": 3105, + "port": 5000, + "instanceId": "sqream_0_1", + "portSsl": 5100, + "initialSubscribedServices": "sqream", + "useConfigIP": true } You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. .. _modifying_your_configuration_using_a_legacy_configuration_file: -Modifying Your Configuration Using a Legacy Configuration File ------------------------------------------------------------------------------- +Cluster and Session Configuration File +-------------------------------------- You can modify your configuration using a legacy configuration file. The Legacy configuration file provides access to the read/write flags. A link to this file is provided in the **legacyConfigFilePath** parameter in the worker configuration file. -The following is an example of the legacy configuration file: +The following is an example of the default cluster and session configuration file: .. code-block:: json { - "developerMode": true, - "reextentUse": false, - "useClientLog": true, - "useMetadataServer": false, - "enablePythonUdfs": true + "diskSpaceMinFreePercent": 1, + "DefaultPathToLogs": "/home/sqream/sqream_storage/tmp_logs/", + "enableLogDebug": false, + "insertCompressors": 8, + "insertParsers": 8, + "isUnavailableNode": false, + "logBlackList": "webui", + "logDebugLevel": 6, + "nodeInfoLoggingSec": 60, + "useClientLog": true, + "useMetadataServer": true, + "spoolMemoryGB": 28, + "useLogMaxFileSize": false, + "logMaxFileSizeMB": 20, + "logFileRotateTimeFrequency": "daily", + "waitForClientSeconds": 18000 } \ No newline at end of file From 1de0e72e8f6bbceafdd965fe7ec227ca84f565f8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 Jan 2024 17:32:11 +0200 Subject: [PATCH 1141/1892] permissions --- .../access_control_permissions.rst | 310 +++++++++--------- .../access_control_commands/grant.rst | 167 +++++----- .../access_control_commands/revoke.rst | 160 +++++---- 3 files changed, 305 insertions(+), 332 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 893c93ca3..e172ce27f 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -29,7 +29,9 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create schemas in the database | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE FUNCTION`` | Create and drop functions | +| ``CREATEFUNCTION`` | Create and drop functions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter tables within the database | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All database permissions except for a SUPERUSER permission | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ @@ -39,6 +41,10 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATE`` | Create tables in the schema | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SUPERUSER`` | No permission restrictions on any activity within the schema (this does not include modifying roles or permissions) | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Drop and alter tables within the schema | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All schema permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Table** | @@ -69,6 +75,8 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | DDL operations of view results | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``ALL`` | All views permissions | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Foreign Table** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from foreign table | @@ -111,96 +119,95 @@ GRANT .. code-block:: postgres -- Grant permissions to all databases: - GRANT - { - SUPERUSER - | LOGIN - | PASSWORD '<password>' - } - TO <role> [, ...] + GRANT { + SUPERUSER + | LOGIN + | PASSWORD '<password>' } + TO <role> [, ...] -- Grant permissions at the database level: - GRANT - { - CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION } [, ...] - | ALL [PERMISSIONS] + GRANT { + CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] ON DATABASE <database> [, ...] - TO <role> [, ...] + TO <role> [, ...] -- Grant permissions at the schema level: - GRANT - { - CREATE - | USAGE - | SUPERUSER } [, ...] - | ALL [PERMISSIONS] - ON SCHEMA <schema> [, ...] - TO <role> [, ...] + GRANT { + CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + ON SCHEMA <schema> [, ...] + TO <role> [, ...] -- Grant permissions at the object level: - GRANT - { - SELECT - | INSERT - | DELETE - | DDL - | UPDATE } [, ...] - | ALL [PERMISSIONS] - ON - { - TABLE <table_name> [, ...] - | ALL TABLES IN SCHEMA <schema_name> [, ...] - | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS IN SCHEMA <schema_name> [, ...] - | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] - } + GRANT { + SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + ON {TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] -- Grant permissions at the catalog level: - GRANT - { - SELECT - | INSERT - | DELETE - | UPDATE } [, ...] - | ALL [PERMISSIONS] - ON - { - CATALOG <catalog_name> [, ...] - } + GRANT { + {SELECT } [, ...] + | ALL [PERMISSIONS] } + ON { CATALOG <catalog_name> [, ...] } + TO <role> [, ...] + + -- Grant permissions on the foreign table level: + + GRANT { + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] -- Grant function execution permission: - GRANT - { - ALL - | EXECUTE - | DDL - } - ON FUNCTION <function_name> - TO role; + GRANT { + ALL + | EXECUTE + | DDL } + ON FUNCTION <function_name> + TO <role> - -- Grant permissions at the Service level: - GRANT - { - { USAGE } [PERMISSIONS] - } - ON { SERVICE <service_name> } + -- Grant permissions on the view level + GRANT { + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { VIEW <view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] - - -- Grant permissions at the Saved Query level: + + -- Grant permissions at the Service level: GRANT { - { SELECT - | DDL - | USAGE } [, ...] + {USAGE} [, ...] | ALL [PERMISSIONS] } - ON SAVED QUERY <saved_query_name> [, ...] + ON { SERVICE <service_name> [, ...] + | ALL SERVICES IN SYSTEM } TO <role> [, ...] + + -- Grant saved query permissions + GRANT + SELECT + | DDL + | USAGE + | ALL + ON SAVED QUERY <saved_query> [,...] + TO <role> [,...] -- Allows role2 to use permissions granted to role1 GRANT <role1> [, ...] @@ -217,98 +224,95 @@ REVOKE .. code-block:: postgres -- Revoke permissions from all databases: - REVOKE - { - SUPERUSER - | LOGIN - | PASSWORD - } + REVOKE { + SUPERUSER + | LOGIN + | PASSWORD '<password>' } FROM <role> [, ...] - + -- Revoke permissions at the database level: - REVOKE - { - CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION } [, ...] - | ALL [PERMISSIONS] - ON DATABASE <database_name> [, ...] + REVOKE { + CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] + ON DATABASE <database> [, ...] FROM <role> [, ...] - -- Revoke permissions at the schema level: - REVOKE - { - CREATE - | USAGE - | SUPERUSER } [, ...] - | ALL [PERMISSIONS] - ON SCHEMA <schema_name> [, ...] + -- Revoke permissions at the schema level: + REVOKE { + CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + ON SCHEMA <schema> [, ...] FROM <role> [, ...] - - -- Revoke permissions at the object level: - REVOKE - { - SELECT - | INSERT - | DELETE - | DDL - | UPDATE } [, ...] - | ALL [PERMISSIONS] - ON - { - TABLE <table_name> [, ...] - | ALL TABLES [, ...] - | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS [, ...] - | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLES [, ...] - IN SCHEMA <schema_name> [, ...] - } + + -- Revoke permissions at the object level: + REVOKE { + SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + ON {TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...]} FROM <role> [, ...] - -- Revoke permissions at the catalog level: - REVOKE - { - SELECT - | INSERT - | DELETE - | UPDATE } [, ...] - | ALL [PERMISSIONS] - ON - { - CATALOG <catalog_name> [, ...] - } + -- Revoke permissions at the catalog level: + REVOKE { + {SELECT } [, ...] + | ALL [PERMISSIONS] } + ON { CATALOG <catalog_name> [, ...] } FROM <role> [, ...] - - -- Revoke permissions at the function execution level: - REVOKE - { - All - | EXECUTE - | DDL - } - ON FUNCTION <function_name> - FROM <role> [, ...] + + -- Revoke permissions on the foreign table level: - -- Revoke permissions at the service level: - REVOKE - { - { USAGE } [, ...] - | ALL [PERMISSIONS] - } - ON { SERVICE <service_name> } + REVOKE { + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...]} FROM <role> [, ...] - - -- Revoke permissions at the Saved Query level: + + -- Revoke function execution permission: REVOKE { - { SELECT - | DDL - | USAGE } [, ...] + ALL + | EXECUTE + | DDL } + ON FUNCTION <function_name> + FROM <role> + + -- Revoke permissions on the view level + REVOKE { + {SELECT + | DDL } [, ...] | ALL [PERMISSIONS] } - ON SAVED QUERY <saved_query_name> [, ...] + ON { VIEW <view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...]} FROM <role> [, ...] + + -- Revoke permissions at the Service level: + REVOKE { + {USAGE} [, ...] + | ALL [PERMISSIONS] } + ON { SERVICE <service_name> [, ...] + | ALL SERVICES IN SYSTEM } + FROM <role> [, ...] + + -- Revoke saved query permissions + REVOKE + SELECT + | DDL + | USAGE + | ALL + ON SAVED QUERY <saved_query> [,...] + FROM <role> [,...] -- Removes access to permissions in role1 by role 2 REVOKE [ADMIN OPTION FOR] <role1> [, ...] @@ -334,7 +338,7 @@ schema statement is run. .. code-block:: postgres ALTER DEFAULT PERMISSIONS FOR modifying_role - [IN schema_name [, ...] + [IN <schema_name> [, ...] FOR { SCHEMAS | TABLES diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 4bc2d22eb..7fbc159bb 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -20,117 +20,96 @@ Syntax .. code-block:: postgres - -- Grant permissions at the instance/ storage cluster level: - GRANT - { - SUPERUSER - | LOGIN - | PASSWORD '<password>' - } - TO <role> [, ...] + -- Grant permissions to all databases: + GRANT { + SUPERUSER + | LOGIN + | PASSWORD '<password>' } + TO <role> [, ...] -- Grant permissions at the database level: - GRANT - { - { CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION } [, ...] - | ALL [PERMISSIONS] - } + GRANT { + CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] ON DATABASE <database> [, ...] - TO <role> [, ...] + TO <role> [, ...] -- Grant permissions at the schema level: - GRANT - { - { CREATE - | DDL - | USAGE - | SUPERUSER } [, ...] - | ALL [PERMISSIONS] - } - ON SCHEMA <schema> [, ...] - TO <role> [, ...] + GRANT { + CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] + ON SCHEMA <schema> [, ...] + TO <role> [, ...] -- Grant permissions at the object level: - GRANT - { - { SELECT - | INSERT - | DELETE - | DDL - | UPDATE } [, ...] - | ALL [PERMISSIONS] - } - ON - { - TABLE <table_name> [, ...] - | ALL TABLES IN SCHEMA <schema_name> [, ...] - | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS IN SCHEMA <schema_name> [, ...] - | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] - } + GRANT { + SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + ON {TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] - GRANT - { - { SELECT - | INSERT - | DELETE - | UPDATE } [, ...] - | ALL [PERMISSIONS] - } - ON - { - | CATALOG <catalog_name> [, ...] - } + -- Grant permissions at the catalog level: + GRANT { + {SELECT } [, ...] + | ALL [PERMISSIONS] } + ON { CATALOG <catalog_name> [, ...] } TO <role> [, ...] - -- Grant execute function permission: - GRANT - { - ALL - | EXECUTE - | DDL - } - ON FUNCTION function_name - TO role; - - -- Grant permissions at the column level: - GRANT - { - { SELECT - | DDL } [, ...] - | ALL [PERMISSIONS] - } - ON - { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] - | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] - } + -- Grant permissions on the foreign table level: + + GRANT { + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] - -- Grant permissions at the Service level: - GRANT - { - { USAGE } [PERMISSIONS] - } - ON { SERVICE <service_name> } + -- Grant function execution permission: + GRANT { + ALL + | EXECUTE + | DDL } + ON FUNCTION <function_name> + TO <role> + + -- Grant permissions on the view level + GRANT { + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { VIEW <view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...]} TO <role> [, ...] - - -- Grant permissions at the Saved Query level: + + -- Grant permissions at the Service level: GRANT { - { SELECT - | DDL - | USAGE } [, ...] + {USAGE} [, ...] | ALL [PERMISSIONS] } - ON SAVED QUERY <saved_query_name> [, ...] + ON { SERVICE <service_name> [, ...] + | ALL SERVICES IN SYSTEM } TO <role> [, ...] + + -- Grant saved query permissions + GRANT + SELECT + | DDL + | USAGE + | ALL + ON SAVED QUERY <saved_query> [,...] + TO <role> [,...] -- Allows role2 to use permissions granted to role1 GRANT <role1> [, ...] diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index f4f9b5008..44e27d54a 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -20,106 +20,96 @@ Syntax .. code-block:: postgres - -- Revoke permissions at the instance/ storage cluster level: - REVOKE - { - SUPERUSER - | LOGIN - | PASSWORD - } + -- Revoke permissions from all databases: + REVOKE { + SUPERUSER + | LOGIN + | PASSWORD '<password>' } FROM <role> [, ...] - + -- Revoke permissions at the database level: - REVOKE - { - { CREATE - | CONNECT - | DDL - | SUPERUSER - | CREATE FUNCTION }[, ...] - | ALL [PERMISSIONS] - } + REVOKE { + CREATE + | CONNECT + | DDL + | SUPERUSER + | CREATE FUNCTION } [, ...] + | ALL [PERMISSIONS] ON DATABASE <database> [, ...] FROM <role> [, ...] - -- Revoke permissions at the schema level: - REVOKE - { - { CREATE - | DDL - | USAGE - | SUPERUSER } [, ...] - | ALL [PERMISSIONS] - } + -- Revoke permissions at the schema level: + REVOKE { + CREATE + | DDL + | USAGE + | SUPERUSER } [, ...] + | ALL [PERMISSIONS] ON SCHEMA <schema> [, ...] FROM <role> [, ...] - - -- Revoke permissions at the object level: - REVOKE - { - { SELECT - | INSERT - | DELETE - | DDL - | UPDATE } [, ...] - | ALL - } - ON - { - [ TABLE ] <table_name> [, ...] - | ALL TABLES IN SCHEMA <schema_name> [, ...] - | VIEW <schema_name.view_name> [, ...] - | ALL VIEWS IN SCHEMA <schema_name> [, ...] - | FOREIGN TABLE <table_name> [, ...] - | ALL FOREIGN TABLES IN SCHEMA <schema_name> [, ...] - } + + -- Revoke permissions at the object level: + REVOKE { + SELECT + | INSERT + | DELETE + | DDL + | UPDATE } [, ...] + | ALL [PERMISSIONS] + ON {TABLE <table_name> [, ...] + | ALL TABLES IN SCHEMA <schema_name> [, ...]} FROM <role> [, ...] - REVOKE - { - { SELECT - | INSERT - | DELETE - | UPDATE } [, ...] - | ALL - } - ON - { - | CATALOG <catalog_name> [, ...] - } - FROM <role> [, ...] - - -- Revoke permissions at the column level: - REVOKE - { - { SELECT - | DDL } [, ...] - | ALL [PERMISSIONS]} - ON - { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] - } + -- Revoke permissions at the catalog level: + REVOKE { + {SELECT } [, ...] + | ALL [PERMISSIONS] } + ON { CATALOG <catalog_name> [, ...] } FROM <role> [, ...] - -- Revoke permissions at the service level: - REVOKE - { - { USAGE } [, ...] - | ALL [PERMISSIONS] - } - ON { SERVICE <service_name> } - FROM <role> [, ...] + -- Revoke permissions on the foreign table level: - -- Revoke permissions at the Saved Query level: REVOKE { - { SELECT - | DDL - | USAGE } [, ...] + {SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] } + ON { FOREIGN TABLE <table_name> [, ...] + | ALL FOREIGN TABLE IN SCHEMA <schema_name> [, ...]} + FROM <role> [, ...] + + -- Revoke function execution permission: + REVOKE { + ALL + | EXECUTE + | DDL } + ON FUNCTION <function_name> + FROM <role> + + -- Revoke permissions on the view level + REVOKE { + {SELECT + | DDL } [, ...] | ALL [PERMISSIONS] } - ON SAVED QUERY <saved_query_name> [, ...] + ON { VIEW <view_name> [, ...] + | ALL VIEWS IN SCHEMA <schema_name> [, ...]} FROM <role> [, ...] + + -- Revoke permissions at the Service level: + REVOKE { + {USAGE} [, ...] + | ALL [PERMISSIONS] } + ON { SERVICE <service_name> [, ...] + | ALL SERVICES IN SYSTEM } + FROM <role> [, ...] + + -- Revoke saved query permissions + REVOKE + SELECT + | DDL + | USAGE + | ALL + ON SAVED QUERY <saved_query> [,...] + FROM <role> [,...] -- Removes access to permissions in role1 by role 2 REVOKE [ADMIN OPTION FOR] <role1> [, ...] From c2e707f8464c78c476c11c8eef7bb00a7c4cafdb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:33:41 +0200 Subject: [PATCH 1142/1892] Update sample.java --- connecting_to_sqream/client_drivers/jdbc/sample.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/sample.java b/connecting_to_sqream/client_drivers/jdbc/sample.java index ca591aa26..9f43188b3 100644 --- a/connecting_to_sqream/client_drivers/jdbc/sample.java +++ b/connecting_to_sqream/client_drivers/jdbc/sample.java @@ -52,7 +52,7 @@ public void testJDBC() throws SQLException, IOException { } rs.close(); // Close the result set stmt.close(); // Close the statement handle - conn.close() + conn.close(); } From 28ea241137621ac690d49f06c03b8949f8c6e1ea Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jan 2024 10:21:57 +0200 Subject: [PATCH 1143/1892] 4.6 RN --- configuration_guides/current_method_configuration_levels.rst | 2 +- .../scalar_functions/conversion/is_castable.rst | 4 ++-- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- reference/sql/sql_syntax/cross_database_query.rst | 5 +++++ releases/4.6.rst | 4 ++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index be4d2e577..4294ffe8e 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -319,6 +319,6 @@ Flag List * - ``QueryTimeoutMinutes`` - Anyone - Session - - When set to 1—4320 minutes(72 hours), the flag is designed to identify queries that are stuck, having exceeded the specified time limit. Once the flag value is reached, the query automatically stops. + - The flag is intended to identify and address situations where queries have been in the queue for extended durations, suggesting potential irrelevance or a need for unavailable resources. If a query surpasses the defined time limit, which ranges from ``1`` to ``4320`` minutes (72 hours), the system automatically terminates the query. - integer - ``0`` (no query timeout) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst index 99224c365..328a2eaa5 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -1,10 +1,10 @@ .. _is_castable: ************ -IS CUSTABLE +IS CASTABLE ************ -The ``IsCastable`` function checks whether a cast operation is possible or supported for the given column and data type. If the cast is not supported, the ``CASE`` statement handles the exception by providing an alternative. +The ``IsCastable`` function checks whether a data type cast operation is supported for any given rows. If the cast is not supported, the ``CASE`` statement handles the exception by providing an alternative. Syntax ====== diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 30affe0b7..ebed5658b 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -181,7 +181,7 @@ Elements * - ``DELETE_SOURCE_ON_SUCCESS`` - ``false`` - ``true`` | ``false`` - - When set to ``true``, the target path's source file or folder is deleted after ``COPY FROM`` has successfully completed. This parameter cannot be executed concurrently with the ``OFFSET``, ``ERROR_LOG``, ``REJECTED_DATA``, ``ERROR_COUNT`` and ``LIMIT`` parameters. This parameter is supported for AWS, HADOOP, and GCP. Setting the parameter to "true" will restrict users without delete permissions on their operating system from executing the "COPY FROM" command. + - When set to ``true``, the source file or files associated with the target path will be deleted after a successful completion of the ``COPY FROM`` operation. File deletion will not occur in the case of unsuccessful ``COPY FROM`` operations, such as when a user lacks delete permissions on their operating system. It's important to note that this parameter cannot be used concurrently with the ``OFFSET``, ``ERROR_LOG``, ``REJECTED_DATA``, ``ERROR_COUNT``, and ``LIMIT`` parameters. This parameter is supported for S3, HDFS, and GCP Object Storage. .. _copy_date_parsers: diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index c2ae4c51c..57bc92c85 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -164,3 +164,8 @@ Querying data from three tables in different databases: ON t2.id = t3.id WHERE t1.date >= '2022-01-01' AND t2.status = 'active' AND t3.quantity > 10; +Limitation +========== + +The cross-database syntax is not supported for querying SQreamDB's logical schema, ``sqream_catalog``. + diff --git a/releases/4.6.rst b/releases/4.6.rst index df745580f..a0462c90b 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -38,11 +38,11 @@ New Features and Enhancements ► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning cloud storage but also helps conserve storage space. -► Cast data types seamlessly with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. +► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. ► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. -► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using non-positional arguments. +► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using keyword arguments. ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. From 5abe6bf3525554e1e920d4882fda2f72ee9cec81 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jan 2024 14:56:04 +0200 Subject: [PATCH 1144/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index fc13ce0ec..6470fd072 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0 ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 9335344301258166c4565c62035a45e80b2d1905 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:09:36 +0200 Subject: [PATCH 1145/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 6470fd072..b7df158de 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 7521a60d251b9fa69764384f90cdb7658a50f0c0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jan 2024 10:03:35 +0200 Subject: [PATCH 1146/1892] Update 4.6.rst --- releases/4.6.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index a0462c90b..bfb1d2999 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -21,7 +21,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 49 | +| Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | @@ -46,8 +46,6 @@ New Features and Enhancements ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. -► - Known Issues ------------ From 8825879cae719424a8747a9e6ee757dab223592e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jan 2024 10:29:15 +0200 Subject: [PATCH 1147/1892] Update index.rst --- releases/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/releases/index.rst b/releases/index.rst index d5df7e92d..06aebb47b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,11 @@ Release Notes ************* +:ref:` Version 4.6 - February xxxx, 2024<4.6>` + +* Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. +* Safely cast data types with the new :ref:`IsCastable<is_castable>` function. + :ref:`Version 4.5 - December 5, 2023<4.5>` * Introducing a new :ref:`Health-Check Monitor<select_health_check_monitoring>` utility command empowers administrators to oversee the database's health. This command serves as a valuable tool for monitoring, enabling administrators to assess and ensure the optimal health and performance of the database From cf76b1dadce1432fa1cbb08dbe96e8e699792d55 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jan 2024 10:29:46 +0200 Subject: [PATCH 1148/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index 06aebb47b..8bd5f678b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:` Version 4.6 - February xxxx, 2024<4.6>` +:ref:`Version 4.6 - February xxxx, 2024<4.6>` * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. * Safely cast data types with the new :ref:`IsCastable<is_castable>` function. From 8753de8d65990e67055156fe2afc044d23ecf423 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 08:17:13 +0200 Subject: [PATCH 1149/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 827a7c9a9..1ea6b65b9 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -810,11 +810,11 @@ Installing the CUDA Driver The current recommendation is for CUDA 12.2.1. -For A100 GPU and other A series GPUs, you must install the **CUDA 11.4.3 driver**. +For A100 GPU and other A series GPUs, you must install CUDA driver **11.4.3** or a later version. -For H100 GPU and other H series GPUs, you must install the **CUDA 11.8 driver** or a later version. +For H100 GPU and other H series GPUs, you must install CUDA driver **11.8** or a later version. -For L40S GPU and other L series GPUs, you must install the **CUDA 12.0 driver** or a later version. +For L40S GPU and other L series GPUs, you must install CUDA driver **12.0** or a later version. For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. From 9329015c2fc9d3a1170955ba0cac9bcd69b4327c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:02:07 +0200 Subject: [PATCH 1150/1892] SELECT RELEASE_DEFUNCT_LOCKS(); removal --- .../utility_commands/stop_statement.rst | 69 +++++++++---------- troubleshooting/lock_related_issues.rst | 26 ++----- 2 files changed, 38 insertions(+), 57 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/stop_statement.rst b/reference/sql/sql_statements/utility_commands/stop_statement.rst index 30efc25b5..64256d681 100644 --- a/reference/sql/sql_statements/utility_commands/stop_statement.rst +++ b/reference/sql/sql_statements/utility_commands/stop_statement.rst @@ -6,25 +6,15 @@ STOP_STATEMENT ``STOP_STATEMENT`` stops or aborts an active statement. -To find a statement by ID, see :ref:`show_server_status` and :ref:`show_connections`. - -.. tip:: Some DBMSs call this process killing a session, terminating a job, or kill query - -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - Syntax ========== -.. code-block:: postgres +.. code-block:: sql - stop_statement_statement ::= - SELECT STOP_STATEMENT(stmt_id) - ; - - stmt_id ::= bigint + stop_statement_statement ::= + SELECT STOP_STATEMENT(stmt_id) + + stmt_id ::= bigint Parameters ============ @@ -38,40 +28,45 @@ Parameters * - ``stmt_id`` - The statement ID to stop -Returns -========= -This utility does not return any value, and always succeeds even if the statement does not exist, or has already stopped. +Notes +===== +This utility always succeeds even if the statement does not exist, or has already stopped. -Notes -=========== +Example +======= -* This utility always succeeds even if the statement does not exist, or has already stopped. +1. Check your server status: -Examples -=========== +.. code-block:: psql -Using :ref:`show_connections` to get statement IDs ----------------------------------------------------- + SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 17-01-2022 16:19:31 | Executing | 17-01-2022 16:19:32 + sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 17-01-2022 16:19:39 | Executing | 17-01-2022 16:19:39 + sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 17-01-2022 15:55:01 | In Queue | 17-01-2022 15:55:02 -.. tip:: Use :ref:`show_server_status` to find statments from across the entire cluster, or :ref:`show_connections` to show statements from the current worker the client is connected to. +2. Retrieve stuck statement ID: .. code-block:: psql - t=> SELECT SHOW_CONNECTIONS(); - ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt - -------------+---------+---------------------+---------+---------------------+-------------------------- - 192.168.1.91 | 103 | 2019-12-24 00:01:27 | 129 | 2019-12-24 00:38:18 | SELECT GET_DATE(), * F... - 192.168.1.91 | 23 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 22 | 2019-12-24 00:01:27 | -1 | 2019-12-24 00:01:27 | - 192.168.1.91 | 26 | 2019-12-24 00:01:28 | -1 | 2019-12-24 00:01:28 | + SELECT SHOW_CONNECTIONS(); + + ip | conn_id | conn_start_time | stmt_id | stmt_start_time | stmt + --------------+----------+---------------------+---------+---------------------+----------------------------------------------------------------------------------------------------- + 192.168.0.111 | 19 | 2022-01-17 15:50:05 | 2484923 | 2022-01-17 16:19:31 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; + 192.168.1.112 | 2 | 2022-01-17 15:50:05 | 2484924 | 2022-01-17 16:19:39 | select show_server_status(); + 192.168.1.112 | 248 | 2022-01-17 15:50:05 | 2484665 | 2022-01-17 15:55:01 | select * from sqream_catalog.tables; +3. Stop stuck query: -The statement ID we're interested in is ``129``. We can now stop this statement: +.. code-block:: sql -.. code-block:: psql + SELECT STOP_STATEMENT(2484923); - t=> SELECT STOP_STATEMENT(129) - executed +Permissions +============= +The role must have the ``SUPERUSER`` permissions. \ No newline at end of file diff --git a/troubleshooting/lock_related_issues.rst b/troubleshooting/lock_related_issues.rst index ed1e21579..26df848a7 100644 --- a/troubleshooting/lock_related_issues.rst +++ b/troubleshooting/lock_related_issues.rst @@ -3,29 +3,15 @@ *********************** Lock Related Issues *********************** + Sometimes, a rare situation can occur where a lock is never freed. The workflow for troubleshooting locks is: -#. Identify which statement has obtained locks -#. Understand if the statement is itself stuck, or waiting for another statement -#. Try to abort the offending statement -#. Force the stale locks to be removed - -For example, we will assume that the statement from the previous example is stuck (statement #\ ``287``). We can attempt to abort it using :ref:`stop_statement`: - -.. code-block:: psql - - t=> SELECT STOP_STATEMENT(287); - executed - -If the locks still appear in the :ref:`show_locks` utility, we can force remove the stale locks: - -.. code-block:: psql - - t=> SELECT RELEASE_DEFUNCT_LOCKS(); - executed +#. Identify which statement has obtained locks. +#. Understand if the statement is itself stuck, or waiting for another statement. +#. Try to :ref:`stop<stop_statement>` the offending statement, as in the following example: -.. tip:: ``RELEASE_DEFUNCT_LOCKS`` has an optional input parameter to specify the number of seconds, after which ``RELEASE_DEFUNCT_LOCKS`` will execute. +.. code-block:: sql -.. warning:: This operation can cause some statements to fail on the specific worker on which they are queued. This is intended as a "last resort" to solve stale locks. \ No newline at end of file + SELECT STOP_STATEMENT(287); \ No newline at end of file From 54f84e58c2b385d0ff093f478735c3f340c82d29 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:05:47 +0200 Subject: [PATCH 1151/1892] Update lock_related_issues.rst --- troubleshooting/lock_related_issues.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/troubleshooting/lock_related_issues.rst b/troubleshooting/lock_related_issues.rst index 26df848a7..7a5ef908b 100644 --- a/troubleshooting/lock_related_issues.rst +++ b/troubleshooting/lock_related_issues.rst @@ -14,4 +14,4 @@ The workflow for troubleshooting locks is: .. code-block:: sql - SELECT STOP_STATEMENT(287); \ No newline at end of file + SELECT STOP_STATEMENT(2484923); \ No newline at end of file From e65ecfdd1a3fce55424eb481e6a45c12a4449c99 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:38:58 +0200 Subject: [PATCH 1152/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 196482a6e..696026077 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -56,7 +56,7 @@ An average single-node cluster can be a rackmount server or workstation, contain * - GPU - - NVIDIA 2x A100ת, H100, or L40S + NVIDIA 2x A00ת, H100, or L40S * - Operating System - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux From e0f2604166747b1cd8d82c613886233f710f0af9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 10:42:49 +0200 Subject: [PATCH 1153/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 696026077..e2ead1e4c 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -56,10 +56,10 @@ An average single-node cluster can be a rackmount server or workstation, contain * - GPU - - NVIDIA 2x A00ת, H100, or L40S + NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -106,7 +106,7 @@ The following table shows SQream's recommended hardware specifications: * - GPU - NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux Metadata Specifications ~~~~~~~~~~~~~~~~~~~~~~~ @@ -132,7 +132,7 @@ The following table shows SQream's recommended metadata server specifications: * - Power sources - Two Power Supplies - 800W AC 50/60Hz 100~240Vac/9.2-4.7A, 3139 BTU/hr * - Operating System - - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at 5GB/s or more. @@ -156,7 +156,7 @@ The following table shows SQream's recommended Studio server specifications: * - Onboard storage - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v7.x / 8.x or CentOS v7.9 + - Red Hat Enterprise Linux v7.9 or CentOS v7.9 Cluster Design Considerations ============================= @@ -229,7 +229,7 @@ Operating System SQream can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v7.x / 8.x + * Red Hat Enterprise Linux (RHEL) v7.9 * CentOS v7.9 * Amazon Linux 2018.03 From 6458b926004ff1f7aad4a52c7a8a7ab977ffe261 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 13:48:26 +0200 Subject: [PATCH 1154/1892] Update show_locks.rst --- .../utility_commands/show_locks.rst | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index d5e7c02ec..df9c769a2 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -8,24 +8,13 @@ SHOW_LOCKS Read more about locks in :ref:`concurrency_and_locks`. -Permissions -============= - -The role must have the ``SUPERUSER`` permissions. - Syntax ========== .. code-block:: postgres - show_locks_statement ::= - SELECT SHOW_LOCKS() - ; - -Parameters -============ - -None + show_locks_statement ::= + SELECT SHOW_LOCKS() Returns ========= @@ -67,13 +56,18 @@ In this example, we create a table based on results (:ref:`create_table_as`), bu .. code-block:: psql - t=> SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + SELECT SHOW_LOCKS(); + + statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time + -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + +Permissions +============= +This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file From b7b4904a52d7ffdc747ab3fbe57db3b77b56e8e0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:37:41 +0200 Subject: [PATCH 1155/1892] NodeJS --- ...mended_pre-installation_configurations.rst | 26 +++++++++---------- .../utility_commands/show_locks.rst | 6 ++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 1ea6b65b9..228875fd3 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -382,13 +382,13 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console - wget https://nodejs.org/dist/latest-v14.x/node-v14.21.3-linux-x64.tar.xz + wget https://nodejs.org/dist/v16.20.0/node-v16.20.0-linux-x64.tar.xz -2. Move the node-v14.21.3-linux-x64 file to the */usr/local* directory. +2. Move the node-v16.20.0-linux-x64 file to the */usr/local* directory. .. code-block:: console - sudo mv node-v14.21.3-linux-x64 /usr/local + sudo mv node-v16.20.0-linux-x64 /usr/local 3. Navigate to the ``/usr/bin/`` directory: @@ -396,23 +396,23 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not cd /usr/bin -4. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/node node`` directory: +4. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/node node`` directory: .. code-block:: console - sudo ln -s ../local/node-v14.21.3-linux-x64/bin/node node + sudo ln -s ../local/node-v16.20.0-linux-x64//bin/node node -5. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/npm npm`` directory: +5. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npm npm`` directory: .. code-block:: console - sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npm npm + sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npm npm -6. Create a symbolic link to the ``/local/node-v14.21.3-linux-x64/bin/npx npx`` directory: +6. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npx npx`` directory: .. code-block:: console - sudo ln -s ../local/node-v14.21.3-linux-x64/bin/npx npx + sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npx npx 7. Install the ``pm2`` process management: @@ -432,18 +432,18 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console - cd /usr/local/node-v14.21.3-linux-x64/lib/node_modules + cd /usr/local/node-v16.20.0-linux-x64/lib/node_modules tar -czvf pm2_x86.tar.gz pm2 c. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. :: - d. Move the ``pm2`` folder to the ``/usr/local/node-v14.21.3-linux-x64/lib/node_modules`` directory: + d. Move the ``pm2`` folder to the ``/usr/local/node-v16.20.0-linux-x64/lib/node_modules`` directory: .. code-block:: console - sudo mv pm2 /usr/local/node-v14.21.3-linux-x64/lib/node_modules + sudo mv pm2 /usr/local/node-v16.20.0-linux-x64/lib/node_modules e. Navigate back to the ``/usr/bin`` directory: @@ -455,7 +455,7 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console - sudo ln -s /usr/local/node-v14.21.3-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + sudo ln -s /usr/local/node-v16.20.0-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 g. Verify that installation was successful without using ``sudo``: diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index df9c769a2..bc814c9dc 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -9,7 +9,7 @@ SHOW_LOCKS Read more about locks in :ref:`concurrency_and_locks`. Syntax -========== +====== .. code-block:: postgres @@ -51,10 +51,10 @@ Examples Using ``SHOW_LOCKS`` to see active locks --------------------------------------------------- -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. +In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQreamDB applies locks during the table creation process to prevent the table from being altered during it's creation. -.. code-block:: psql +.. code-block:: postgres SELECT SHOW_LOCKS(); From 0122c85e6902d21ee49b2a2288af08527cbc6922 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:38:53 +0200 Subject: [PATCH 1156/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 228875fd3..0fdddd7e1 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -383,6 +383,7 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console wget https://nodejs.org/dist/v16.20.0/node-v16.20.0-linux-x64.tar.xz + tar -xf node-v16.20.0-linux-x64.tar.xz 2. Move the node-v16.20.0-linux-x64 file to the */usr/local* directory. From cf9d7e6a0dfe906c68c65268ff779f731079db9d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:44:09 +0200 Subject: [PATCH 1157/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 0fdddd7e1..75767ef26 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -383,7 +383,7 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console wget https://nodejs.org/dist/v16.20.0/node-v16.20.0-linux-x64.tar.xz - tar -xf node-v16.20.0-linux-x64.tar.xz + tar -xf node-v16.20.0-linux-x64.tar.xz 2. Move the node-v16.20.0-linux-x64 file to the */usr/local* directory. From 6ab7debaa0a87c10aa6a0f0c474674e491d47074 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Feb 2024 08:48:24 +0200 Subject: [PATCH 1158/1892] Update logging.rst --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 28ffca44b..e22a89632 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -292,7 +292,7 @@ SQL Syntax Command Line Utility -------------------- -If you cannot access SQream DB for any reason, you can also use a command line toolto collect the same information: +If you cannot access SQream DB for any reason, you can also use a command line tool to collect the same information: .. code-block:: console From 93834f62cc77e8391076ca752869a9d9b19a5dd5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:36:10 +0200 Subject: [PATCH 1159/1892] trino --- connecting_to_sqream/client_drivers/index.rst | 46 +++++---- .../client_drivers/trino/index.rst | 96 ++++++++----------- .../monitoring_query_performance.rst | 2 +- 3 files changed, 65 insertions(+), 79 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 1c3a43814..cb0681883 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,19 +18,29 @@ Client Driver Downloads - Docs - Notes - Operating System + * - **Apache Spark** + - `Apache Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ + - :ref:`spark` + - + - All * - **JDBC** - `sqream-jdbc 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All - * - **SQreamNet** - - `.NET .dll file <https://sq-ftp-public.s3.amazonaws.com/SqreamNet6.0_v5.0.0.zip>`_ - - :ref:`net` - - + * - **Node.JS** + - `sqream-v4.2.4 <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ + - :ref:`nodejs` + - Recommended installation via ``npm`` - All - * - **Apache Spark** - - `Apache Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ - - :ref:`spark` + * - **ODBC** + - For the **ODBC installer**, please contact your `SQreamDB representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ + - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` + - + - Windows, Linux + * - **Power BI** + - `Power BI Power Query Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ + - :ref:`power_bi` - - All * - **Python** @@ -38,26 +48,22 @@ Client Driver Downloads - :ref:`pysqream` - Recommended installation via ``pip`` - All - * - **Node.JS** - - `sqream-v4.2.4 <https://sq-ftp-public.s3.amazonaws.com/sqream-sqreamdb-4.2.4.tgz>`_ - - :ref:`nodejs` - - Recommended installation via ``npm`` + * - **SQreamNet** + - `.NET .dll file <https://sq-ftp-public.s3.amazonaws.com/SqreamNet6.0_v5.0.0.zip>`_ + - :ref:`net` + - - All * - **Tableau** - `Tableau Connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ - :ref:`tableau` - - All - * - **Power BI** - - `Power BI Power Query Connector <https://sq-ftp-public.s3.amazonaws.com/SqlODBC__v1.0.mez>`_ - - :ref:`power_bi` - - + * - **Trino** + - `Trino Connector <>`_ + - :ref:`trino` + - - All - * - **ODBC** - - For the **ODBC installer**, please contact your `SQreamDB representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ - - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` - - - - Windows, Linux + diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index c8c67a068..28c3bcb39 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -4,7 +4,6 @@ Trino ***** - If you are using Trino for distributed SQL query processing and wish to use it to connect to BLUE, follow these instructions. @@ -12,42 +11,26 @@ If you are using Trino for distributed SQL query processing and wish to use it t :local: :depth: 1 -Prerequisites -------------- +Before You Begin +================ -To use Trino with BLUE, you must have the following installed: +It is essential you have the following installed: -* SQream version 4.1 or later +* SQreamDB version 4.1 or later * Trino version 403 or later -* Trino Connector xxxx -* JDBC version 4.5.6 or later - - +* :ref:`Trino Connector<>`_ +* :ref:`JDBC<java_jdbc>` version 4.5.6 or later Installation ------------- - -.. contents:: - :local: - :depth: 1 - -JDBC -~~~~ - -In case JDBC is not yet configured, follow the :ref:`JDBC Client Drivers page<java_jdbc>` for registration and configuration guidance. - - -Trino Connector -~~~~~~~~~~~~~~~ +============ The Trino Connector must be installed on each cluster node dedicated to Trino. 1. Create a dedicated directory for the Trino Connector. -2. Download the `Trino Connector<...>` and extract the content of the ZIP file to the dedicated directory, as shown in the example: +2. Download the Trino Connector and extract the content of the ZIP file to the dedicated directory, as shown in the example: - -.. code-block:: postgres +.. code-block:: trino-server/ └── plugin @@ -57,57 +40,33 @@ The Trino Connector must be installed on each cluster node dedicated to Trino. ├── trino-sqream-SNAPSHOT.jar └── all dependencies +Connecting to SQreamDB +====================== - -Connecting to SQream --------------------- - -Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQream database. If you wish Trino to have access to more than one SQream database or server, you must create additional catalogs. +Trino uses catalogs for referencing stored objects such as tables, databases, and functions. Each Trino catalog may be configured with access to a single SQreamDB database. If you wish Trino to have access to more than one SQreamDB database or server, you must create additional catalogs. Catalogs may be created using ``properties`` files. Start by creating a ``sqream.properties`` file and placing it under ``trino-server/etc/catalog``. The following is an example of a properties file: -.. code-block:: postgres +.. code-block:: java connector.name=<name> connection-url=jdbc:Sqream://<host and port>/<database name>;[<optional parameters>; ...] connection-user=<user> connection-password=<password> -Syntax examples ---------------- - -The following is an example of the ``SHOW SCHEMAS FROM`` statement: - -.. code-block:: postgres - - SHOW SCHEMAS FROM sqream; - -The following is an example of the ``SHOW TABLES FROM`` statement: - -.. code-block:: postgres - - SHOW TABLES FROM sqream.public; - -The following is an example of the ``DESCRIBE sqream.public.t`` statement: - -.. code-block:: postgres - - DESCRIBE sqream.public.t; - - Supported Data Types and Mapping --------------------------------- +================================ -Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQream data types. +Use the appropriate Trino data type for executing queries. Upon execution, incompatible data types will be converted by Trino to SQreamDB data types. .. list-table:: :widths: auto :header-rows: 1 * - Trino type - - SQream type + - SQreamDB type * - ``BOOLEAN`` - ``BOOL`` * - ``TINYINT`` @@ -130,9 +89,30 @@ Use the appropriate Trino data type for executing queries. Upon execution, incom - ``TEXT`` * - ``DECIMAL(P,S)`` - ``NUMERIC(P,S)`` + +Examples +======== + +The following is an example of the ``SHOW SCHEMAS FROM`` statement: + +.. code-block:: postgres + + SHOW SCHEMAS FROM sqream; + +The following is an example of the ``SHOW TABLES FROM`` statement: + +.. code-block:: postgres + + SHOW TABLES FROM sqream.public; + +The following is an example of the ``DESCRIBE sqream.public.t`` statement: + +.. code-block:: postgres + + DESCRIBE sqream.public.t; Limitations ------------ +=========== The Trino Connector does not support the following SQL statements: diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 547d37d0a..a2ec79564 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -71,7 +71,7 @@ First, create a foreign table for the logs message TEXT, end_message TEXT(5) ) - WRAPPER cdv_fdw + WRAPPER csv_fdw OPTIONS ( LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', From 2fc014533b600c92d822e830e593f6536640438b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Feb 2024 15:26:07 +0200 Subject: [PATCH 1160/1892] trino --- connecting_to_sqream/client_drivers/index.rst | 2 +- connecting_to_sqream/client_drivers/trino/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index cb0681883..b499986b4 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -59,7 +59,7 @@ Client Driver Downloads - - All * - **Trino** - - `Trino Connector <>`_ + - `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar.gz>`_ - :ref:`trino` - - All diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index 28c3bcb39..734d949cf 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -18,7 +18,7 @@ It is essential you have the following installed: * SQreamDB version 4.1 or later * Trino version 403 or later -* :ref:`Trino Connector<>`_ +* `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar.gz>`_ * :ref:`JDBC<java_jdbc>` version 4.5.6 or later Installation From 1980ed856f0736e6daaa33ebd2ea29f8ff6c0293 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 5 Feb 2024 14:36:35 +0200 Subject: [PATCH 1161/1892] Update monitoring_query_performance.rst From ab8237619e4cebb123ebf12703186f1cdfbdd569 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 6 Feb 2024 10:52:59 +0200 Subject: [PATCH 1162/1892] Trino --- connecting_to_sqream/client_drivers/index.rst | 2 +- .../client_drivers/trino/index.rst | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index b499986b4..9ce16723c 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -59,7 +59,7 @@ Client Driver Downloads - - All * - **Trino** - - `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar.gz>`_ + - `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar>`_ - :ref:`trino` - - All diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index 734d949cf..72b6ef35a 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -18,7 +18,7 @@ It is essential you have the following installed: * SQreamDB version 4.1 or later * Trino version 403 or later -* `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar.gz>`_ +* `Trino Connector <https://sq-ftp-public.s3.amazonaws.com/trino-server-402.tar>`_ * :ref:`JDBC<java_jdbc>` version 4.5.6 or later Installation @@ -28,17 +28,7 @@ The Trino Connector must be installed on each cluster node dedicated to Trino. 1. Create a dedicated directory for the Trino Connector. -2. Download the Trino Connector and extract the content of the ZIP file to the dedicated directory, as shown in the example: - -.. code-block:: - - trino-server/ - └── plugin - └── sqream - ├── sqream-jdbc.jar - ├── trino-sqream-services.jar - ├── trino-sqream-SNAPSHOT.jar - └── all dependencies +2. Download the Trino Connector and extract the content of the ZIP file to the dedicated directory. Connecting to SQreamDB ====================== From ddcbfc812b0d91577a595584a6c0762751fb76cc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 6 Feb 2024 11:20:13 +0200 Subject: [PATCH 1163/1892] Update ldap.rst --- configuration_guides/ldap.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 4d9e25d24..b86d70c53 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -13,8 +13,9 @@ Before integrating SQream with LDAP consider the following: * If SQream DB has been installed and LDAP has not yet been integrated with SQream, it is best practice to ensure that the newly created LDAP user names are consistent with existing SQream role names. Previously existing SQream roles that were mistakenly not configured in LDAP or that have names which are different than in LDAP, will be recreated in SQream as roles that cannot log in, have no permissions, and have no default schema. -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 Before You Begin ================ @@ -32,8 +33,6 @@ Configuring SQream roles Follow this procedure if you already have LDAP configured for your environment. -**Procedure** - 1. Create a new role: .. code-block:: postgres @@ -58,8 +57,9 @@ You may also wish to :ref:`rename SQream roles<rename_role>` so that they are co Configuring LDAP Authentication =============================== -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 Configuration Methods --------------------- From c319abfca551e0b6ccd4347f5d6b42b81b925394 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 6 Feb 2024 16:46:58 +0200 Subject: [PATCH 1164/1892] Passw0rd! --- .../access_control_departmental_example.rst | 27 ++++++------------- .../access_control_managing_roles.rst | 6 ++--- .../access_control_commands/grant.rst | 2 +- 3 files changed, 12 insertions(+), 23 deletions(-) diff --git a/operational_guides/access_control_departmental_example.rst b/operational_guides/access_control_departmental_example.rst index 0a6b55e54..e17ce4717 100644 --- a/operational_guides/access_control_departmental_example.rst +++ b/operational_guides/access_control_departmental_example.rst @@ -1,8 +1,8 @@ .. _access_control_departmental_example: -************** +********************* Departmental Example -************** +********************* You work in a company with several departments. @@ -118,13 +118,13 @@ After the group roles have been created, you can now create user roles for each CREATE ROLE ecodd; GRANT LOGIN TO ecodd; - GRANT PASSWORD 'ecodds_secret_password' TO ecodd; + GRANT PASSWORD 'Passw0rd!' TO ecodd; GRANT CONNECT ON DATABASE my_database TO ecodd; GRANT my_schema_database_designers TO ecodd; CREATE ROLE ebachmann; GRANT LOGIN TO ebachmann; - GRANT PASSWORD 'another_secret_password' TO ebachmann; + GRANT PASSWORD 'Passw0rd!!!' TO ebachmann; GRANT CONNECT ON DATABASE my_database TO ebachmann; GRANT my_database_designers TO ebachmann; @@ -136,19 +136,19 @@ After the group roles have been created, you can now create user roles for each CREATE ROLE jbarker; GRANT LOGIN TO jbarker; - GRANT PASSWORD 'action_jack' TO jbarker; + GRANT PASSWORD 'action_jacC%k' TO jbarker; GRANT CONNECT ON DATABASE my_database TO jbarker; GRANT my_schema_readers TO jbarker; CREATE ROLE lbream; GRANT LOGIN TO lbream; - GRANT PASSWORD 'artichoke123' TO lbream; + GRANT PASSWORD 'artichoke123O$' TO lbream; GRANT CONNECT ON DATABASE my_database TO lbream; GRANT my_schema_readers TO lbream; CREATE ROLE pgregory; GRANT LOGIN TO pgregory; - GRANT PASSWORD 'c1ca6a' TO pgregory; + GRANT PASSWORD 'c1ca6aG$' TO pgregory; GRANT CONNECT ON DATABASE my_database TO pgregory; GRANT my_schema_readers TO pgregory; @@ -156,22 +156,11 @@ After the group roles have been created, you can now create user roles for each CREATE ROLE hoover; GRANT LOGIN TO hoover; - GRANT PASSWORD 'mintchip' TO hoover; + GRANT PASSWORD 'mint*Rchip' TO hoover; GRANT CONNECT ON DATABASE my_database TO hoover; GRANT my_schema_security_officers TO hoover; -.. todo: - create some example users - show that they have the right permission - try out the with admin option. we can't really do a security officer because - only superusers can create users and logins. see what can be done - need 1-2 users in each group, for at least 2 schemas/departments - this example will be very big just to show what this setup can do ... - example: a security officer for a department which will only have - read only access to a schema can only get that with admin option - access granted to them - After this setup: * Database designers will be able to run any ddl on objects in the schema and create new objects, including ones created by other database designers diff --git a/operational_guides/access_control_managing_roles.rst b/operational_guides/access_control_managing_roles.rst index 9b81b855d..b6e9985f8 100644 --- a/operational_guides/access_control_managing_roles.rst +++ b/operational_guides/access_control_managing_roles.rst @@ -32,7 +32,7 @@ The following is an example of creating a new role: CREATE ROLE new_role_name ; GRANT LOGIN TO new_role_name; - GRANT PASSWORD 'my_password' to new_role_name; + GRANT PASSWORD 'Passw0rd!' to new_role_name; GRANT CONNECT ON DATABASE master to new_role_name; A database role may have a number of permissions that define what tasks it can perform, which are assigned using the :ref:`grant` command. @@ -81,7 +81,7 @@ The following is an example of changing a user password: .. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. Altering Public Role Permissions ------------------------------- +--------------------------------- The database has a predefined ``PUBLIC`` role that cannot be deleted. Each user role is automatically granted membership in the ``PUBLIC`` role public group, and this membership cannot be revoked. However, you have the capability to adjust the permissions associated with this ``PUBLIC`` role. @@ -89,7 +89,7 @@ The ``PUBLIC`` role has ``USAGE`` and ``CREATE`` permissions on ``PUBLIC`` schem Altering Role Membership (Groups) ------------------------------- +--------------------------------- Many database administrators find it useful to group user roles together. By grouping users, permissions can be granted to, or revoked from a group with one command. In SQream DB, this is done by creating a group role, granting permissions to it, and then assigning users to that group role. diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 7fbc159bb..ffd914cf5 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -273,7 +273,7 @@ The following is an example of changing a password for a user role. This is done .. code-block:: postgres - GRANT PASSWORD 'new_password' TO rhendricks; + GRANT PASSWORD 'Passw0rd!' TO rhendricks; .. note:: Granting a new password overrides any previous password. Changing the password while the role has an active running statement does not affect that statement, but will affect subsequent statements. From d5c5e7695994baab7004e409b3575912ef4a5426 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Feb 2024 08:33:53 +0200 Subject: [PATCH 1165/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 78 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 40 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index e2ead1e4c..8e92e933e 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -4,22 +4,22 @@ Hardware Guide ************** -The **Hardware Guide** describes the SQream reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQream installation. +The **Hardware Guide** describes the SQreamDB reference architecture, emphasizing the benefits to the technical audience, and provides guidance for end-users on selecting the right configuration for a SQreamDB installation. .. rubric:: Need help? -This page is intended as a "reference" to suggested hardware. However, different workloads require different solution sizes. SQream's experienced customer support has the experience to advise on these matters to ensure the best experience. +This page is intended as a "reference" to suggested hardware. However, different workloads require different solution sizes. SQreamDB's experienced customer support has the experience to advise on these matters to ensure the best experience. -Visit `SQream's support portal <https://sqream.atlassian.net/servicedesk/customer/portals>`_ for additional support. +Visit `SQreamDB's support portal <https://sqream.atlassian.net/servicedesk/customer/portals>`_ for additional support. -A SQream Cluster -================ +A SQreamDB Cluster +================== -SQream recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. +SQreamDB recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. -A typical SQream cluster includes one or more nodes, consisting of +A typical SQreamDB cluster includes one or more nodes, consisting of -* Two-socket enterprise processors, like the Intel® Xeon® Gold processor family or an IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. +* Two-socket enterprise processors, such as Intel® Xeon® Gold processors or the IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. :: @@ -32,7 +32,7 @@ A typical SQream cluster includes one or more nodes, consisting of Single-Node Cluster Example --------------------------- -A single-node SQream cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). +A single-node SQreamDB cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). An average single-node cluster can be a rackmount server or workstation, containing the following components: @@ -44,7 +44,7 @@ An average single-node cluster can be a rackmount server or workstation, contain - Type * - Server - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) - * - Processor + * - Processors - 2x Intel Xeon Gold 6348 (28C/56HT) 3.5GHz or similar * - RAM - 1.5 TB @@ -63,14 +63,14 @@ An average single-node cluster can be a rackmount server or workstation, contain .. note:: If you are using internal storage, your volumes must be formatted as xfs. -In this system configuration, SQream can store about 100TB of raw data (assuming an average compression ratio and ~30TB of usable raw storage). +In this system configuration, SQreamDB can store about 100TB of raw data (assuming an average compression ratio and ~30TB of usable raw storage). -If a NAS is used, the 10x SSD drives can be omitted, but SQream recommends 2TB of local spool space on SSD or NVMe drives. +If a NAS is used, the 10x SSD drives can be omitted, but SQreamDB recommends 2TB of local spool space on SSD or NVMe drives. Multi-Node Cluster Examples --------------------------- -Multi-node clusters can handle any number of concurrent users. A typical SQream cluster relies on a minimum of two GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. +Multi-node clusters can handle any number of concurrent users. A typical SQreamDB cluster relies on a minimum of two GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. The **Multi-Node Cluster Examples** section describes the following specifications: @@ -81,7 +81,7 @@ The **Multi-Node Cluster Examples** section describes the following specificatio Hardware Specifications ~~~~~~~~~~~~~~~~~~~~~~~ -The following table shows SQream's recommended hardware specifications: +The following table shows SQreamDB's recommended hardware specifications: .. list-table:: :widths: 15 65 @@ -91,7 +91,7 @@ The following table shows SQream's recommended hardware specifications: - Type * - Server - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) - * - Processor + * - Processors - 2x Intel Xeon Gold 6348 (28C/56HT) 3.5GHz or similar * - RAM - 2 TB @@ -111,7 +111,7 @@ The following table shows SQream's recommended hardware specifications: Metadata Specifications ~~~~~~~~~~~~~~~~~~~~~~~ -The following table shows SQream's recommended metadata server specifications: +The following table shows SQreamDB's recommended metadata server specifications: .. list-table:: :widths: 15 90 @@ -120,26 +120,24 @@ The following table shows SQream's recommended metadata server specifications: * - Component - Type * - Processors - - Two Intel Xeon Gold 6342 2.8 Ghz 24C processors or similar + - 2x Intel Xeon Gold 6342 2.8 Ghz 24C processors or similar * - RAM - 512GB DDR4 RAM 8x64GB RDIMM or similar - * - Discs - - Two 960 GB MVMe SSD drives in RAID 1 or similar + * - Onboard storage + - 2x 960 GB MVMe SSD drives in RAID 1 or similar * - Network Card (Storage) - - Two Mellanox ConnectX-6 Single Port HDR VPI InfiniBand Adapter cards at 100GbE or similar. - * - Network Card (Corporate) - - Two 1 GbE cards or similar - * - Power sources - - Two Power Supplies - 800W AC 50/60Hz 100~240Vac/9.2-4.7A, 3139 BTU/hr + - 2x Mellanox ConnectX-6 Single Port HDR VPI InfiniBand Adapter cards at 100GbE or similar. + * - Network Card (Client) + - 2x 1 GbE cards or similar * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux -.. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQream worker can read data at 5GB/s or more. +.. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. -SQream Studio Server Example ----------------------------- +SQreamDB Studio Server Example +------------------------------ -The following table shows SQream's recommended Studio server specifications: +The following table shows SQreamDB's recommended Studio server specifications: .. list-table:: :widths: auto @@ -163,24 +161,24 @@ Cluster Design Considerations This section describes the following cluster design considerations: -* In a SQream installation, the storage and computing are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. +* In a SQreamDB installation, the storage and computing are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. :: -* SQream uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. At least 256GB of RAM per physical GPU is recommended. +* SQreamDB uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. At least 256GB of RAM per physical GPU is recommended. :: -* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQream recommends an SSD or NVMe drive in RAID0 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. +* Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQreamDB recommends an SSD or NVMe drive in RAID0 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. :: -* When using NAS devices, SQream recommends approximately 5GB/s of burst throughput from storage per GPU. +* When using NAS devices, SQreamDB recommends approximately 5GB/s of burst throughput from storage per GPU. Balancing Cost and Performance ------------------------------ -Prior to designing and deploying a SQream cluster, a number of important factors must be considered. +Prior to designing and deploying a SQreamDB cluster, a number of important factors must be considered. The **Balancing Cost and Performance** section provides a breakdown of deployment details to ensure that this installation exceeds or meets the stated requirements. The rationale provided includes the necessary information for modifying configurations to suit the customer use-case scenario, as shown in the following table: @@ -208,26 +206,26 @@ The **Balancing Cost and Performance** section provides a breakdown of deploymen CPU Compute ----------- -SQream relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. +SQreamDB relies on multi-core Intel Gold Xeon processors or IBM POWER9 processors and recommends a dual-socket machine populated with CPUs with 18C/36HT or better. While a higher core count may not necessarily affect query performance, more cores will enable higher concurrency and better load performance. GPU Compute and RAM ------------------- -The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQream recommends the NVIDIA Tesla A100 80GB GPU for the best performance and highest concurrent user support. +The NVIDIA Tesla range of high-throughput GPU accelerators provides the best performance for enterprise environments. Most cards have ECC memory, which is crucial for delivering correct results every time. SQreamDB recommends the NVIDIA Tesla A100 80GB GPU for the best performance and highest concurrent user support. GPU RAM, sometimes called GRAM or VRAM, is used for processing queries. It is possible to select GPUs with less RAM. However, the smaller GPU RAM results in reduced concurrency, as the GPU RAM is used extensively in operations like JOINs, ORDER BY, GROUP BY, and all SQL transforms. RAM --- -SQream requires using **Error-Correcting Code memory (ECC)**, standard on most enterprise servers. Large amounts of memory are required for improved performance for heavy external operations, such as sorting and joining. +SQreamDB requires using **Error-Correcting Code memory (ECC)**, standard on most enterprise servers. Large amounts of memory are required for improved performance for heavy external operations, such as sorting and joining. -SQream recommends at least 256GB of RAM per GPU on your machine. +SQreamDB recommends at least 256GB of RAM per GPU on your machine. Operating System ---------------- -SQream can run on the following 64-bit Linux operating systems: +SQreamDB can run on the following 64-bit Linux operating systems: * Red Hat Enterprise Linux (RHEL) v7.9 * CentOS v7.9 @@ -237,7 +235,7 @@ SQream can run on the following 64-bit Linux operating systems: Storage ------- -For clustered scale-out installations, SQream relies on NAS storage. For stand-alone installations, SQream relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. +For clustered scale-out installations, SQreamDB relies on NAS storage. For stand-alone installations, SQreamDB relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. -SQream recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQream recommends 1 Tesla A100 / H100 or L40S GPU per 2 users, for full, uninterrupted dedicated access. +SQreamDB recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQreamDB recommends 1 Tesla A100 / H100 or L40S GPU per 2 users, for full, uninterrupted dedicated access. From 97bdedf29d4bcdf038c1359e4687c406e581fb87 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Feb 2024 09:07:57 +0200 Subject: [PATCH 1166/1892] Maintenance --- getting_started/creating_a_database.rst | 1 + getting_started/creating_your_first_table.rst | 1 + getting_started/deleting_rows.rst | 11 ++++---- getting_started/hardware_guide.rst | 8 ++++-- getting_started/ingesting_data.rst | 1 + getting_started/inserting_rows.rst | 28 +++++++++---------- getting_started/listing_tables.rst | 4 +-- .../non_production_hardware_guide.rst | 1 + .../performing_basic_sqream_operations.rst | 5 ++-- getting_started/querying_data.rst | 4 ++- getting_started/running_queries.rst | 28 ++++++++----------- .../running_the_sqream_sql_client.rst | 8 +++--- ...ing_query_results_to_a_csv_or_psv_file.rst | 5 ++-- installation_guides/index.rst | 3 +- .../installing_and_launching_sqream.rst | 9 +++--- .../installing_dashboard_data_collector.rst | 7 +++-- .../launching_sqream_with_monit.rst | 1 + 17 files changed, 66 insertions(+), 59 deletions(-) diff --git a/getting_started/creating_a_database.rst b/getting_started/creating_a_database.rst index 6b208f123..c55f077d4 100644 --- a/getting_started/creating_a_database.rst +++ b/getting_started/creating_a_database.rst @@ -3,6 +3,7 @@ **************************** Creating a Database **************************** + Once you've installed SQream you can create a database. **To create a database:** diff --git a/getting_started/creating_your_first_table.rst b/getting_started/creating_your_first_table.rst index 05c601c3e..f02ab3b21 100644 --- a/getting_started/creating_your_first_table.rst +++ b/getting_started/creating_your_first_table.rst @@ -3,6 +3,7 @@ **************************** Creating Your First Table **************************** + The **Creating Your First Table** section describes the following: * :ref:`Creating a table<creating_a_table>` diff --git a/getting_started/deleting_rows.rst b/getting_started/deleting_rows.rst index 2ff33b8dc..6ce20d489 100644 --- a/getting_started/deleting_rows.rst +++ b/getting_started/deleting_rows.rst @@ -3,6 +3,7 @@ **************************** Deleting Rows **************************** + The **Deleting Rows** section describes the following: * :ref:`Deleting selected rows<deleting_selected_rows>` @@ -16,17 +17,16 @@ You can delete rows in a table selectively using the ``DELETE`` command. You mus .. code-block:: psql - test=> DELETE FROM cool_animals WHERE weight is null; + DELETE FROM cool_animals WHERE weight is null; executed - master=> SELECT * FROM cool_animals; + SELECT * FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 4,Elephant ,6500 5,Rhinoceros ,2100 - 5 rows .. _deleting_all_rows: @@ -36,9 +36,8 @@ You can delete all rows in a table using the ``TRUNCATE`` command followed by th .. code-block:: psql - test=> TRUNCATE TABLE cool_animals; - - executed + TRUNCATE TABLE cool_animals; + .. note:: While :ref:`truncate` deletes data from disk immediately, :ref:`delete` does not physically remove the deleted rows. diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 8e92e933e..e7f0acde3 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -12,8 +12,12 @@ This page is intended as a "reference" to suggested hardware. However, different Visit `SQreamDB's support portal <https://sqream.atlassian.net/servicedesk/customer/portals>`_ for additional support. -A SQreamDB Cluster -================== +.. contents:: + :local: + + +Cluster Architectures +===================== SQreamDB recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. diff --git a/getting_started/ingesting_data.rst b/getting_started/ingesting_data.rst index ff82a685e..4da4d764c 100644 --- a/getting_started/ingesting_data.rst +++ b/getting_started/ingesting_data.rst @@ -3,6 +3,7 @@ **************************** Ingesting Data **************************** + After creating a database you can begin ingesting data into SQream. For more information about ingesting data, see `Data Ingestion Guides <https://docs.sqream.com/en/latest/data_ingestion/index.html>`_. \ No newline at end of file diff --git a/getting_started/inserting_rows.rst b/getting_started/inserting_rows.rst index 890befebf..d52f133a5 100644 --- a/getting_started/inserting_rows.rst +++ b/getting_started/inserting_rows.rst @@ -3,6 +3,7 @@ **************************** Inserting Rows **************************** + The **Inserting Rows** section describes the following: * :ref:`Inserting basic rows<inserting_basic_rows>` @@ -19,9 +20,8 @@ You can insert basic rows into a table using the ``INSERT`` statement. The inser .. code-block:: psql - test=> INSERT INTO cool_animals VALUES (1, 'Dog', 7); + INSERT INTO cool_animals VALUES (1, 'Dog', 7); - executed .. _changing_value_order: @@ -31,9 +31,8 @@ You can change the order of values by specifying the column order, as shown in t .. code-block:: psql - test=> INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); + INSERT INTO cool_animals(weight, id, name) VALUES (3, 2, 'Possum'); - executed .. _inserting_multiple_rows: @@ -43,12 +42,11 @@ You can insert multiple rows using the ``INSERT`` statement by using sets of par .. code-block:: psql - test=> INSERT INTO cool_animals VALUES - (3, 'Cat', 5) , - (4, 'Elephant', 6500) , - (5, 'Rhinoceros', 2100); + INSERT INTO cool_animals VALUES + (3, 'Cat', 5) , + (4, 'Elephant', 6500) , + (5, 'Rhinoceros', 2100); - executed .. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. @@ -60,16 +58,16 @@ Omitting columns that have a default values (including default ``NULL`` values) .. code-block:: psql - test=> INSERT INTO cool_animals (id) VALUES (6); + INSERT INTO cool_animals (id) VALUES (6); - executed + .. code-block:: psql - test=> INSERT INTO cool_animals (id) VALUES (6); + INSERT INTO cool_animals (id) VALUES (6); - executed - test=> SELECT * FROM cool_animals; + + SELECT * FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 @@ -77,7 +75,7 @@ Omitting columns that have a default values (including default ``NULL`` values) 5,Rhinoceros ,2100 6,\N,\N - 6 rows + .. note:: Null row values are represented as ``\N`` diff --git a/getting_started/listing_tables.rst b/getting_started/listing_tables.rst index d376cb7ee..a197207e1 100644 --- a/getting_started/listing_tables.rst +++ b/getting_started/listing_tables.rst @@ -3,11 +3,11 @@ **************************** Listing Tables **************************** + To see the tables in the current database you can query the catalog, as shown in the following example: .. code-block:: psql - test=> SELECT table_name FROM sqream_catalog.tables; + SELECT table_name FROM sqream_catalog.tables; cool_animals - 1 rows \ No newline at end of file diff --git a/getting_started/non_production_hardware_guide.rst b/getting_started/non_production_hardware_guide.rst index 03c738887..6b990401c 100644 --- a/getting_started/non_production_hardware_guide.rst +++ b/getting_started/non_production_hardware_guide.rst @@ -3,6 +3,7 @@ *************************************** Staging and Development Hardware Guide *************************************** + The **Staging and Development Hardware Guide** describes the SQream recommended HW for development, staging and or QA desktop and servers. .. warning:: The HW specification in this page are not intended for production use! diff --git a/getting_started/performing_basic_sqream_operations.rst b/getting_started/performing_basic_sqream_operations.rst index 0808c22dd..af12ed813 100644 --- a/getting_started/performing_basic_sqream_operations.rst +++ b/getting_started/performing_basic_sqream_operations.rst @@ -1,8 +1,9 @@ .. _performing_basic_sqream_operations: -**************************** +********************************** Performing Basic SQream Operations -**************************** +********************************** + After installing SQream you can perform the operations described on this page: .. toctree:: diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst index 7b6b46aed..6ac28db4c 100644 --- a/getting_started/querying_data.rst +++ b/getting_started/querying_data.rst @@ -3,6 +3,7 @@ **************************** Querying Data **************************** + One of the most basic operations when using SQream is querying data. To begin familiarizing yourself with querying data, you can create the following table using the ``CREATE TABLE`` statement: @@ -38,7 +39,8 @@ The above query gets the following from the table above, limited to showing the .. code-block:: psql - nba=> SELECT Name, Team, Age FROM nba LIMIT 10; + SELECT Name, Team, Age FROM nba LIMIT 10; + Avery Bradley,Boston Celtics,25 Jae Crowder,Boston Celtics,25 John Holland,Boston Celtics,27 diff --git a/getting_started/running_queries.rst b/getting_started/running_queries.rst index 57f6811d7..fe3891e1c 100644 --- a/getting_started/running_queries.rst +++ b/getting_started/running_queries.rst @@ -3,6 +3,7 @@ **************************** Running Queries **************************** + The **Running Queries** section describes the following: * :ref:`Running basic queries<running_basic_queries>` @@ -21,15 +22,14 @@ You can run a basic query using the ``SELECT`` keyword, followed by a list of co .. code-block:: psql - test=> SELECT id, name, weight FROM cool_animals; + SELECT id, name, weight FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 4,Elephant ,6500 5,Rhinoceros ,2100 6,\N,\N - - 6 rows + For more information on the ``SELECT`` keyword, see :ref:`select`. @@ -41,15 +41,14 @@ You can output all columns without specifying them using the star operator ``*`` .. code-block:: psql - test=> SELECT * FROM cool_animals; + SELECT * FROM cool_animals; 1,Dog ,7 2,Possum ,3 3,Cat ,5 4,Elephant ,6500 5,Rhinoceros ,2100 6,\N,\N - - 6 rows + .. _outputting_shorthand_table_values: @@ -59,10 +58,9 @@ You can output the number of values in a table without getting the full result s .. code-block:: psql - test=> SELECT COUNT(*) FROM cool_animals; + SELECT COUNT(*) FROM cool_animals; 6 - - 1 row + .. _filtering_results: @@ -72,11 +70,10 @@ You can filter results by adding a ``WHERE`` clause and specifying the filter co .. code-block:: psql - test=> SELECT id, name, weight FROM cool_animals WHERE weight > 1000; + SELECT id, name, weight FROM cool_animals WHERE weight > 1000; 4,Elephant ,6500 5,Rhinoceros ,2100 - - 2 rows + .. _sorting_results: @@ -86,7 +83,7 @@ You can sort results by adding an ``ORDER BY`` clause and specifying ascending ( .. code-block:: psql - test=> SELECT * FROM cool_animals ORDER BY weight DESC; + SELECT * FROM cool_animals ORDER BY weight DESC; 4,Elephant ,6500 5,Rhinoceros ,2100 1,Dog ,7 @@ -94,8 +91,6 @@ You can sort results by adding an ``ORDER BY`` clause and specifying ascending ( 2,Possum ,3 6,\N,\N - 6 rows - .. _filtering_null_rows: **Filtering Null Rows** @@ -104,14 +99,13 @@ You can filter null rows by adding an ``IS NOT NULL`` filter, as shown in the fo .. code-block:: psql - test=> SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; + SELECT * FROM cool_animals WHERE weight IS NOT NULL ORDER BY weight DESC; 4,Elephant ,6500 5,Rhinoceros ,2100 1,Dog ,7 3,Cat ,5 2,Possum ,3 - 5 rows For more information, see the following: diff --git a/getting_started/running_the_sqream_sql_client.rst b/getting_started/running_the_sqream_sql_client.rst index faba6494d..0731a20aa 100644 --- a/getting_started/running_the_sqream_sql_client.rst +++ b/getting_started/running_the_sqream_sql_client.rst @@ -1,8 +1,9 @@ .. _running_the_sqream_sql_client: -**************************** +***************************** Running the SQream SQL Client -**************************** +***************************** + The following example shows how to run the SQream SQL client: .. code-block:: psql @@ -12,8 +13,7 @@ The following example shows how to run the SQream SQL client: Interactive client mode To quit, use ^D or \q. - - master=> _ + Running the SQream SQL client prompts you to provide your password. Use the username and password that you have set up, or your DBA has provided. diff --git a/getting_started/saving_query_results_to_a_csv_or_psv_file.rst b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst index 9a40ad440..c5da4d3ed 100644 --- a/getting_started/saving_query_results_to_a_csv_or_psv_file.rst +++ b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst @@ -1,8 +1,9 @@ .. _saving_query_results_to_a_csv_or_psv_file: -**************************** +***************************************** Saving Query Results to a CSV or PSV File -**************************** +***************************************** + You can save query results to a CSV or PSV file using the ``sqream sql`` command from a CLI client. This saves your query results to the selected delimited file format, as shown in the following example: .. code-block:: console diff --git a/installation_guides/index.rst b/installation_guides/index.rst index 47f89c219..216fde62d 100644 --- a/installation_guides/index.rst +++ b/installation_guides/index.rst @@ -3,7 +3,8 @@ ************************* Installation Guides ************************* -Before you get started using SQream, consider your business needs and available resources. SQream was designed to run in a number of environments, and to be installed using different methods depending on your requirements. This determines which installation method to use. + +Before you get started using SQreamDB, consider your business needs and available resources. SQreamDB was designed to run in a number of environments, and to be installed using different methods depending on your requirements. This determines which installation method to use. The **Installation Guides** section describes the following installation guide sets: diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 2c325c3a7..b82bc95e8 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -1,9 +1,10 @@ .. _installing_and_launching_sqream: -************************* -Installing and Launching SQream -************************* -The **Installing and Launching SQream** page includes the following installation guides: +********************************* +Installing and Launching SQreamDB +********************************* + +The **Installing and Launching SQreamDB** page includes the following installation guides: .. toctree:: :maxdepth: 1 diff --git a/installation_guides/installing_dashboard_data_collector.rst b/installation_guides/installing_dashboard_data_collector.rst index ba0475a6d..0c154da9d 100644 --- a/installation_guides/installing_dashboard_data_collector.rst +++ b/installation_guides/installing_dashboard_data_collector.rst @@ -2,12 +2,13 @@ -*********************** +*************************************** Installing the Dashboard Data Collector -*********************** +*************************************** Installing the Dashboard Data Collector -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + After accessing the Prometheus user interface, you can install the **Dashboard Data Collector**. You must install the Dashboard Data Collector to enable the Dashboard in Studio. .. note:: Before installing the Dashboard Data collector, verify that Prometheus has been installed and configured for the cluster. diff --git a/installation_guides/launching_sqream_with_monit.rst b/installation_guides/launching_sqream_with_monit.rst index b8dc4f1a6..5e0822734 100644 --- a/installation_guides/launching_sqream_with_monit.rst +++ b/installation_guides/launching_sqream_with_monit.rst @@ -3,6 +3,7 @@ ********************************************* Launching SQream with Monit ********************************************* + This procedure describes how to launch SQream using Monit. Launching SQream From a339a35379542494f619277f150ba5ecc071d21f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Feb 2024 11:00:15 +0200 Subject: [PATCH 1167/1892] CLI --- reference/cli/sqream_cli.rst | 450 +++++++++++++++++++++++++++++++ reference/cli/sqream_console.rst | 2 +- 2 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 reference/cli/sqream_cli.rst diff --git a/reference/cli/sqream_cli.rst b/reference/cli/sqream_cli.rst new file mode 100644 index 000000000..76eabae72 --- /dev/null +++ b/reference/cli/sqream_cli.rst @@ -0,0 +1,450 @@ +.. _sqream_cli: + +********************************* +SQreamDB CLI +********************************* + +``sqream-console`` is an interactive shell designed to help manage a dockerized SQream DB installation. + +The console itself is a dockerized application. + +.. contents:: + :local: + :depth: 1 + +Starting the console +====================== + +``sqream-console`` can be found in your SQream DB installation, under the name ``sqream-console``. + +Start the console by executing it from the shell + +.. code-block:: console + + $ ./sqream-console + .................................................................................................................... + + ███████╗ ██████╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗███████╗ ██████╗ ██╗ ███████╗ + ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗████╗ ████║ ██╔════╝██╔═══██╗████╗ ██║██╔════╝██╔═══██╗██║ ██╔════╝ + ███████╗██║ ██║██████╔╝█████╗ ███████║██╔████╔██║ ██║ ██║ ██║██╔██╗ ██║███████╗██║ ██║██║ █████╗ + ╚════██║██║▄▄ ██║██╔══██╗██╔══╝ ██╔══██║██║╚██╔╝██║ ██║ ██║ ██║██║╚██╗██║╚════██║██║ ██║██║ ██╔══╝ + ███████║╚██████╔╝██║ ██║███████╗██║ ██║██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██║ ╚████║███████║╚██████╔╝███████╗███████╗ + ╚══════╝ ╚══▀▀═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝ + + .................................................................................................................... + + + Welcome to SQream Console ver 1.7.6, type exit to log-out + + usage: sqream [-h] [--settings] {master,worker,client,editor} ... + + Run SQream Cluster + + optional arguments: + -h, --help show this help message and exit + --settings sqream environment variables settings + + subcommands: + sqream services + + {master,worker,client,editor} + sub-command help + master start sqream master + worker start sqream worker + client operating sqream client + editor operating sqream statement editor + sqream-console> + +The console is now waiting for commands. + +The console is a wrapper around a standard linux shell. It supports commands like ``ls``, ``cp``, etc. + +All SQream DB-specific commands start with the keyword ``sqream``. + + +Operations and flag reference +=============================== + +Commands +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Command + - Description + * - ``sqream --help`` + - Shows the initial usage information + * - ``sqream master`` + - Controls the master node's operations + * - ``sqream worker`` + - Controls workers' operations + * - ``sqream client`` + - Access to :ref:`sqream sql<sqream_sql_cli_reference>` + * - ``sqream editor`` + - Controls the statement editor's operations (web UI) + +.. _master_node: + +Master +------------ + +The master node contains the :ref:`metadata server<metadata_server_cli_reference>` and the :ref:`load balancer<server_picker_cli_reference>`. + +Syntax +^^^^^^^^^^ + +.. code-block:: console + + sqream master <flags> + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag/command + - Description + * - ``--start [ --single-host ]`` + - + Starts the master node. + The ``--single-host`` modifier sets the mode to allow all containers to run on the same server. + + * - ``--stop [ --all ]`` + - + Stops the master node and all connected :ref:`workers<workers>`. + The ``--all`` modifier instructs the ``--stop`` command to stop all running services related to SQream DB + * - ``--list`` + - Shows a list of all active master nodes and their workers + * - ``-p <port>`` + - Sets the port for the load balancer. Defaults to ``3108`` + * - ``-m <port>`` + - Sets the port for the metadata server. Defaults to ``3105`` + +Common usage +^^^^^^^^^^^^^^^ + +Start master node +******************** + +.. code-block:: console + + sqream-console> sqream master --start + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 3105,3108 + +Start master node on different ports +******************************************* + +.. code-block:: console + + sqream-console> sqream master --start -p 4105 -m 4108 + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 4105,4108 + +Listing active master nodes and workers +*************************************************** + +.. code-block:: console + + sqream-console> sqream master --list + container name: sqream_single_host_worker_1, container id: de9b8aff0a9c + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038 + +Stopping all SQream DB workers and master +********************************************* + +.. code-block:: console + + sqream-console> sqream master --stop --all + shutting down 2 sqream services ... + sqream_editor stopped + sqream_single_host_worker_1 stopped + sqream_single_host_worker_0 stopped + sqream_single_host_master stopped + +.. _workers: + +Workers +------------ + +Workers are :ref:`SQream DB daemons<sqreamd_cli_reference>`, that connect to the master node. + +Syntax +^^^^^^^^^^ + +.. code-block:: console + + sqream worker <flags> + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag/command + - Description + * - ``--start [ options [ ...] ]`` + - Starts worker nodes. See options table below. + * - ``--stop [ <worker name> | --all ]`` + - + Stops the specified worker name. + The ``--all`` modifier instructs the ``--stop`` command to stop all running workers. + +Start options are specified consecutively, separated by spaces. + +.. list-table:: Start options + :widths: auto + :header-rows: 1 + + * - Option + - Description + * - ``<n>`` + - Specifies the number of workers to start + * - ``-j <config file> [ ...]`` + - Specifies configuration files to apply to each worker. When launching multiple workers, specify one file per worker, separated by spaces. + * - ``-p <port> [ ...]`` + - Sets the ports to listen on. When launching multiple workers, specify one port per worker, separated by spaces. Defaults to 5000 - 5000+n. + * - ``-g <gpu id> [ ...]`` + - Sets the GPU ordinal to assign to each worker. When launching multiple workers, specify one GPU ordinal per worker, separated by spaces. Defaults to automatic allocation. + * - ``-m <spool memory>`` + - Sets the spool memory per node in gigabytes. + * - ``--master-host`` + - Sets the hostname for the master node. Defaults to ``localhost``. + * - ``--master-port`` + - Sets the port for the master node. Defaults to ``3105``. + * - ``--stand-alone`` + - For testing only: Starts a worker without connecting to the master node. + +Common usage +^^^^^^^^^^^^^^^ + +Start 2 workers +******************** + +After starting the master node, start workers: + +.. code-block:: console + + sqream-console> sqream worker --start 2 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 + +Stop a single worker +******************************************* + +To stop a single worker, find its name first: + +.. code-block:: console + + sqream-console> sqream master --list + container name: sqream_single_host_worker_1, container id: de9b8aff0a9c + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038 + +Then, issue a stop command: + +.. code-block:: console + + sqream-console> sqream worker --stop sqream_single_host_worker_1 + stopped sqream_single_host_worker_1 + +Start workers with a different spool size +********************************************** + +If no spool size is specified, the RAM is equally distributed among workers. +Sometimes a system engineer may wish to specify the spool size manually. + +This example starts two workers, with a spool size of 50GB per node: + +.. code-block:: console + + sqream-console> sqream worker --start 2 -m 50 + +Starting multiple workers on non-dedicated GPUs +**************************************************** + +By default, SQream DB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. + +This example starts 4 workers on 2 GPUs, with 50GB spool each: + +.. code-block:: console + + sqream-console> sqream worker --start 2 -g 0 -m 50 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 0 + sqream-console> sqream worker --start 2 -g 1 -m 50 + started sqream_single_host_worker_2 on port 5002, allocated gpu: 1 + started sqream_single_host_worker_3 on port 5003, allocated gpu: 1 + +Overriding default configuration files +******************************************* + +It is possible to override default configuration settings by listing a configuration file for every worker. + +This example starts 2 workers on the same GPU, with modified configuration files: + +.. code-block:: console + + sqream-console> sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json + +Client +------------ + +The client operation runs :ref:`sqream sql<sqream_sql_cli_reference>` in interactive mode. + +.. note:: The dockerized client is useful for testing and experimentation. It is not the recommended method for executing analytic queries. See more about connecting a :ref:`third party tool to SQream DB <third_party_tools>` for data analysis. + +Syntax +^^^^^^^^^^ + +.. code-block:: console + + sqream client <flags> + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag/command + - Description + * - ``--master`` + - Connects to the master node via the load balancer + * - ``--worker`` + - Connects to a worker directly + * - ``--host <hostname>`` + - Specifies the hostname to connect to. Defaults to ``localhost``. + * - ``--port <port>``, ``-p <port>`` + - Specifies the port to connect to. Defaults to ``3108`` when used with ``-master``. + * - ``--user <username>``, ``-u <username>`` + - Specifies the role's username to use + * - ``--password <password>``, ``-w <password>`` + - Specifies the password to use for the role + * - ``--database <database>``, ``-d <database>`` + - Specifies the database name for the connection. Defaults to ``master``. + +Common usage +^^^^^^^^^^^^^^^ + +Start a client +******************** + +Connect to default ``master`` database through the load balancer: + +.. code-block:: console + + sqream-console> sqream client --master -u sqream -w sqream + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +Start a client to a specific worker +************************************** + +Connect to database ``raviga`` directly to a worker on port 5000: + +.. code-block:: console + + sqream-console> sqream client --worker -u sqream -w sqream -p 5000 -d raviga + Interactive client mode + To quit, use ^D or \q. + + raviga=> _ + +Start master node on different ports +******************************************* + +.. code-block:: console + + sqream-console> sqream master --start -p 4105 -m 4108 + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 4105,4108 + +Listing active master nodes and worker nodes +*************************************************** + +.. code-block:: console + + sqream-console> sqream master --list + container name: sqream_single_host_worker_1, container id: de9b8aff0a9c + container name: sqream_single_host_worker_0, container id: c919e8fb78c8 + container name: sqream_single_host_master, container id: ea7eef80e038 + +.. _start_editor: + +Editor +------------ + +The editor operation runs the web UI for the :ref:`SQream DB Statement Editor<statement_editor>`. + +The editor can be used to run queries from a browser. + +Syntax +^^^^^^^^^^ + +.. code-block:: console + + sqream editor <flags> + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag/command + - Description + * - ``--start`` + - Start the statement editor + * - ``--stop`` + - Shut down the statement editor + * - ``--port <port>``, ``-p <port>`` + - Specify a different port for the editor. Defaults to ``3000``. + +Common usage +^^^^^^^^^^^^^^^ + +Start the editor UI +********************** + +.. code-block:: console + + sqream-console> sqream editor --start + access sqream statement editor through Chrome http://192.168.0.100:3000 + +Stop the editor UI +********************** + +.. code-block:: console + + sqream-console> sqream editor --stop + sqream_editor stopped + + +Using the console to start SQream DB +============================================ + +The console is used to start and stop SQream DB components in a dockerized environment. + +Starting a SQream DB cluster for the first time +------------------------------------------------------- + +To start a SQream DB cluster, start the master node, followed by workers. + +The example below starts 2 workers, running on 2 dedicated GPUs. + +.. code-block:: console + + sqream-console> sqream master --start + starting master server in single_host mode ... + sqream_single_host_master is up and listening on ports: 3105,3108 + + sqream-console> sqream worker --start 2 + started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 + started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 + + sqream-console> sqream editor --start + access sqream statement editor through Chrome http://192.168.0.100:3000 + +SQream DB is now listening on port 3108 for any incoming statements. + +A user can also access the web editor (running on port ``3000`` on the SQream DB machine) to connect and run queries. \ No newline at end of file diff --git a/reference/cli/sqream_console.rst b/reference/cli/sqream_console.rst index 10c4e05bf..ac46fdbb0 100644 --- a/reference/cli/sqream_console.rst +++ b/reference/cli/sqream_console.rst @@ -1,7 +1,7 @@ .. _sqream_console_cli_reference: ********************************* -sqream-console +sqream Linux console ********************************* ``sqream-console`` is an interactive shell designed to help manage a dockerized SQream DB installation. From 7a1c2dd6a630d5e30baf229fe11692b0732e3c78 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Feb 2024 08:30:28 +0200 Subject: [PATCH 1168/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index e7f0acde3..66c46eb51 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -14,6 +14,7 @@ Visit `SQreamDB's support portal <https://sqream.atlassian.net/servicedesk/custo .. contents:: :local: + :depth: 2 Cluster Architectures @@ -21,7 +22,7 @@ Cluster Architectures SQreamDB recommends rackmount servers by server manufacturers Dell, Lenovo, HP, Cisco, Supermicro, IBM, and others. -A typical SQreamDB cluster includes one or more nodes, consisting of +A typical SQreamDB cluster includes one or more nodes, consisting of: * Two-socket enterprise processors, such as Intel® Xeon® Gold processors or the IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. @@ -33,7 +34,7 @@ A typical SQreamDB cluster includes one or more nodes, consisting of * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. -Single-Node Cluster Example +Single-Node Cluster --------------------------- A single-node SQreamDB cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). @@ -71,7 +72,7 @@ In this system configuration, SQreamDB can store about 100TB of raw data (assumi If a NAS is used, the 10x SSD drives can be omitted, but SQreamDB recommends 2TB of local spool space on SSD or NVMe drives. -Multi-Node Cluster Examples +Multi-Node Cluster --------------------------- Multi-node clusters can handle any number of concurrent users. A typical SQreamDB cluster relies on a minimum of two GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. @@ -138,7 +139,7 @@ The following table shows SQreamDB's recommended metadata server specifications: .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. -SQreamDB Studio Server Example +SQreamDB Studio Server ------------------------------ The following table shows SQreamDB's recommended Studio server specifications: From 12290d3a9196058de91c6cb9045358d874d84377 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:57:54 +0200 Subject: [PATCH 1169/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 66c46eb51..e3a730708 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -35,7 +35,7 @@ A typical SQreamDB cluster includes one or more nodes, consisting of: * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. Single-Node Cluster ---------------------------- +------------------- A single-node SQreamDB cluster can handle between 1 and 8 concurrent users, with up to 1PB of data storage (when connected via NAS). @@ -73,19 +73,12 @@ In this system configuration, SQreamDB can store about 100TB of raw data (assumi If a NAS is used, the 10x SSD drives can be omitted, but SQreamDB recommends 2TB of local spool space on SSD or NVMe drives. Multi-Node Cluster ---------------------------- +------------------ Multi-node clusters can handle any number of concurrent users. A typical SQreamDB cluster relies on a minimum of two GPU-enabled servers and shared storage connected over a network fabric, such as InfiniBand EDR, 40GbE, or 100GbE. The **Multi-Node Cluster Examples** section describes the following specifications: -.. contents:: - :local: - :depth: 1 - -Hardware Specifications -~~~~~~~~~~~~~~~~~~~~~~~ - The following table shows SQreamDB's recommended hardware specifications: .. list-table:: @@ -113,8 +106,8 @@ The following table shows SQreamDB's recommended hardware specifications: * - Operating System - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux -Metadata Specifications -~~~~~~~~~~~~~~~~~~~~~~~ +Metadata Server +--------------- The following table shows SQreamDB's recommended metadata server specifications: @@ -124,6 +117,8 @@ The following table shows SQreamDB's recommended metadata server specifications: * - Component - Type + * - Server + - * - Processors - 2x Intel Xeon Gold 6342 2.8 Ghz 24C processors or similar * - RAM @@ -140,7 +135,7 @@ The following table shows SQreamDB's recommended metadata server specifications: .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. SQreamDB Studio Server ------------------------------- +---------------------- The following table shows SQreamDB's recommended Studio server specifications: From 71506a44929626d88c7cd1da5ebeeadd7a1c360c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:00:08 +0200 Subject: [PATCH 1170/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index e3a730708..8ced7b0ef 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -97,6 +97,10 @@ The following table shows SQreamDB's recommended hardware specifications: - * 2x 960GB SSD 2.5in hot plug for OS, RAID1 * 2x 2TB SSD or NVMe, for temporary spooling, RAID0 + * - Network Card (Storage) + - 2x Mellanox ConnectX-6 Single Port HDR VPI InfiniBand Adapter cards at 100GbE or similar. + * - Network Card (Client) + - 2x 1 GbE cards or similar * - External Storage - * Mellanox Connectx5/6 100G NVIDIA Network Card (if applicable) or other high-speed network card minimum 40G compatible with customer’s infrastructure From d2e5602c7a00c2edc1b7e11f36e354baed08aa26 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Feb 2024 08:46:59 +0200 Subject: [PATCH 1171/1892] Update repeat.rst --- .../scalar_functions/string/repeat.rst | 142 +++++++----------- 1 file changed, 55 insertions(+), 87 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/repeat.rst b/reference/sql/sql_functions/scalar_functions/string/repeat.rst index 4e202b5b2..920aa55db 100644 --- a/reference/sql/sql_functions/scalar_functions/string/repeat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/repeat.rst @@ -1,20 +1,17 @@ .. _repeat: -************************** +****** REPEAT -************************** - -Repeats a string as many times as specified. - -.. warning:: This function works ONLY with ``TEXT`` data type. +****** +The ``REPEAT`` function repeats an input string expression as many times as specified. Syntax ========== -.. code-block:: postgres +.. code-block:: sql - REPEAT(expr, character_count) + REPEAT('expr', n) Arguments ============ @@ -25,105 +22,76 @@ Arguments * - Parameter - Description - * - ``expr`` - - String expression - * - ``character_count`` + * - ``'expr'`` + - A ``TEXT`` expression + * - ``n`` + - An ``INTEGER`` expression specifying the number of repetitions for the string expression -Returns -============ - -Returns the same type as the argument supplied. - -Notes -======= +Return +====== -* When ``character_count`` <= 0, and empty string is returned. +* Returns a ``TEXT`` string. +* When ``n`` <= 0, and empty string is returned. Examples -=========== +======== -For these examples, consider the following table and contents: +For these example, consider the following table: -.. code-block:: postgres +.. code-block:: sql - CREATE TABLE customer(customername TEXT)); + CREATE TABLE customer(customername TEXT); - INSERT INTO customer VALUES - ('Alfreds Futterkiste'), - ('Ana Trujillo Emparedados y helados'), - ('Antonio Moreno Taquería'), - ('Around the Horn'); + INSERT INTO customer VALUES + ('Alfreds Futterkiste'), + ('Ana Trujillo Emparedados y helados'), + ('Antonio Moreno Taquería'), + ('Around the Horn'); -Repeat the text in customername 2 times: ------------------------------------------ +Repeating Content of a Table Column +----------------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT REPEAT(customername, 2) FROM customers; + SELECT REPEAT(customername, 2) FROM customer; - repeat - -------------------------- - Alfreds FutterkisteAlfreds Futterkiste - Ana Trujillo Emparedados y heladosAna Trujillo Emparedados y helados - Antonio Moreno TaqueríaAntonio Moreno Taquería - Around the HornAround the Horn + repeat + -------------------------------------------------------------------- + Alfreds FutterkisteAlfreds Futterkiste + Ana Trujillo Emparedados y heladosAna Trujillo Emparedados y helados + Antonio Moreno TaqueríaAntonio Moreno Taquería + Around the HornAround the Horn +Repeating a String +------------------ -Repeat the string 0 times: ----------------------------- +.. code-block:: sql -.. code-block:: psql + SELECT REPEAT('abc', 3); + + repeat + --------- + abcabcabc - t=> SELECT REPEAT('abc', 0); - - repeat - ----------------------------------------------- - '' -Repeat the string 1 times: ----------------------------- +Repeating a String 0 Times +-------------------------- -.. code-block:: psql +.. code-block:: sql - t=> SELECT REPEAT('abc', 1); - - repeat - ----------------------------------------------- - 'abc' - + SELECT REPEAT('abc', 0); + + repeat + ------ -Repeat the string 3 times: ----------------------------- +Repeating an Empty String +------------------------- -.. code-block:: psql - - t=> SELECT REPEAT('a', 3); - - repeat - ----------------------------------------------- - 'aaa' +.. code-block:: sql - -Repeat an empty string 10 times: ----------------------------- - -.. code-block:: psql - - t=> SELECT REPEAT('', 10); - - repeat - ----------------------------------------------- - '' - - -Repeat a string -3 times: ----------------------------- - -.. code-block:: psql - - t=> SELECT REPEAT('abc', -3); - - repeat - ----------------------------------------------- - '' \ No newline at end of file + SELECT REPEAT('', 3); + + repeat + ------ + From 8f142c31364c7ca4be83e758db3e727a3c580866 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:17:36 +0200 Subject: [PATCH 1172/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index b7df158de..cb1e88f4b 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From cf26a1cc484375d5a682e1352a1e6cd2e04d3518 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 18 Feb 2024 14:26:00 +0200 Subject: [PATCH 1173/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index cb1e88f4b..9b86d3d59 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role * - ``password`` - The password of the role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. To load the entire data of a source table using the CLI, run the following command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. To customize the data load, use the following parameters within a CLI or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100.000`` - - The number of records to be read at once from the source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle. See :ref:`Using the Type Parameter<using_the_type_parameter>` * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements .. _using_the_type_parameter: Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continues to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 6313a085644ad9f2690de3591ddf0a4fe701c9f2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:02:39 +0200 Subject: [PATCH 1174/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index cb1e88f4b..9edea37fa 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. Getting the SQLoader Configuration and JAR Files ================================================ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: SQLoader Files :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Connection String ================= The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Loading Data into SQreamDB Tables ================================= 1. Run the ``sqloader.jar`` file using the following CLI command: .. code-block:: console java -jar sqloader.jar 2. You may load the entire data of a source table using the following CLI command: .. code-block:: console java -jar sqloader.jar -table source_table_name 3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Using the ``type`` Parameter ------------------------------ Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto :header-rows: 1 * - Loading Type - Parameter Option - Description * - Full Table - ``full`` - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); Data Type Mapping ================= .. contents:: :local: :depth: 1 Automatic Mapping ------------------ The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manually Adjusting Mapping ---------------------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 43149c31bddc17400f8b4f18878fd5506be857fc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:09:53 +0200 Subject: [PATCH 1175/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 9edea37fa..eea5b2a36 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 7350c3b5af562198b5e5023e2dbdfab54308eb4c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 10:14:58 +0200 Subject: [PATCH 1176/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index eea5b2a36..de9a491c4 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file: .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From ad0e55400e899854ea7e124d44b5d219ef3a5db1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 11:03:42 +0200 Subject: [PATCH 1177/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index de9a491c4..1fcbfe3cf 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing any of the following *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements --------------------------------- Creating Summary Tables ======================== Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- This summary table uses Oracle syntax. .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Creating a Change Data Capture Table -------------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- Data Type and Mapping ===================== SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ----------------- Oracle ^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql ^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA ^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping -------------- You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method ^^^^^^^^^^^^^^^^^ To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file From 99860b03b8a4dbac143d48b74f3c04f9bcd8322c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:13:06 +0200 Subject: [PATCH 1178/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 1fcbfe3cf..3089df28a 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database. * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table source_table_name -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table source_table_name -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 \ No newline at end of file From 0f02ea8d522c86e7c1edb4364ce7de5ef94f67c5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 15:20:12 +0200 Subject: [PATCH 1179/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 3089df28a..3e4ced904 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 \ No newline at end of file From 49fbdc458554e329db6bb92573463ffca5d430fc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:19:34 +0200 Subject: [PATCH 1180/1892] 4.6 RN --- releases/4.6.rst | 2 +- releases/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index bfb1d2999..f3f7aa8b2 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -4,7 +4,7 @@ Release Notes 4.6 ***************** -The 4.6 release notes were released on January XXX, 2023 +The 4.6 release notes were released on February 19, 2024 .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index 8bd5f678b..f99fa2838 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.6 - February xxxx, 2024<4.6>` +:ref:`Version 4.6 - February 19, 2024<4.6>` * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. * Safely cast data types with the new :ref:`IsCastable<is_castable>` function. From 58d435e9d84b4a6537764e1773b9ddb9332b7a5c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:21:52 +0200 Subject: [PATCH 1181/1892] Update 4.6.rst --- releases/4.6.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index f3f7aa8b2..fbfa4e17e 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -21,14 +21,14 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 51 | +| Storage version | 50 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | | | * Pysqream 5.0.0 | -| | * Spark | +| | * Spark 5.0.0 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 85e9f9525b3c7ed2f1ff58b5848f680cf434ec9c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Feb 2024 16:58:31 +0200 Subject: [PATCH 1182/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index fbfa4e17e..47ed1df62 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -21,7 +21,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 50 | +| Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.0.0 | | | * ODBC 4.4.4 | From 07175c4218e9add6200558ec7624f51e716b8591 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Feb 2024 08:18:27 +0200 Subject: [PATCH 1183/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 8ced7b0ef..d65eff6b8 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -64,7 +64,7 @@ An average single-node cluster can be a rackmount server or workstation, contain NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v8.8 or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -108,7 +108,7 @@ The following table shows SQreamDB's recommended hardware specifications: * - GPU - NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v8.8 or Amazon Linux Metadata Server --------------- @@ -134,7 +134,7 @@ The following table shows SQreamDB's recommended metadata server specifications: * - Network Card (Client) - 2x 1 GbE cards or similar * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 or Amazon Linux + - Red Hat Enterprise Linux v8.8 or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. From fda64754cce1c458bfd7f72e2c257cd2e547fcd5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Feb 2024 08:23:48 +0200 Subject: [PATCH 1184/1892] Remove 2021 --- releases/2020.1.rst | 189 -------------------------------- releases/2020.2.rst | 116 -------------------- releases/2020.3.1.rst | 78 ------------- releases/2020.3.2.1.rst | 36 ------ releases/2020.3.2.rst | 30 ----- releases/2020.3.rst | 111 ------------------- releases/2020.3_index.rst | 20 ---- releases/2021.1.2.rst | 69 ------------ releases/2021.1.rst | 224 -------------------------------------- releases/2021.1_index.rst | 18 --- 10 files changed, 891 deletions(-) delete mode 100644 releases/2020.1.rst delete mode 100644 releases/2020.2.rst delete mode 100644 releases/2020.3.1.rst delete mode 100644 releases/2020.3.2.1.rst delete mode 100644 releases/2020.3.2.rst delete mode 100644 releases/2020.3.rst delete mode 100644 releases/2020.3_index.rst delete mode 100644 releases/2021.1.2.rst delete mode 100644 releases/2021.1.rst delete mode 100644 releases/2021.1_index.rst diff --git a/releases/2020.1.rst b/releases/2020.1.rst deleted file mode 100644 index ddc5702d4..000000000 --- a/releases/2020.1.rst +++ /dev/null @@ -1,189 +0,0 @@ -.. _2020.1: - -******************** -Release Notes 2020.1 -******************** - -SQream DB v2020.1 contains lots of new features, improved performance, and bug fixes. - -This is the first release of 2020, with a strong focus on integration into existing environments. The release includes connectivity to Hadoop and other legacy data warehouse ecosystems. We’re also bringing lots of new capabilities to our analytics engine, to empower data users to analyze more data with less friction. - -The latest release vastly improves reliability and performance, and makes getting more data into SQream DB easier than ever. - -The core of SQream DB v2020.1 contains new integration features, more analytics capabilities, and better drivers and connectors. - - -New features -============ - -Integration ------------ - -* Load files directly from :ref:`S3 buckets<inserting_data>`. Customers with columnar data in S3 data lakes can now access the data directly. All that is needed is to simply point an external table to an S3 bucket with Parquet, ORC, or CSV objects. This feature is available on all deployments of SQream DB – in the cloud and on-prem. - -* Load files directly from :ref:`HDFS<inserting_data>`. SQream DB now comes with built-in, native HDFS support for directly loading data from Hadoop-based data lakes. Our focus on helping Hadoop customers do more with their data led us to develop this feature, which works out of the box. As a result, SQream DB can now not only read but also write data, and intermediate results back to HDFS for HIVE and other data consumers. SQream DB now fits seamlessly into a Hadoop data pipeline. - - -* Import :ref:`ORC files<orc>`, through :ref:`external_tables`. ORC files join Parquet as files that can be natively accessed and inserted into SQream DB tables. - -* :ref:`Python driver (pysqream)<pysqream>` is now DB-API v2.0 compliant. Customers can write high-performance Python applications that make full use of SQream DB - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. - -* Certified :ref:`Tableau JDBC connector (taco)<connect_to_tableau>`, now also :ref:`supported on MacOS<tableau_manual_installation>`. Users are encouraged to install the new JDBC connector. - -* - All logs are now unified into one log, which can be analyzed with SQream DB directly. - See :ref:`logging` for more information. - - -SQL support ------------ - -* - Added frames and frame exclusions to :ref:`window_functions`. This is available for preview, with more features coming in the next version. - - The new frames and frame exclusionsfeature adds complex analytics capabilities to the already powerful window functions. - -* - New datatype - ``TEXT``, which replaces ``NVARCHAR`` directly with UTF-8 support and improved performance. - - Unlike ``VARCHAR``, the new ``TEXT`` data type has no restrictions on size, and carries no performance overhead as the text sizes grow. - -* ``TEXT`` join keys are now supported - -* Added lots of new :ref:`aggregate functions<aggregate_functions>`, including ``VAR_SAMP``, ``VAR_POP``, ``COVAR_POP``, etc. - - -Improvements and fixes -====================== - -SQream DB v2020.1 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. Existing SQream DB users can expect to see a general speedup of around 10% on most statements and queries! - -* 207 bug fixes, including: - - - Improved performance of both inner and outer joins - - Fixed wrong results on STDDEV (0 instead of ``NULL``) - - Fixed wrong results on nested Parquet files - - Fixed failing cast from ``VARCHAR`` to ``FLOAT`` - - Fix ``INSERT`` that would fail on nullable values and non-nullable columns in some scenarios - - Improved memory consumption, so ``Out of GPU memory`` errors should not occur anymore - - Reduced long compilation times for very complex queries - - Improved ODBC reliability - - Fixed situation where some logs would clip very long queries - - Improved error messages when dropping a schema with many objects - - Fixed situation where Spotfire would not show table names - - Fixed situation where some queries with UTF-8 literals wouldn't run through Tableau over ODBC - - Significantly improved cache freeing and memory allocation - - Fixed situation in which a malformed time (``24:00:00``) would get incorrectly inserted from a CSV - - Fixed race condition in which loading thousands of small files from HDFScaused a memory leak - -* The :ref:`saved query<saved_queries>` feature can now be used with :ref:`insert` statements - -* Faster "Deferred gather" algorithm for joins with text keys - -* Faster filtering when using :ref:`datepart` - -* Faster metadata tagging during load - -* Fixed situation where some queries would get compiled twice - -* :ref:`saved_queries` now support :ref:`insert` statements - -* ``highCardinalityColumns`` can be configured to tell the system about :ref:`high selectivity<high_selectivity>` columns - -* :ref:`sqream sql<sqream_sql_cli_reference>` starts up faster, can run on any Linux machine - -* Additional CSV date formats (date parsers) added for compatibility - -Behaviour changes -================= - -* ``ClientCmd`` is now known as :ref:`sqream sql<sqream_sql_cli_reference>` - -* ``NVARCHAR`` columns are now known as ``TEXT`` internally - -* - Deprecated the ability to run ``SELECT`` and ``COPY`` at the same time on the same worker. This change is designed to protect against ``out of GPU memory`` issues. - This comes with a configuration change, namely the ``limitQueryMemoryGB`` setting. See the operations section for more information. - -* All logs are now unified into one log. See :ref:`logging` for more information - -* Compression changes: - - - The latest version of SQream DB could select a different compression scheme if data is reloaded, compared to previous versions of SQream DB. This internal change improves performance. - - - With ``LZ4`` compression, the maximum chunk size is limited to 2.1GB. If the chunk size is bigger, another compression may be selected - primarily ``SNAPPY``. - -* The following configuration flags have been deprecated: - - - ``addStatementRechunkerAfterGpuToHost`` - - ``increasedChunkSizeFactor`` - - ``gpuReduceMergeOutputFactor`` - - ``fullSortInputMemFactor`` - - ``reduceInputMemFactor`` - - ``distinctInputMemFactor`` - - ``useAutoMemFactors`` - - ``autoMemFactorsVramFactor`` - - ``catchNotEnoughVram`` - - ``useNetworkRechunker`` - - ``useMemFactorInJoinOutput`` - -Operations -========== - -* The client-server protocol has been updated to support faster data flow, and more reliable memory allocations on the client side. End users are required to use only the latest :ref:`sqream sql<sqream_sql_cli_reference>`, :ref:`java_jdbc`, and :ref:`odbc` drivers delivered with this version. See the :ref:`client driver download page<client_drivers>` for the latest drivers and connectors. - -* When upgrading from a previous version of SQream DB (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` - -* - A change in memory allocation behaviour in this version sees the introduction of a new setting, ``limitQueryMemoryGB``. This is an addition to the previous ``spoolMemoryGB`` setting. - - A good rule-of-thumb is to allow 5% system memory for other processes. The spool memory allocation should be around 90% of the total memory allocated. - - - ``limitQueryMemoryGB`` defines how much total system memory is used by the worker. The recommended setting is (``total host memory`` - 5%) / ``sqreamd workers on host``. - - - ``spoolMemoryGB`` defines how much memory is set aside for spooling, out of the total system memory allocated in ``limitQueryMemoryGB``. The recommended setting is 90% of the ``limitQueryMemoryGB``. - - This setting must be set lower than the ``limitQueryMemoryGB`` setting. - - For example, for a machine with 512GB of RAM and 4 workers, the recommended settings are: - - - ``limitQueryMemoryGB`` - ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. - - - ``spoolMemoryGB`` - ``⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108`` - - Example settings per-worker, for 512GB of RAM and 4 workers: - - .. code-block:: none - - "runtimeGlobalFlags": { - "limitQueryMemoryGB" : 121, - "spoolMemoryGB" : 108 - - - - -Known Issues & Limitations -========================== - -* An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. - -* ``TEXT`` columns cannot be used in a window functions' partition - -* Parsing errors are sometimes hard to read - the location points to the wrong part of the statement - -* LZ4 compression may not be applied correctly on very large ``VARCHAR`` columns, which decreases performance - -* Using ``SUM`` on very large numbers in window functions can error (``overflow``) when not used with an ``ORDER BY`` clause - -* Slight performance decrease with :ref:`dateadd` in this version (<4%) - -* Operations on Snappy-compressed ORC files are slower than their Parquet equivalents. - - -Upgrading to v2020.1 -==================== - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream. - diff --git a/releases/2020.2.rst b/releases/2020.2.rst deleted file mode 100644 index c512ecb32..000000000 --- a/releases/2020.2.rst +++ /dev/null @@ -1,116 +0,0 @@ -.. _2020.2: - -******************** -Release Notes 2020.2 -******************** - -SQream v2020.2 contains some new features, improved performance, and bug fixes. - -This version has new window ranking function and a new editor UI to empower data users to analyze more data with less friction. - -As always, the latest release improves reliability and performance, and makes getting more data into SQream easier than ever. - - -New Features -============ - -UI --- - -* New :ref:`sqream_studio` replaces the previous Statement Editor. - -Integration ------------ - -* Our :ref:`Python driver (pysqream)<pysqream>` now has an SQLAlchemy dialect. Customers can write high-performance Python applications that make full use of SQream - connect, query, delete, and insert data. Data scientists can use pysqream with Pandas, Numpy, and AI/ML frameworks like TensorFlow for direct queries of huge datasets. - -SQL Support ------------ - -* Added :ref:`lag`/:ref:`lead` ranking functions to our :ref:`window_functions` support. We will have more features coming in the next version. - -* - New syntax preview for :ref:`external_tables`. Foreign tables replace external tables, with improved functionality. - - You can keep using the existing foreign table syntax for now, but it may be deprecated in the future. - - .. code-block:: postgres - - CREATE FOREIGN TABLE orc_example - ( - name varchar(40), - Age tinyint, - Salary float - ) - WRAPPER orc_fdw - OPTIONS - ( LOCATION = 'hdfs://hadoop-nn.piedpiper.com:8020/demo-data/example.orc' ); - - -Improvements and Fixes -====================== - -SQream v2020.2 includes hundreds of small new features and tunable parameters that improve performance, reliability, and stability. - -* ~100 bug fixes, including: - - - Fixed CSV handling for DOS newlines - - Fixed "out of bounds" message when several layers of nested ``substring``, ``cast``, and ``to_hex`` were used to produce one value. - - Fixed "Illegal memory access" that would occur in extremely rare situations on all-text tables - - Window functions can now be used with all aggregations - - Fixed situation where a single worker may use more than one GPU that isn't allocated to it - - Text columns can now be added to existing tables with :ref:`alter_table` - -* New :ref:`data_clustering` syntax that can improve query performance for unsorted data - - -Operations -========== - -* When upgrading from a previous version of SQream (for example, v2019.2), the storage version must be upgraded using the :ref:`upgrade_storage_cli_reference` utility: ``./bin/upgrade_storage /path/to/storage/sqreamdb/`` - -* - A change in memory allocation behaviour in this version sees the introduction of a new setting, ``limitQueryMemoryGB``. This is an addition to the previous ``spoolMemoryGB`` setting. - - A good rule-of-thumb is to allow 5% system memory for other processes. The spool memory allocation should be around 90% of the total memory allocated. - - - ``limitQueryMemoryGB`` defines how much total system memory is used by the worker. The recommended setting is (``total host memory`` - 5%) / ``sqreamd workers on host``. - - - ``spoolMemoryGB`` defines how much memory is set aside for spooling, out of the total system memory allocated in ``limitQueryMemoryGB``. The recommended setting is 90% of the ``limitQueryMemoryGB``. - - This setting must be set lower than the ``limitQueryMemoryGB`` setting. - - For example, for a machine with 512GB of RAM and 4 workers, the recommended settings are: - - - ``limitQueryMemoryGB`` - ``⌊(512 * 0.95 / 4)⌋ → ~ 486 / 4 → 121``. - - - ``spoolMemoryGB`` - ``⌊( 0.9 * limitQueryMemoryGB )⌋ → ⌊( 0.9 * 121 )⌋ → 108`` - - Example settings per-worker, for 512GB of RAM and 4 workers: - - .. code-block:: none - - "runtimeFlags": { - "limitQueryMemoryGB" : 121, - "spoolMemoryGB" : 108 - - - - -Known Issues and Limitations -============================ - -* An invalid formatted CSV can cause an ``insufficient memory`` error on a :ref:`copy_from` statement if a quote isn't closed and the file is much larger than system memory. - -* Multiple ``COUNT( distinct ... )`` operations within the same query are limited to "developer mode" due to an instability that was identified. If you rely on this feature, contact your SQream account manager to enable this feature. - -* ``TEXT`` columns can't be used with an outer join together with an inequality check (``!= , <>``) - - -Upgrading to Version 2020.2 -============================ - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream. - diff --git a/releases/2020.3.1.rst b/releases/2020.3.1.rst deleted file mode 100644 index cbd0ee613..000000000 --- a/releases/2020.3.1.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _2020.3.1: - -********************** -Release Notes 2020.3.1 -********************** - -The 2020.3.1 release notes were released on October 8, 2020 and describe the following: - -.. contents:: - :local: - :depth: 1 - - - -New Features ------------- - -The following list describes the new features: - - -* TEXT data type: - * Full support for ``MIN`` and ``MAX`` aggregate functions on ``TEXT`` columns in ``GROUP BY`` queries. - * Support Text-type as window partition keys (e.g., select distinct name, max(id) over (partition by name) from ``textTable;``). - * Support Text-type fields in windows order by keys. - * Support join on ``TEXT`` columns (such as ``t1.x = t2.y`` where ``x`` and ``y`` are columns of type ``TEXT``). - * Complete the implementation of ``LIKE`` on ``TEXT`` columns (previously limited to prefix and suffix). - * Support for cast fromm ``TEXT`` to ``REAL/FLOAT``. - * New string function - ``REPEAT`` for repeating a string value for a specified number of times. - -* Support mapping ``DECIMAL ORC`` columns to SQream's floating-point types. - -* Support ``LIKE`` on non-literal patterns (such as columns and complex expressions). - -* Catch OS signals and save the signal along with the stack trace in the SQream debug log. - -* Support equijoin conditions on columns with different types (such as ``tinyint``, ``smallint``, ``int`` and ``bigint``). - -* ``DUMP_DATABASE_DDL`` now includes foreign tables in the output. - -* New utility function - ``TRUNCATE_IF_EXISTS``. - - -Performance Enhancements ------------------------- - -The following list describes the performance enhancements: - - -* Introduced the "MetaData on Demand" feature which results in signicant proformance improvements. - -* Implemented regex functions (``RLIKE``, ``REGEXP_COUNT``, ``REGEXP_INSTR``, ``REGEXP_SUBSTR``, ``PATINDEX``) for ``TEXT`` columns on GPU. - - -Resolved Issues ---------------- - -The following list describes the resolved issues: - - -* Multiple distinct aggregates no longer need to be used with developerMode flag. -* In some scenarios, the ``statement_id`` and ``connection_id values`` are incorrectly recorded as ``-1`` in the log. -* ``NOT RLIKE`` is not supported for ``TEXT`` in the compiler. -* Casting from ``TEXT`` to ``date/datetime`` returns an error when the ``TEXT`` column contains ``NULL``. - - -Known Issues and Limitations ----------------------------- - -No known issues and limitations. - - -Upgrading to v2020.3.1 ----------------------- - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream. - diff --git a/releases/2020.3.2.1.rst b/releases/2020.3.2.1.rst deleted file mode 100644 index 8a62ac0a3..000000000 --- a/releases/2020.3.2.1.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. _2020.3.2.1: - -************************ -Release Notes 2020.3.2.1 -************************ - -The 2020.3.2.1 release notes were released on October 8, 2020 and describe the following: - -.. contents:: - :local: - :depth: 1 - - -Overview --------- - -SQream DB v2020.3.2.1 contains major performance improvements and some bug fixes. - -Performance Enhancements ------------------------- - -* Metadata on Demand optimization resulting in reduced latency and improved overall performance. - - -Known Issues and Limitations ----------------------------- - -* Multiple count distinct operations is enabled for all data types. - -Upgrading to v2020.3.2.1 ------------------------- - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream. - diff --git a/releases/2020.3.2.rst b/releases/2020.3.2.rst deleted file mode 100644 index d4e15e7fb..000000000 --- a/releases/2020.3.2.rst +++ /dev/null @@ -1,30 +0,0 @@ -.. _2020.3.2: - -********************** -What's new in 2020.3.2 -********************** - -SQream DB v2020.3.2 contains major performance improvements and some bug fixes. - -Performance Enhancements -======================== - -* Metadata on Demand optimization resulting in reduced latency and improved overall performance - - -Known Issues & Limitations -========================== - -* Bug with STDDEV_SAMP,STDDEV_POP and STDEV functions -* Window function query returns wrong results -* rank() in window function sometimes returns garbage -* Window function on null value could have bad result -* Window function lead() on varchar can have garbage results -* Performance degradation when using "groupby" or outer_join - -Upgrading to v2020.3.2 -====================== - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream DB. diff --git a/releases/2020.3.rst b/releases/2020.3.rst deleted file mode 100644 index ec3c96e96..000000000 --- a/releases/2020.3.rst +++ /dev/null @@ -1,111 +0,0 @@ -.. _2020.3: - -******************** -Release Notes 2020.3 -******************** - -The 2020.3 release notes were released on October 8, 2020 and describes the following: - -.. contents:: - :local: - :depth: 1 - - -Overview --------- - -SQream DB v2020.3 contains new features, performance enhancements, and resolved issues. - - -New Features ------------- - -The following list describes the new features: - - -* Parquet and ORC files can now be exported to local storage, S3, and HDFS with :ref:`copy_to` and foreign data wrappers. - -* New error tolerance features when loading data with foreign data wrappers. - -* ``TEXT`` is ramping up with new features (previously only available with VARCHARs): - - * `SUBSTRING <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/substring.html>`_ - * `LTRIM <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/substring.html>`_ - * `CHARINDEX <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/substring.html>`_ - * `REPLACE <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/substring.html>`_ - - * Binary operators - `CONCAT <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/concat.html>`_ , `REPLACE <https://docs.sqream.com/en/v2020.3/reference/sql/sql_functions/scalar_functions/string/like.html>`_ , etc. - - * Casts to and from ``TEXT`` - -* :ref:`sqream_studio` v5.1 - - * New log viewer helps you track and debug what's going on in SQream DB. - - * Dashboard now also available for non-k8s deployments. - - * The editor contains a new query concurrency tool for date and numeric ranges. - - - -Performance Enhancements ------------------------- - -The following list describes the performance enhancements: - - -* Error handling for CSV FDW. -* Enable logging errors - ORC, Parquet, CSV. -* Add limit and offset options to ``csv_fdw`` import. -* Enable logging errors to an external file when skipping CSV, Parquet, and ORC errors. -* Option to specify date format to the CSV FDW. -* Support all existing ``VARCHAR`` functions with ``TEXT`` on GPU. -* Support ``INSERT INTO`` + ``ORDER BY`` optimization for non-clustered tables. -* Performance improvements with I/O. - -Resolved Issues ---------------- - -The following list describes the resolved issues: - - -* Better error message when passing the max errors limit. This was fixed. -* ``showFullExceptionInfo`` is no longer restricted to Developer Mode. This was fixed. -* An ``StreamAggregateA`` reduction error occured when performing aggregation on a ``NULL`` column. This was fixed. -* Insert into query fails with ""Error at Sql phase during Stages ""rewriteSqlQuery"". This was fixed. -* Casting from ``VARCHAR`` to ``TEXT`` does not remove the spaces. This was fixed. -* An ``Internal Runtime Error t1.size() == t2.size()`` occurs when querying the ``sqream_catalog.delete_predicates``. This was fixed. -* ``spoolMemoryGB`` and ``limitQueryMemoryGB`` show incorrectly in the **runtime global** section of ``show_conf.`` This was fixed. -* Casting empty text to ``int`` causes illegal memory access. This was fixed. -* Copying from the ``TEXT`` field is 1.5x slower than the ``VARCHAR`` equivalent. This was fixed. -* ``TPCDS 10TB - Internal runtime error (std::bad_alloc: out of memory)`` occurs on 2020.1.0.2. This was fixed. -* An unequal join on non-existing ``TEXT`` caused a system crash. This was fixed. -* An ``Internal runtime time error`` occured when using ``TEXT (tpcds)``. This was fixed. -* Copying CSV with a quote in the middle of a field to a ``TEXT`` field does not produce the required error. This was fixed. -* Cannot monitor long network insert loads with SQream. This was fixed. -* Upper and like performance on ``TEXT``. This was fixed. -* Insert into from 4 instances would get stuck (hanging). This was fixed. -* An invalid formatted CSV would cause an insufficient memory error on a ``COPY FROM`` statement if a quote was not closed and the file was much larger than system memory. This was fixed. -* ``TEXT`` columns cannot be used with an outer join together with an inequality check (!= , <>). This was fixed. - -Known Issues And Limitations ----------------------------- - -The following list describes the known issues and limitations: - - -* Cast from ``TEXT`` to a ``DATE`` or ``DATETIME`` errors when the ``TEXT`` column contains ``NULL`` - -* Casting an empty ``TEXT`` field to an ``INT`` type returns ``0`` instead of erroring - -* Multiple ``COUNT( distinct ... )`` operations on the ``TEXT`` data type are currently unsupported - -* Multiple ``COUNT( distinct ... )`` operations within the same query are limited to "developer mode" due to an instability that was identified. If you rely on this feature, contact your SQream account manager to enable this feature. - - -Upgrading to v2020.3 --------------------- - -Versions are available for IBM POWER9, RedHat (CentOS) 7, Ubuntu 18.04, and other OSs via Docker. - -Contact your account manager to get the latest release of SQream. diff --git a/releases/2020.3_index.rst b/releases/2020.3_index.rst deleted file mode 100644 index e2066e8a6..000000000 --- a/releases/2020.3_index.rst +++ /dev/null @@ -1,20 +0,0 @@ -.. _2020.3_index: - -******************** -Release Notes 2020.3 -******************** - -The 2020.3 release notes describe the following releases: - -.. contents:: - :local: - :depth: 1 - -.. toctree:: - :maxdepth: 1 - :glob: - - 2020.3.2.1 - 2020.3.2 - 2020.3.1 - 2020.3 \ No newline at end of file diff --git a/releases/2021.1.2.rst b/releases/2021.1.2.rst deleted file mode 100644 index a8c279981..000000000 --- a/releases/2021.1.2.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. _2021.1.2: - -********************** -Release Notes 2021.1.2 -********************** - -The 2021.1.2 release notes were released on 8/9/2021 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - -The 2021.1.2 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Aliases Added to SUBSTRING Function and Length Argument -******************************************************* - -The following aliases have been added: - -* length - ``len`` -* substring - ``substr`` - -Data Type Aliases Added -************ -The following data type aliases have been added: - -* INTEGER - ``int`` -* DECIMAL - ``numeric`` -* DOUBLE PRECISION - ``double`` -* CHARACTER/CHAR - ``text`` -* NATIONAL CHARACTER/NATIONAL CHAR/NCHAR - ``text`` -* CHARACTER VARYING/CHAR VARYING - ``text`` -* NATIONAL CHARACTER VARYING/NATIONAL CHAR VARYING/NCHAR VARYING - ``text`` - -String Literals Containing ASCII Characters Interepreted as TEXT -**************************************************************** - -SQream now interprets all string literals, including those containing ASCII characters, as ``text``. - -For more information, see `String Types <https://docs.sqream.com/en/v2021.1.2/data_type_guides/sql_data_types_string.html>`_. - -Decimal Literals Interpreted as Numeric Columns -*********************************************** - -SQream now interprets literals containing decimal points as ``numeric`` instead of as ``double``. - -For more information, see `Data Types <https://docs.sqream.com/en/v2021.1.2/data_type_guides/index.html>`_. - -Roles Area Added to Studio Version 5.4.3 -**************************************** - -The **Roles** area has been added to `Studio version 5.4.3 <https://docs.sqream.com/en/v2021.1.2/sqream_studio_5.4.3/creating_assigning_and_managing_roles_and_permissions.html>`_. From the Roles area users can create and assign roles and manage user permissions. - -Resolved Issues ---------------- - -The following list describes the resolved issues: - -* In Parquet files, ``float`` columns could not be mapped to SQream ``double`` columns. This was fixed. -* The ``REPLACE`` function only supported constant values as arguments. This was fixed. -* The ``LIKE`` function did not check for incorrect patterns or handle escape characters. This was fixed. - diff --git a/releases/2021.1.rst b/releases/2021.1.rst deleted file mode 100644 index ebf839f21..000000000 --- a/releases/2021.1.rst +++ /dev/null @@ -1,224 +0,0 @@ -.. _2021.1: - -******************** -Release Notes 2021.1 -******************** - -The 2021.1 release notes were released on 6/13/2021 and describe the following: - -.. contents:: - :local: - :depth: 1 - - -Version Content ---------------- - -The 2021.1 Release Notes describes the following: - -* Major feature release targeted for all on-premises customers. -* Basic Cloud functionality. - - -New Features ------------- - -The 2021.1 Release Notes include the following new features: - - - -.. contents:: - :local: - :depth: 1 - -SQream DB on Cloud -****************** - -SQream DB can now be run on AWS, GCP, and Azure. - -Numeric Data Types -****************** - -SQream now supports Numeric Data types for the following operations: - - * All join types. - * All aggregation types (not including Window functions). - * Scalar functions (not including some trigonometric and logarithmic functions). - -For more information, see `Numeric Data Types <https://docs.sqream.com/en/v2021.1/reference/sql_data_types.html#numeric-data-types.html>`_. - -Text Data Type -************** - -SQream now supports TEXT data types in all operations, which is default string data type for new projects. - - - * Sqream supports VARCHAR functionalty, but recommends using TEXT. - - * TEXT data enhancements introduced in Release Notes version 2020.3.1: - - * Support text columns in queries with multiple distinct aggregates. - * Text literal support for all functions. - -For more information, see `String Types <https://docs.sqream.com/en/v2021.1/data_type_guides/sql_data_types_string.html>`_. - - -Supports Scalar Subqueries -************************** - -SQream now supports running initial scalar subqueries. - -For more information, see `Subqueries <https://docs.sqream.com/en/v2021.1/reference/sql/sql_syntax/subqueries.html>`_. - -Literal Arguments -***************** - -SQream now supports literal arguments for functions in all cases where column/scalar arguments are supported. - -Simple Scalar SQL UDFs -********************** - -SQream now supports simple scalar SQL UDF's. - -For more information, see `Simple Scalar SQL UDF’s <https://docs.sqream.com/en/v2021.1/reference/sql/sql_functions/user_defined_functions/scalar_sql_udf.html>`_. - -Logging Enhancements -************ -The following log information has been added for the following events: - - * Compilation start time. - * When the first metadata callback in the compiler (if relevant). - * When the last metadata callback in the compiler (if relevant). - * When the log started attempting to apply locks. - * When a statement entered the queue. - * When a statement exited the queue. - * When a client has connected to an instance of **sqreamd** (if it reconnects). - * When the log started executing. - -Improved Presented License Information -************ -SQream now displays information related to data size limitations, expiration date, type of license shown by the new UF. The **Utility Function (UF)** name is ``get_license_info()``. - -For more information, see `GET_LICENSE_INFO <https://docs.sqream.com/en/v2021.1/reference/sql/sql_statements/utility_commands/get_license_info.html>`_. - - - - -Optimized Foreign Data Wrapper Export -************************************* - -Sqream now supports exporting to multiple files concurrently. This is useful when you need to reduce file size to more easily export multiple files. - -The following is the correct syntax for exporting multiple files concurrently: - -.. code-block:: none - - COPY table_name TO fdw_name OPTIONS(max_file_size=size_in_bytes,enforce_single_file={TRUE|FALSE}); - -The following is an example of the correct syntax for exporting multiple files concurrently: - -.. code-block:: none - - COPY my_table1 TO my_ext_table OPTIONS(max_file_size=500000,enforce_single_file=TRUE); - -The following apply: - -* Both of the parameters in the above example are optional. - -* The ``max_file_size`` value is specified in bytes and can be any positive value. The default value is ``16*2^20`` (16MB). - -* When the ``enforce_single_file`` value is set to ``TRUE``, only one file is created, and its size is not limited by the ``max_file_size`` value. Its default value is ``TRUE``. - -Main Features -------------- - -The following list describes the main features: - -* SQreamDB available on AWS. -* SQreamDB available on GCP. -* SQreamDB available on Azure. -* SQream usages storage located on Object Store (as opposed to local disks) for the above three cloud providers. -* SQream now supports Microstrategy. -* Supports MVP licensing system. -* A new literal syntax containing character escape semantics for string literals has been added. -* Supports optimizing exporting foreign data wrappers. -* Supports truncating Numeric values when ingested from ORC and CSV files. -* Supports catalog Utility Function that accepts valid SQL patterns and escape characters. -* Supports creating a basic random data foreign data wrapper for non-text types. -* The new foreign data wrapper ``random_fdw`` has been introduced for non-text types. -* Supports simple scalar SQL UDF's. -* SQream parses its own logs as CSV's. - - -Resolved Issues ---------------- - -The following list describes the resolved issues: - -* Copying text from a CSV file to the TEXT column without closing quotes caused SQream to crash. This was fixed. -* Using an unsupported function call generated an incorrect insert error. This was fixed. -* Using the ``insert into`` function from ``table_does_not_exist`` generated an incorrect error. -* SQream treated inserting ``*`` in ``select_distinct`` as one column. This was fixed. -* Using certain encodeKey functions generated errors. This was fixed. -* Compile errors occurred while running decimal datatype sets. This was fixed. -* Running the ``select table_name,row_count from sqream_catalog.tables order by row_count limit 5`` query generated an internal runtime error. -* Using wildcards (such as ``*.x.y``) did not work in parquet files. This was fixed. -* Executing ``log*(x,y)`` generated an incorrect error message. This was fixed. -* The ``internal runtime error`` type doesn't have a fixed size when doing max on text on develop. -* The ``min`` and ``max`` on ``TEXT`` were significantly slower than ``varchar``. This was fixed. -* Running ``regexp_instr`` generated an empty regular expression. This was fixed. -* Schemas with foreign tables could be dropped. This was fixed. - - - -Operations and Configuration Changes ------------------------------------- - -Recommended SQream Configuration on Cloud -***************************************** - -For more information about AWS, see `Amazon S3 <https://docs.sqream.com/en/v2021.1/operational_guides/s3.html>`_. - - - - -Optimized Foreign Data Wrapper Export Configuration Flag -******************************************************** - -SQream now has a new ``runtimeGlobalFlags`` flag called ``WriteToFileThreads``. - -This flag configures the number of threads in the **WriteToFile** function. The default value is ``16``. - -For more information about the ``runtimeGlobalFlags`` flag, see the **Runtime Global Flags** table in `Configuration <https://docs.sqream.com/en/v2021.1/configuration_guides/index.html>`_. - - - - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -No features were depecrated. - -Known Issues and Limitations ----------------------------- - -The the list below describes the following known issues and limitations: - -* In cases when selecting top 1 from foreign table using the Parquet format with an hdfs path, SQream experienced an error. -* Internal Runtime Error occurred when SQream was unable to find column in reorder columns. -* Casting datetime to text truncates the time segment. -* In the **select** list, the compiler generates an error when a count is used as an alias. -* Performance degradation occurred when joins made on small tables. -* SQream causes a logging error when using copy from logs. -* Deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. - -Upgrading to v2021.1 --------------------- - -Due to the known issue of a limitation on the amount of access requests that can be simultaneously sent to AWS, deploying S3 requires setting the ``ObjectStoreClients`` parameter to ``40``. - diff --git a/releases/2021.1_index.rst b/releases/2021.1_index.rst deleted file mode 100644 index ce573329a..000000000 --- a/releases/2021.1_index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _2021.1_index: - -******************** -Release Notes 2021.1 -******************** - -The 2021.1 Release Notes describe the following releases: - -.. contents:: - :local: - :depth: 1 - -.. toctree:: - :maxdepth: 1 - :glob: - - 2021.1.2 - 2021.1 \ No newline at end of file From d488cc02166fc4abc4cc34ef7e60fd3a83e0e812 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Feb 2024 15:19:30 +0200 Subject: [PATCH 1185/1892] Update repeat.rst --- .../sql/sql_functions/scalar_functions/string/repeat.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/repeat.rst b/reference/sql/sql_functions/scalar_functions/string/repeat.rst index 920aa55db..df9c2fe6f 100644 --- a/reference/sql/sql_functions/scalar_functions/string/repeat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/repeat.rst @@ -3,7 +3,7 @@ ****** REPEAT ****** - + The ``REPEAT`` function repeats an input string expression as many times as specified. Syntax @@ -32,7 +32,8 @@ Return ====== * Returns a ``TEXT`` string. -* When ``n`` <= 0, and empty string is returned. +* When ``n`` = 0, and empty string is returned. +* When ``n`` < 0, an error is thrown. Examples ======== From 0a8fb28cc5f59a2e5aa78c8b01ffe999bce2c77a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Feb 2024 16:22:23 +0200 Subject: [PATCH 1186/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index c641f8989..bc44cbe0e 100644 --- a/conf.py +++ b/conf.py @@ -26,7 +26,7 @@ # The full version, including alpha/beta/rc tags -release = '4.6' +release = '4.7' From ab09c1253bf9eb47a2d19f8f169f3a84ae652c08 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Feb 2024 15:32:51 +0200 Subject: [PATCH 1187/1892] Update current_method_configuration_levels.rst --- .../current_method_configuration_levels.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 4294ffe8e..5c627b2ef 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -104,6 +104,12 @@ Flag List - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - boolean - ``FALSE`` + * - ``clientReconnectionTimeout`` + - Anyone + - Cluster + - Reconnection time out for the system in seconds. + - Integer + - ``30`` * - ``compilerGetsOnlyUFs`` - SUPERUSER - Session From f5261d63ebab3d5063814a26b97abb992fb16548 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 08:11:56 +0200 Subject: [PATCH 1188/1892] Update conf.py --- conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index bc44cbe0e..55b4d938d 100644 --- a/conf.py +++ b/conf.py @@ -21,7 +21,7 @@ # -- Project information ----------------------------------------------------- project = 'SQreamDB' -copyright = '2023 SQreamDB' +copyright = '2024 SQreamDB' author = 'SQreamDB Documentation' @@ -64,7 +64,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static/images'] +html_static_path = ['_static'] favicons = [ "_static/images/faviconSQ.png" From 1265273159ec4a2c62733af39c90a44bfa4ed401 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:16:06 +0200 Subject: [PATCH 1189/1892] ldap --- conf.py | 3 --- configuration_guides/ldap.rst | 45 +++++++++++++++-------------------- 2 files changed, 19 insertions(+), 29 deletions(-) diff --git a/conf.py b/conf.py index 55b4d938d..2ed03f47f 100644 --- a/conf.py +++ b/conf.py @@ -66,9 +66,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -favicons = [ - "_static/images/faviconSQ.png" -] html_css_files = [ 'css/custom.css', # Relative to the _static path diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index b86d70c53..592d51f3b 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -17,17 +17,6 @@ Before integrating SQream with LDAP consider the following: :local: :depth: 1 -Before You Begin -================ - -Enable self-signed certificates for OpenLDAP by adding the following line to the ``ldap.conf`` configuration file: - -.. code-block:: postgres - - ``TLS_REQCERT allow`` - - - Configuring SQream roles ======================== @@ -94,19 +83,19 @@ To enable basic LDAP authentication, configure the following cluster flag attrib * - Attribute - Description * - ``authenticationMethod`` - - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap`` * - ``ldapIpAddress`` - - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol. + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol * - ``ldapConnTimeoutSec`` - - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds. + - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds * - ``ldapPort`` - LDAP server port number. * - ``ldapAdvancedMode`` - - Configure either basic or advanced authentication method. Default = ``false``. + - Configure either basic or advanced authentication method. Default = ``false`` * - ``ldapPrefix`` - - String to prefix to the user name when forming the DN to bind as, when doing simple bind authentication. + - String to prefix to the user name when forming the DN to bind as, when doing simple bind authentication * - ``ldapSuffix`` - - String to append to the user name when forming the DN to bind as, when doing simple bind authentication. + - String to append to the user name when forming the DN to bind as, when doing simple bind authentication Basic Method Configuration @@ -192,23 +181,25 @@ To enable advanced LDAP authentication, configure the following cluster flag att * - Attribute - Description * - ``authenticationMethod`` - - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap``. + - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap`` * - ``ldapIpAddress`` - - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol. + - Configure the IP address or the Fully Qualified Domain Name (FQDN) of your LDAP server and select a protocol: ``ldap`` or ``ldaps``. Sqream recommends using the encrypted ``ldaps`` protocol * - ``ldapConnTimeoutSec`` - - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds. + - Configure the LDAP connection timeout threshold (seconds). Default = 30 seconds * - ``ldapPort`` - - LDAP server port number. + - LDAP server port number * - ``ldapAdvancedMode`` - - Set ``ldapAdvancedMode`` = ``true``. + - Set ``ldapAdvancedMode`` = ``true`` * - ``ldapBaseDn`` - - Root DN to begin the search for the user in, when doing advanced authentication. + - Root DN to begin the search for the user in, when doing advanced authentication * - ``ldapBindDn`` - - DN of user with which to bind to the directory to perform the search when doing search + bind authentication. + - DN of user with which to bind to the directory to perform the search when doing search + bind authentication * - ``ldapBindDnPassword`` - - Password for user with which to bind to the directory to perform the search when doing search + bind authentication. + - Password for user with which to bind to the directory to perform the search when doing search + bind authentication * - ``ldapSearchAttribute`` - - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used. + - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used + * - ``ldapSearchFilter`` + - Filters ``ldapAdvancedMode`` authentication Advanced Method Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -307,6 +298,8 @@ User has value of elonm for attribute ``sAMAccountName``. ALTER SYSTEM SET ldapConnTimeoutSec = 30; + ALTER SYSTEM SET ldapSearchFilter = "(memberOf=CN=SqreamGroup,CN=Builtin,DC=sqream,DC=loc)(memberOf=CN=Admins,CN=Builtin,DC=sqream,DC=loc)" + Logging in will be possible using the username elonm using sqream client From f79754c251a246ebc130347625f78ac879864435 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:19:54 +0200 Subject: [PATCH 1190/1892] Update ldap.rst --- configuration_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 592d51f3b..75b99bb6f 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -298,7 +298,7 @@ User has value of elonm for attribute ``sAMAccountName``. ALTER SYSTEM SET ldapConnTimeoutSec = 30; - ALTER SYSTEM SET ldapSearchFilter = "(memberOf=CN=SqreamGroup,CN=Builtin,DC=sqream,DC=loc)(memberOf=CN=Admins,CN=Builtin,DC=sqream,DC=loc)" + ALTER SYSTEM SET ldapSearchFilter = "(memberOf=CN=SqreamGroup,CN=Builtin,DC=sqream,DC=loc)(memberOf=CN=Admins,CN=Builtin,DC=sqream,DC=loc)"; Logging in will be possible using the username elonm using sqream client From 50eeeb21801c7c92894f9da4cd8855a23b123b32 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:32:54 +0200 Subject: [PATCH 1191/1892] Maintenance --- index.rst | 2 +- operational_guides/external_data.rst | 3 ++- reference/sql_feature_support.rst | 17 ++++++++--------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/index.rst b/index.rst index e6155a857..98c3ab087 100644 --- a/index.rst +++ b/index.rst @@ -5,7 +5,7 @@ SQreamDB Documentation ************************* -SQreamDB is a columnar analytic SQL database management system. SQreamDB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQreamDB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQreamDB easily plugs in to third-party tools like :ref:`Tableau<connect_to_tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. +SQreamDB is a columnar analytic SQL database management system. SQreamDB supports regular SQL including :ref:`a substantial amount of ANSI SQL<sql_feature_support>`, uses :ref:`serializable transactions<transactions>`, and :ref:`scales horizontally<concurrency_and_scaling_in_sqream>` for concurrent statements. Even a :ref:`basic SQreamDB machine<hardware_guide>` can support tens to hundreds of terabytes of data. SQreamDB easily plugs in to third-party tools like :ref:`Tableau<tableau>` comes with standard SQL client drivers, including :ref:`JDBC<java_jdbc>`, :ref:`ODBC<odbc>`, and :ref:`Python DB-API<pysqream>`. +-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index c9a6cfb33..bab21eeff 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -3,6 +3,7 @@ ********************************** Working with External Data ********************************** + SQream supports the following external data sources: .. toctree:: @@ -15,7 +16,7 @@ SQream supports the following external data sources: For more information, see the following: -* :ref:`external_tables` +* :ref:`foreign_tables` :: diff --git a/reference/sql_feature_support.rst b/reference/sql_feature_support.rst index 70c101dae..75dff3614 100644 --- a/reference/sql_feature_support.rst +++ b/reference/sql_feature_support.rst @@ -4,8 +4,7 @@ SQL Feature Checklist ********************* - -To understand which ANSI SQL and other SQL features SQream DB supports, use the tables below. +To understand which ANSI SQL and other SQL features SQreamDB supports, use the tables below. .. contents:: In this topic: :local: @@ -14,8 +13,6 @@ To understand which ANSI SQL and other SQL features SQream DB supports, use the Data Types and Values ===================== -Read more about :ref:`Yes data types<data_types>`. - .. list-table:: Data Types and Values :widths: auto :header-rows: 1 @@ -85,10 +82,12 @@ Constraints - ``IDENTITY`` +.. _transactions: + Transactions ============ -SQream DB treats each statement as an auto-commit transaction. Each transaction is isolated from other transactions with serializable isolation. +SQreamDB treats each statement as an auto-commit transaction. Each transaction is isolated from other transactions with serializable isolation. If a statement fails, the entire transaction is canceled and rolled back. The database is unchanged. @@ -96,11 +95,11 @@ If a statement fails, the entire transaction is canceled and rolled back. The da Indexes ======= -SQream DB has a range-index collected on all columns as part of the metadata collection process. +SQreamDB has a range-index collected on all columns as part of the metadata collection process. -SQream DB does not support explicit indexing, but does support clustering keys. +SQreamDB does not support explicit indexing, but does support clustering keys. -Read more about :ref:`clustering keys<data_clustering>` and our :ref:`metadata system<metadata_system>`. +Read more about :ref:`clustering keys<clustering_keys>`. Schema Changes ================ @@ -289,7 +288,7 @@ Read more about :ref:`scalar_expressions`. Permissions =============== -Read more about :ref:`access_control` in SQream DB. +Read more about :ref:`access_control` in SQreamDB. .. list-table:: Permissions :widths: auto From e1833bca8a00fa0ef94a0b433943f943f3efbaeb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 11:51:19 +0200 Subject: [PATCH 1192/1892] Update conf.py --- conf.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/conf.py b/conf.py index 2ed03f47f..99cd8288e 100644 --- a/conf.py +++ b/conf.py @@ -38,7 +38,6 @@ extensions = [ 'sphinx_rtd_theme' ,'notfound.extension' # 404 handling - ,'sphinx_favicon' ] # Mark 'index' as the main page @@ -59,7 +58,6 @@ # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' -html_favicon = "_static/images/faviconSQ.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From 3ede9fc9f839fffa416a8f4980436e162488da3c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:09:48 +0200 Subject: [PATCH 1193/1892] Update ldap.rst --- configuration_guides/ldap.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 75b99bb6f..c89249eb1 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -249,20 +249,26 @@ Only roles with admin privileges and higher may enable LDAP Authentication. .. code-block:: postgres ALTER SYSTEM SET ldapSearchAttribute = '<search_attribute>'; + +8. To set the ``ldapSearchFilter`` attribute (Optional), run: + +.. code-block:: postgres + + ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)'; -8. To set the ``ldapPort`` attribute (Optional), run: +9. To set the ``ldapPort`` attribute (Optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapPort = <port_number> -9. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: +10. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapConnTimeoutSec = <15>; -10. Restart all sqreamd servers. +11. Restart all sqreamd servers. Example ~~~~~~~ From 87dedf9099e4b08f70f3cec88827840cfdcdfb85 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 13:17:57 +0200 Subject: [PATCH 1194/1892] Update ldap.rst --- configuration_guides/ldap.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index c89249eb1..8f1d53fd9 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -199,7 +199,7 @@ To enable advanced LDAP authentication, configure the following cluster flag att * - ``ldapSearchAttribute`` - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used * - ``ldapSearchFilter`` - - Filters ``ldapAdvancedMode`` authentication + - Filters ``ldapAdvancedMode`` authentication. ``ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)';`` Advanced Method Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From 3873053b215718656b7203bfdd5215184d46c176 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 5 Mar 2024 16:51:29 +0200 Subject: [PATCH 1195/1892] SSO --- configuration_guides/configuring_sqream.rst | 1 + configuration_guides/index.rst | 3 +- configuration_guides/ldap.rst | 6 +- configuration_guides/sso.rst | 64 +++++++++++++++++++++ releases/4.6.rst | 1 + 5 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 configuration_guides/sso.rst diff --git a/configuration_guides/configuring_sqream.rst b/configuration_guides/configuring_sqream.rst index 685e24516..bbaffc9e1 100644 --- a/configuration_guides/configuring_sqream.rst +++ b/configuration_guides/configuring_sqream.rst @@ -3,6 +3,7 @@ ************************* Configuring SQream ************************* + The **Configuring SQream** page describes the following configuration topics: .. toctree:: diff --git a/configuration_guides/index.rst b/configuration_guides/index.rst index a694bb227..cf89a57ce 100644 --- a/configuration_guides/index.rst +++ b/configuration_guides/index.rst @@ -11,4 +11,5 @@ The **Configuration Guides** page describes the following configuration informat :glob: configuring_sqream - ldap \ No newline at end of file + ldap + sso \ No newline at end of file diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 8f1d53fd9..9905d016d 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -1,8 +1,8 @@ .. _ldap: -************************************* -Configuring LDAP authentication -************************************* +******************** +LDAP Authentication +******************** Lightweight Directory Access Protocol (LDAP) is an authentication management service used with Microsoft Active Directory and other directory services. Once LDAP authentication has been configured for SQream, authorization for all existing and newly added roles must be handled by the LDAP server, except for the initial system deployment ``sqream`` role, which was immediately given full control permissions when SQream was initially deployed. diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst new file mode 100644 index 000000000..4f7745558 --- /dev/null +++ b/configuration_guides/sso.rst @@ -0,0 +1,64 @@ +.. _sso: + +Ping Identity Single Sign-On +============================ + + + + + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential you have the following installed: + +* SQreamDB Acceleration Studio v5.9.0 +* There should be an NGINX (or similar) service installed on your Acceleration Studio machine, which will serve as a reverse proxy. This service will accept HTTPS traffic from external sources and communicate with Studio via HTTP internally + +Setting Ping Identity +============================= + +1. Log in to your Ping Identity account and create a **Single Page** application. + +2. Under **Application** > **YourAccount**, set the following: + + * **Policies** > **DaVinci** > **PingOne**, set **Sign On and Registration** + + * **Resources**, set **openid**, **profile**, **P1:read:user**, **P1:verify:user** + +3. Under **Application** > **YourAccount** > **Configuration**, create the following URLs: + + * **URLs** > Copy Authorization URL + + * Redirect URIs + +4. Under **Application** > **YourAccount**, copy Client ID and replace it in the following string: => This is 2nd part of the final URL. + +``?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user (Please note that the whole string must be copied)`` + +Connect both parts in a following manner: + +``https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/authorize?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user`` + +Logoff: + +``https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff`` + +Setting SQreamDB Acceleration Studio +========================================================== + +1. Set PingOne SSO authentication using either of the following methods: + + * The **recommended** method is to manually paste the authentication URL to your ``sqrea_admin_config.json`` file. + + * Alternatively, you may set the authentication URL during the SQreamDB Acceleration Studio installation process, after having ran the ``npm run setup`` command, by pasting the authentication URL in the questionnaire. + +2. In your ``sqream_legacy.json``, change ``"authenticationMethod": "sqream"`` to ``"authenticationMethod": "ldap"`` and add the ``pingoneValidateUrl`` flag along with the ______ URL: ``"pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo"`` + +5. Restart SQreamDB. +6. Restart SQreamDB Acceleration Studio. + diff --git a/releases/4.6.rst b/releases/4.6.rst index 47ed1df62..fc69f38c4 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -29,6 +29,7 @@ Compatibility Matrix | | * .NET 3.0.2 | | | * Pysqream 5.0.0 | | | * Spark 5.0.0 | +| | * SQLoader 7.12 (compatible with v4.6.1 or later) | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 78d53431196d00ab96a6cc72e5018e5a2527e531 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 6 Mar 2024 10:10:01 +0200 Subject: [PATCH 1196/1892] Update create_role.rst --- .../sql/sql_statements/access_control_commands/create_role.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/access_control_commands/create_role.rst b/reference/sql/sql_statements/access_control_commands/create_role.rst index 6e3b815b1..630cf6714 100644 --- a/reference/sql/sql_statements/access_control_commands/create_role.rst +++ b/reference/sql/sql_statements/access_control_commands/create_role.rst @@ -83,4 +83,4 @@ A user role has permissions to login, and has a password. GRANT PASSWORD 'passw0rd' to new_role; GRANT CONNECT ON DATABASE master to new_role; -- Repeat for all desired databases GRANT USAGE ON SERVICE sqream TO new_role; - GRANT ALL ON SCHEMA public; -- It is advisable to grant permissions on at least one schema \ No newline at end of file + GRANT ALL ON SCHEMA public TO new_role; -- It is advisable to grant permissions on at least one schema From c700d8086f2b09f3b3b8236c2deeb73098ff7c20 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 07:49:39 +0200 Subject: [PATCH 1197/1892] JDBC 5.1.0 --- connecting_to_sqream/client_drivers/index.rst | 2 +- connecting_to_sqream/client_drivers/jdbc/index.rst | 6 +++--- releases/4.6.rst | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 9ce16723c..928913b2b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.0.0.jar>`_ + - `sqream-jdbc 5.1.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.1.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 618d415b7..78e6ea589 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -45,18 +45,18 @@ Setting Up the Class Path To use the driver, you must include the JAR named ``sqream-jdbc-<version>.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-5.0.0.jar``, the following command is used to run application: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-5.1.0.jar``, the following command is used to run application: .. code-block:: console - $ export CLASSPATH=/home/sqream/sqream-jdbc-5.0.0.jar:$CLASSPATH + $ export CLASSPATH=/home/sqream/sqream-jdbc-5.1.0.jar:$CLASSPATH $ java my_java_app Alternatively, you can pass ``-classpath`` to the Java executable file: .. code-block:: console - $ java -classpath .:/home/sqream/sqream-jdbc-5.0.0.jar my_java_app + $ java -classpath .:/home/sqream/sqream-jdbc-5.1.0.jar my_java_app Connecting to SQream Using a JDBC Application ============================================= diff --git a/releases/4.6.rst b/releases/4.6.rst index fc69f38c4..acea25777 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -23,7 +23,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.0.0 | +| Driver compatibility | * JDBC 5.1.0 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | From 102043f2775e866049052a94a21ab5df9769e92c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 08:45:26 +0200 Subject: [PATCH 1198/1892] Maintenance --- connecting_to_sqream/client_drivers/index.rst | 5 ++-- .../client_platforms/index.rst | 2 +- .../php.rst | 26 ++++++------------- .../installing_and_launching_sqream.rst | 1 - operational_guides/external_data.rst | 11 +++----- operational_guides/index.rst | 2 -- reference/index.rst | 1 - releases/2022.1.rst | 13 ---------- releases/index.rst | 1 - ...ts_and_running_queries_from_the_editor.rst | 25 ------------------ 10 files changed, 15 insertions(+), 72 deletions(-) rename connecting_to_sqream/{client_drivers => client_platforms}/php.rst (82%) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 928913b2b..3525e1de5 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -73,12 +73,13 @@ Client Driver Downloads :titlesonly: :hidden: + dotnet/index jdbc/index - python/index nodejs/index odbc/index - dotnet/index + python/index spark/index + trino/index diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 1c1c164b8..796695f4c 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -64,7 +64,7 @@ Data Analysis and Programming Languages tableau talend tibco_spotfire - trino + diff --git a/connecting_to_sqream/client_drivers/php.rst b/connecting_to_sqream/client_platforms/php.rst similarity index 82% rename from connecting_to_sqream/client_drivers/php.rst rename to connecting_to_sqream/client_platforms/php.rst index b15a5121f..f9f90ce85 100644 --- a/connecting_to_sqream/client_drivers/php.rst +++ b/connecting_to_sqream/client_platforms/php.rst @@ -20,11 +20,7 @@ Installing PHP 1. Download the JDBC driver installer from the `SQream Drivers page <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/index.html>`_. - :: - 2. Create a DSN. - - :: 3. Install the **uODBC** extension for your PHP installation. @@ -36,20 +32,14 @@ Configuring PHP You can configure PHP in one of the following ways: * When compiling, configure PHP to enable uODBC using ``./configure --with-pdo-odbc=unixODBC,/usr/local``. - - :: * Install ``php-odbc`` and ``php-pdo`` along with PHP using your distribution package manager. SQream recommends a minimum of version 7.1 for the best results. .. note:: PHP's string size limitations truncates fetched text, which you can override by doing one of the following: * Increasing the **php.ini** default setting, such as the *odbc.defaultlrl* to **10000**. - - :: * Setting the size limitation in your code before making your connection using **ini_set("odbc.defaultlrl", "10000");**. - - :: * Setting the size limitation in your code before fetchng your result using **odbc_longreadlen($result, "10000");**. @@ -60,21 +50,21 @@ After configuring PHP, you can test your connection. **To test your connection:** -#. Create a test connection file using the correct parameters for your SQream installation, as shown below: +1. Create a test connection file using the correct parameters for your SQream installation, as shown below: - .. literalinclude:: test.php - :language: php - :emphasize-lines: 4 - :linenos: + .. literalinclude:: test.php + :language: php + :emphasize-lines: 4 + :linenos: For more information, download the sample :download:`PHP example connection file <test.php>` shown above. The following is an example of a valid DSN line: - .. code:: php + .. code-block:: php - $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; + $dsn = "odbc:Driver={SqreamODBCDriver};Server=192.168.0.5;Port=5000;Database=master;User=rhendricks;Password=super_secret;Service=sqream"; -#. Run the PHP file either directly with PHP (``php test.php``) or through a browser. +2. Run the PHP file either directly with PHP (``php test.php``) or through a browser. For more information about supported DSN parameters, see :ref:`dsn_params`. \ No newline at end of file diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index b82bc95e8..990081cd7 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -12,6 +12,5 @@ The **Installing and Launching SQreamDB** page includes the following installati recommended_pre-installation_configurations installing_sqream_with_binary - running_sqream_in_a_docker_container installing_monit launching_sqream_with_monit \ No newline at end of file diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index bab21eeff..858d4bf20 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -12,16 +12,11 @@ SQream supports the following external data sources: s3 hdfs - mounting_an_nfs_shared_drive For more information, see the following: -* :ref:`foreign_tables` - - :: +:ref:`foreign_tables` -* :ref:`copy_from` - - :: +:ref:`copy_from` -* :ref:`copy_to` \ No newline at end of file +:ref:`copy_to` \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 60a345e91..8f2b5be45 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -24,7 +24,5 @@ This section summarizes the following operational guides: security saved_queries seeing_system_objects_as_ddl - configuration optimization_best_practices - hardware_guide \ No newline at end of file diff --git a/reference/index.rst b/reference/index.rst index 6187b0b1f..2dffa1025 100644 --- a/reference/index.rst +++ b/reference/index.rst @@ -15,4 +15,3 @@ The **Reference Guides** section provides reference for using SQream DB's interf catalog_reference cli/index sql_feature_support - xxconfiguration diff --git a/releases/2022.1.rst b/releases/2022.1.rst index 6659d455e..c748e12d4 100644 --- a/releases/2022.1.rst +++ b/releases/2022.1.rst @@ -125,20 +125,12 @@ Upgrading to v2022.1 2. Shut down all SQream services. - :: - 3. Extract the recently created backup file. - :: - 4. Replace your current metadata with the metadata you stored in the backup file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console @@ -147,9 +139,4 @@ Upgrading to v2022.1 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. -.. toctree:: - :maxdepth: 2 - :glob: - :hidden: - 2022.1 diff --git a/releases/index.rst b/releases/index.rst index f99fa2838..347cacef1 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -48,7 +48,6 @@ Release Notes :glob: :hidden: - whats_new 4.0_index 2022.1_index 2021.2_index diff --git a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index 6f0cb7ad6..840fe283d 100644 --- a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -49,12 +49,8 @@ You can access the following from the Toolbar pane: * **Database dropdown list** - select a database that you want to run statements on. - :: - * **Service dropdown list** - select a service that you want to run statements on. The options in the service dropdown menu depend on the database you select from the **Database** dropdown list. - :: - * **Execute** - lets you set which statements to execute. The **Execute** button toggles between **Execute** and **Stop**, and can be used to stop an active statement before it completes: * **Statements** - executes the statement at the location of the cursor. @@ -63,24 +59,15 @@ You can access the following from the Toolbar pane: * **Format SQL** - Lets you reformat and reindent statements. - :: - * **Download query** - Lets you download query text to your computer. - :: - * **Open query** - Lets you upload query text from your computer. - :: - * **Max Rows** - By default, the Editor fetches only the first 10,000 rows. You can modify this number by selecting an option from the **Max Rows** dropdown list. Note that setting a higher number may slow down your browser if the result is very large. This number is limited to 100,000 results. To see a higher number, you can save the results in a file or a table using the :ref:`create_table_as` command. For more information on stopping active statements, see the :ref:`STOP_STATEMENT<stop_statement>` command. - - - .. _studio_editor_db_tree: Performing Statement-Related Operations from the Database Tree @@ -93,12 +80,8 @@ The database object functions are used to perform the following: * The **SELECT** statement - copies the selected table's **columns** into the Statement panel as ``SELECT`` parameters. - :: - * The **copy** feature |icon-copy| - copies the selected table's **name** into the Statement panel. - :: - * The **additional operations** |icon-dots| - displays the following additional options: @@ -117,9 +100,6 @@ The database object functions are used to perform the following: .. |icon-select| image:: /_static/images/studio_icon_select.png :align: middle -.. |icon-dots| image:: /_static/images/studio_icon_dots.png - :align: middle - .. |icon-filter| image:: /_static/images/studio_icon_filter.png :align: middle @@ -129,9 +109,6 @@ The database object functions are used to perform the following: .. |icon-run-optimizer| image:: /_static/images/studio_icon_run_optimizer.png :align: middle -.. |icon-generate-create-statement| image:: /_static/images/studio_icon_generate_create_statement.png - :align: middle - .. |icon-plus| image:: /_static/images/studio_icon_plus.png :align: middle @@ -236,8 +213,6 @@ Executing Pre-Defined Queries from the System Queries Panel The **System Queries** panel lets you execute predefined queries and includes the following system query types: * **Catalog queries** - Used for analyzing table compression rates, users and permissions, etc. - - :: * **Admin queries** - Queries useful for SQreamDB database management. From e9bce47ba5ec95d3479f415bee5d1cadc839162b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 10:03:06 +0200 Subject: [PATCH 1199/1892] Update sso.rst --- configuration_guides/sso.rst | 40 ++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 4f7745558..a7e29b2e7 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -1,10 +1,8 @@ .. _sso: -Ping Identity Single Sign-On -============================ - - - +************* +Ping Identity +************* .. contents:: @@ -22,21 +20,21 @@ It is essential you have the following installed: Setting Ping Identity ============================= -1. Log in to your Ping Identity account and create a **Single Page** application. +Log in to your Ping Identity account, create a **Single Page** application, and set the following: -2. Under **Application** > **YourAccount**, set the following: +1. Under **Application** > **YourAccount**, set the following: * **Policies** > **DaVinci** > **PingOne**, set **Sign On and Registration** * **Resources**, set **openid**, **profile**, **P1:read:user**, **P1:verify:user** -3. Under **Application** > **YourAccount** > **Configuration**, create the following URLs: +2. Under **Application** > **YourAccount** > **Configuration**, create the following URLs: * **URLs** > Copy Authorization URL * Redirect URIs -4. Under **Application** > **YourAccount**, copy Client ID and replace it in the following string: => This is 2nd part of the final URL. +3. Under **Application** > **YourAccount**, copy Client ID and replace it in the following string: => This is 2nd part of the final URL. ``?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user (Please note that the whole string must be copied)`` @@ -51,14 +49,26 @@ Logoff: Setting SQreamDB Acceleration Studio ========================================================== -1. Set PingOne SSO authentication using either of the following methods: +1. To set PingOne as your SSO, use either of the following methods: - * The **recommended** method is to manually paste the authentication URL to your ``sqrea_admin_config.json`` file. + * Manually paste the authentication URL to your ``sqrea_admin_config.json`` file (recommended method) - * Alternatively, you may set the authentication URL during the SQreamDB Acceleration Studio installation process, after having ran the ``npm run setup`` command, by pasting the authentication URL in the questionnaire. + * Set the authentication URL during an Acceleration Studio installation process by pasting the authentication URL in the questionnaire that follows the ``npm run setup`` command -2. In your ``sqream_legacy.json``, change ``"authenticationMethod": "sqream"`` to ``"authenticationMethod": "ldap"`` and add the ``pingoneValidateUrl`` flag along with the ______ URL: ``"pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo"`` +2. In your ``sqream_legacy.json`` file, make the following adjustments: + + * Change the ``authenticationMethod`` flag value from ``sqream`` to ``ldap`` -5. Restart SQreamDB. -6. Restart SQreamDB Acceleration Studio. + .. code-block:: + + "authenticationMethod": "ldap" + + * Add the ``pingoneValidateUrl`` flag along with the ______ URL + + .. code-block:: + + "pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" + +3. Restart SQreamDB. +4. Restart SQreamDB Acceleration Studio. From 1b1246a2afabd738001c67b3049e30f2b434773e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 11:16:17 +0200 Subject: [PATCH 1200/1892] SSO --- configuration_guides/ldap.rst | 2 +- configuration_guides/sso.rst | 32 +++++++++++-------- .../optimization_best_practices.rst | 6 ++-- .../ddl_commands/drop_clustering_key.rst | 4 +-- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 9905d016d..8b5a18812 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -1,7 +1,7 @@ .. _ldap: ******************** -LDAP Authentication +LDAP ******************** diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index a7e29b2e7..5ca074ba3 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -1,8 +1,8 @@ .. _sso: -************* -Ping Identity -************* +************** +Single Sign-On +************** .. contents:: @@ -18,7 +18,7 @@ It is essential you have the following installed: * There should be an NGINX (or similar) service installed on your Acceleration Studio machine, which will serve as a reverse proxy. This service will accept HTTPS traffic from external sources and communicate with Studio via HTTP internally Setting Ping Identity -============================= +===================== Log in to your Ping Identity account, create a **Single Page** application, and set the following: @@ -49,19 +49,23 @@ Logoff: Setting SQreamDB Acceleration Studio ========================================================== -1. To set PingOne as your SSO, use either of the following methods: +1. Set :ref:`ldap` as your authentication management service. + + The ``authenticationMethod`` flag value should be ``ldap`` + + .. code-block:: + + "authenticationMethod": "ldap" + +2. + +To set PingOne as your SSO, use either of the following methods: * Manually paste the authentication URL to your ``sqrea_admin_config.json`` file (recommended method) * Set the authentication URL during an Acceleration Studio installation process by pasting the authentication URL in the questionnaire that follows the ``npm run setup`` command -2. In your ``sqream_legacy.json`` file, make the following adjustments: - - * Change the ``authenticationMethod`` flag value from ``sqream`` to ``ldap`` - - .. code-block:: - - "authenticationMethod": "ldap" +3. In your ``sqream_legacy.json`` file, make the following adjustments: * Add the ``pingoneValidateUrl`` flag along with the ______ URL @@ -69,6 +73,6 @@ Setting SQreamDB Acceleration Studio "pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" -3. Restart SQreamDB. -4. Restart SQreamDB Acceleration Studio. +4. Restart SQreamDB. +5. Restart SQreamDB Acceleration Studio. diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 2ed925d4b..3b25c90ba 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -8,7 +8,9 @@ This topic explains some best practices of working with SQreamDB. See also our :ref:`monitoring_query_performance` guide for more information. +.. contents:: :local: + :depth: 1 .. _table_design_best_practices: @@ -66,7 +68,7 @@ Data sorting is an important factor in minimizing storage size and improving que * Where possible, sort columns with the lowest cardinality first. Avoid sorting ``TEXT`` columns with lengths exceeding 50 characters. -* For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`external_tables` or by using :ref:`create_table_as`. +* For longer-running queries that run on a regular basis, performance can be improved by sorting data based on the ``WHERE`` and ``GROUP BY`` parameters. Data can be sorted during insert by using :ref:`foreign_tables` or by using :ref:`create_table_as`. .. _query_best_practices: @@ -146,7 +148,7 @@ SQreamDB has a hint function called ``HIGH_SELECTIVITY``, which is a function yo The hint signals to SQreamDB that the result of the condition will be very sparse, and that it should attempt to rechunk the results into fewer, fuller chunks. -Use the high selectivity hint when you expect a predicate to filter out most values. For example, when the data is dispersed over lots of chunks (meaning that the data is :ref:`not well-clustered<data_clustering>`). +Use the high selectivity hint when you expect a predicate to filter out most values. For example, when the data is dispersed over lots of chunks (meaning that the data is :ref:`not well-clustered<cluster_by>`). For example, diff --git a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst index 06cb848ad..73d822631 100644 --- a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst +++ b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst @@ -6,9 +6,9 @@ DROP CLUSTERING KEY ``DROP CLUSTERING KEY`` drops all clustering keys in a table. -Read our :ref:`data_clustering` guide for more information. +Read our :ref:`cluster_by` guide for more information. -See also: :ref:`cluster_by`, :ref:`create_table`. +See also :ref:`create_table` Permissions From 2e01f09089e188f0c8c288b19a78679f572dcbb3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:42:32 +0200 Subject: [PATCH 1201/1892] SSO --- configuration_guides/sso.rst | 42 ++---------- releases/4.0_index.rst | 3 +- releases/4.7.rst | 120 +++++++++++++++++++++++++++++++++++ requirements.txt | 4 +- 4 files changed, 130 insertions(+), 39 deletions(-) create mode 100644 releases/4.7.rst diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 5ca074ba3..7c4ab973b 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -4,6 +4,7 @@ Single Sign-On ************** +Configuring Single Sign-On (SSO) by integrating with an identity provider (IdP) to allow users to authenticate once and seamlessly access SQreamDB as one of multiple services. .. contents:: :local: @@ -16,35 +17,6 @@ It is essential you have the following installed: * SQreamDB Acceleration Studio v5.9.0 * There should be an NGINX (or similar) service installed on your Acceleration Studio machine, which will serve as a reverse proxy. This service will accept HTTPS traffic from external sources and communicate with Studio via HTTP internally - -Setting Ping Identity -===================== - -Log in to your Ping Identity account, create a **Single Page** application, and set the following: - -1. Under **Application** > **YourAccount**, set the following: - - * **Policies** > **DaVinci** > **PingOne**, set **Sign On and Registration** - - * **Resources**, set **openid**, **profile**, **P1:read:user**, **P1:verify:user** - -2. Under **Application** > **YourAccount** > **Configuration**, create the following URLs: - - * **URLs** > Copy Authorization URL - - * Redirect URIs - -3. Under **Application** > **YourAccount**, copy Client ID and replace it in the following string: => This is 2nd part of the final URL. - -``?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user (Please note that the whole string must be copied)`` - -Connect both parts in a following manner: - -``https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/authorize?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user`` - -Logoff: - -``https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff`` Setting SQreamDB Acceleration Studio ========================================================== @@ -57,17 +29,15 @@ Setting SQreamDB Acceleration Studio "authenticationMethod": "ldap" -2. - -To set PingOne as your SSO, use either of the following methods: +2. Set Acceleration Studio to use SSO by choosing one of the following methods: - * Manually paste the authentication URL to your ``sqrea_admin_config.json`` file (recommended method) + * Manually paste your IdP URL to your ``sqream_admin_config.json`` file (recommended method) - * Set the authentication URL during an Acceleration Studio installation process by pasting the authentication URL in the questionnaire that follows the ``npm run setup`` command + * Set the IdP URL during an Acceleration Studio installation process by pasting it to the questionnaire prompted following the ``npm run setup`` command -3. In your ``sqream_legacy.json`` file, make the following adjustments: +3. In your ``sqream_legacy.json`` file, add the ``pingoneValidateUrl`` flag with the IdP URL. - * Add the ``pingoneValidateUrl`` flag along with the ______ URL + Example: .. code-block:: diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index c43fb9593..2f4213ce0 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -18,4 +18,5 @@ 4.3 4.4 4.5 - 4.6 \ No newline at end of file + 4.6 + 4.7 \ No newline at end of file diff --git a/releases/4.7.rst b/releases/4.7.rst new file mode 100644 index 000000000..dc821f613 --- /dev/null +++ b/releases/4.7.rst @@ -0,0 +1,120 @@ +.. _4.7: + +***************** +Release Notes 4.7 +***************** + +The 4.7 release notes were released on XXXXX, 2024 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS - 7.x | +| | * RHEL - 7.x / 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 51 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.1.0 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 3.0.2 | +| | * Pysqream 5.0.0 | +| | * Spark 5.0.0 | +| | * SQLoader 7.12 (compatible with v4.6.1 or later) | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- + + + +Known Issues +------------ + +* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.7 resolved Issues +--------------------------- + ++--------------------+------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+================================================================================================+ +| SQ-16727 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16592 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16534 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16531 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16397 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16038 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-16003 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-15947 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-15690 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-15570 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-14398 | | ++--------------------+------------------------------------------------------------------------------------------------+ +| SQ-13621 | | ++--------------------+------------------------------------------------------------------------------------------------+ + + +Deprecations +------------------- + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +Upgrading to Version 4.7 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + +7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/requirements.txt b/requirements.txt index d17a7f108..f007fb1da 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,8 +1,8 @@ # File: docs/requirements.txt # Defining the exact version will make sure things don't break -sphinx==5.3.0 -sphinx_rtd_theme==1.2.0 +sphinx==7.2.6 +sphinx_rtd_theme>=2.0.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From b8c27b8f0fe4849ace2d76d6402203f0c6b62d1c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 13:54:33 +0200 Subject: [PATCH 1202/1892] Update sso.rst --- configuration_guides/sso.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 7c4ab973b..4b4669650 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -25,7 +25,7 @@ Setting SQreamDB Acceleration Studio The ``authenticationMethod`` flag value should be ``ldap`` - .. code-block:: + .. code-block:: json "authenticationMethod": "ldap" @@ -39,7 +39,7 @@ Setting SQreamDB Acceleration Studio Example: - .. code-block:: + .. code-block:: json "pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" From 8b5b5618e6122e1e080ead914bddff3c77b7d539 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 15:29:52 +0200 Subject: [PATCH 1203/1892] cdc+inc SQLoader --- data_ingestion/ingesting_from_databases.rst | 2 +- .../preparing_oracle_for_data_migration.rst | 216 ++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 data_ingestion/preparing_oracle_for_data_migration.rst diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 3e4ced904..0adea6b12 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file diff --git a/data_ingestion/preparing_oracle_for_data_migration.rst b/data_ingestion/preparing_oracle_for_data_migration.rst new file mode 100644 index 000000000..226d3bc72 --- /dev/null +++ b/data_ingestion/preparing_oracle_for_data_migration.rst @@ -0,0 +1,216 @@ +.. _preparing_oracle_for_data_migration + +*********************************** +Preparing Oracle for Data Migration +*********************************** + + + +Preparing Change Data Capture Table +=================================== + +1. Prepare the data table: + + .. code-block:: sql + + -- Drop the existing table if it exists + DROP TABLE cdc_example; + + -- Create the main data table + CREATE TABLE cdc_example ( + id NUMBER(8) PRIMARY KEY, + id_name VARCHAR(8), + dttm TIMESTAMP, + f_col FLOAT + ); + + -- Insert initial data into the table + INSERT INTO cdc_example (id, id_name, dttm, f_col) VALUES (-1, 'A', CURRENT_TIMESTAMP, 0); + + -- Verify the data in the table + SELECT * FROM cdc_example ORDER BY id DESC; + + +2. Prepare the CDC catalog: + + .. code-block:: sql + + -- Drop the CDC table if it exists + DROP TABLE cdc_example_cdc; + + -- Create the CDC table to store change data + CREATE TABLE cdc_example_cdc ( + id NUMBER(8), + id_name VARCHAR(8), + row_id ROWID, + updated_dttm DATE, + type VARCHAR2(1) + ); + + -- Insert record to CDC_TABLES in the catalog + INSERT INTO SMSDW.CDC_TABLES ( + DB_NAME, + SCHEMA_NAME, + TABLE_NAME, + TABLE_NAME_FULL, + TABLE_NAME_CDC, + INC_COLUMN_NAME, + INC_COLUMN_TYPE, + LOAD_TYPE, + FREQ_TYPE, + FREQ_INTERVAL, + IS_ACTIVE, + STATUS_LOAD, + INC_GAP_VALUE + ) VALUES ( + 'ORCL', + 'QA', + 'CDC_EXAMPLE', + 'QA.CDC_EXAMPLE', + 'QA.CDC_EXAMPLE_CDC', + NULL, + NULL, + 'CDC', + NULL, + NULL, + 1, + 0, + 0 + ); + + -- Insert record to primary keys table in the catalog + INSERT INTO SMSDW.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME, + SCHEMA_NAME, + TABLE_NAME, + TABLE_NAME_FULL, + CONSTRAINT_NAME, + COLUMN_NAME, + IS_NULLABLE + ) VALUES ( + 'ORCL', + 'QA', + 'CDC_EXAMPLE', + 'QA.CDC_EXAMPLE', + NULL, + 'ID', + 0 + ); + + +3. Create trigger on data table: + + .. code-block:: sql + + -- Create a trigger on the data table to track changes and populate the CDC table + CREATE OR REPLACE TRIGGER cdc_example_tracking + AFTER UPDATE OR INSERT OR DELETE ON cdc_example + FOR EACH ROW + DECLARE + l_xtn VARCHAR2(1); + l_id INTEGER; + l_id_name VARCHAR2(1); + r_rowid ROWID; + BEGIN + l_xtn := CASE + WHEN UPDATING THEN 'U' + WHEN INSERTING THEN 'I' + WHEN DELETING THEN 'D' + END; + + l_id_name := CASE + WHEN UPDATING THEN :NEW.id_name + WHEN INSERTING THEN :NEW.id_name + WHEN DELETING THEN :OLD.id_name + END; + + l_id := CASE + WHEN UPDATING THEN :NEW.id + WHEN INSERTING THEN :NEW.id + WHEN DELETING THEN :OLD.id + END; + + r_rowid := CASE + WHEN UPDATING THEN :NEW.rowid + WHEN INSERTING THEN :NEW.rowid + WHEN DELETING THEN :OLD.rowid + END; + + INSERT INTO cdc_example_cdc ( + id, + id_name, + row_id, + updated_dttm, + type + ) VALUES ( + l_id, + l_id_name, + r_rowid, + SYSDATE, + l_xtn + ); + END; + +Preparing Incremental Table +=========================== + +1. Prepare the data table: + + .. code-block:: sql + + -- Create the data table for incremental loading + CREATE TABLE inc_example ( + ID INT PRIMARY KEY, + name VARCHAR(8) + ); + + -- Insert initial data into the table + INSERT INTO inc_example (ID, name) VALUES (1, 'A'); + + -- Verify the data in the table + SELECT * FROM inc_example; + +2. Prepare the CDC catalog: + +.. code-block:: sql + + -- Insert record into CDC_TABLES in the catalog + INSERT INTO SMSDW.CDC_TABLES ( + DB_NAME, + SCHEMA_NAME, + TABLE_NAME, + TABLE_NAME_FULL, + INC_COLUMN_NAME, + INC_COLUMN_TYPE, + LOAD_TYPE, + IS_ACTIVE, + STATUS_LOAD + ) VALUES ( + 'ORCL', + 'QA', + 'INC_EXAMPLE', + 'QA.INC_EXAMPLE', + 'ID', + 'INT', + 'INC', + 1, + 0 + ); + + -- Insert record into primary keys table in the catalog + INSERT INTO SMSDW.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME, + SCHEMA_NAME, + TABLE_NAME, + TABLE_NAME_FULL, + COLUMN_NAME, + IS_NULLABLE + ) VALUES ( + 'ORCL', + 'QA', + 'INC_EXAMPLE', + 'QA.INC_EXAMPLE', + 'ID', + 0 + ); + From 5788a77a17f07b3f0885ddb8062d15cd482e6668 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:27:18 +0200 Subject: [PATCH 1204/1892] Update preparing_oracle_for_data_migration.rst --- data_ingestion/preparing_oracle_for_data_migration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/preparing_oracle_for_data_migration.rst b/data_ingestion/preparing_oracle_for_data_migration.rst index 226d3bc72..307a2e545 100644 --- a/data_ingestion/preparing_oracle_for_data_migration.rst +++ b/data_ingestion/preparing_oracle_for_data_migration.rst @@ -4,7 +4,7 @@ Preparing Oracle for Data Migration *********************************** - +The preparation of incremental and Change Data Capture (CDC) tables is essential for efficiently tracking and managing changes to data over time, enabling streamlined data synchronization and replication. Preparing Change Data Capture Table =================================== From df3e8b86ab21bba28f48fd914071ed0dcd98a99c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 7 Mar 2024 16:39:39 +0200 Subject: [PATCH 1205/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 0adea6b12..81fa07370 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. ``names`` Method """""""""""""""" To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file From e7a09715b0d2721c9bf903da840571d2878d2209 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 10 Mar 2024 09:35:44 +0200 Subject: [PATCH 1206/1892] Update literals.rst --- reference/sql/sql_syntax/literals.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 4fc741ca4..dce24684a 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -1,8 +1,8 @@ .. _literals: -*************************** +********* Literals -*************************** +********* Literals represent constant values. @@ -213,7 +213,7 @@ Typed Literals literal :: type_name -See also :ref:`cast` for more information about supported casts. +See also :ref:`supported_casts` for more information about supported casts. Syntax Reference ------------------- From d3009bc4262c8c9b54ed0f43e479888fe88fd4cd Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 10 Mar 2024 10:07:54 +0200 Subject: [PATCH 1207/1892] Update sso.rst --- configuration_guides/sso.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 4b4669650..390c4e6b1 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -4,7 +4,7 @@ Single Sign-On ************** -Configuring Single Sign-On (SSO) by integrating with an identity provider (IdP) to allow users to authenticate once and seamlessly access SQreamDB as one of multiple services. +Here you can learn how to configure a SSO login for SQreamDB Acceleration Studio by integrating with an identity provider (IdP). A SSO authentication allows users to authenticate once and then seamlessly access SQreamDB as one of multiple services. .. contents:: :local: From 96bfb36aa8fed1941537a71bf2e39c2514e05478 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 10 Mar 2024 11:16:53 +0200 Subject: [PATCH 1208/1892] Update index.rst --- .../client_drivers/python/index.rst | 154 ++++++++++-------- 1 file changed, 87 insertions(+), 67 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index d56f2de1a..3f086434e 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -128,18 +128,23 @@ SQLAlchemy SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. -Limitation ------------ - -Please note that SQLAlchemy does not support the ``ARRAY`` data type. - .. contents:: :local: :depth: 1 +Before You Begin +---------------- + +Pysqream supports the following SQLalchemy versions: + +* SQLalchemy version 2.0.27 (recommended) * SQLalchemy version 1.4.46 -* Currently supports Pysqream 3.2.5 +Limitations +----------- + +* Supports `Pysqream 3.2.5 <https://pypi.org/project/pysqream/3.2.5/>`_ +* Does not support the ``ARRAY`` data type Creating a Standard Connection @@ -171,18 +176,20 @@ Creating a Standard Connection .. code-block:: python - import sqlalchemy as sa + import sqlalchemy as sa + from sqlalchemy.engine.url import URL - from sqlalchemy.engine.url import URL - engine_url = URL('sqream' - , username='<user_name>' - , password='<password>' - , host='<host_name>' - , port=<port_number> - , port_ssl=<port_ssl> - , database='<database_name>') - engine = sa.create_engine(engine_url,connect_args={"clustered": False, "service": "<service_name>"}) + engine_url = sa.engine.url.URL('sqream', + username='<user_name>', + password='<password>', + host='<host_name>', + port=<port_number>, + port_ssl=<port_ssl>, + database='<database_name>') + + engine = sa.create_engine(engine_url,connect_args={"clustered": False, "service": "<service_name>"}) + session = orm.sessionmaker(bind=engine)() Pulling a Table into Pandas @@ -193,21 +200,19 @@ The following example shows how to pull a table in Pandas. This example uses the .. code-block:: python import sqlalchemy as sa - - from sqlalchemy.engine.url import URL - import pandas as pd + from sqlalchemy.engine.url import URL - engine_url = URL('sqream' - , username='sqream' - , password='12345' - , host='127.0.0.1' - , port=3108 - , database='master') - engine = sa.create_engine(engine_url,connect_args={"clustered": True, "service": "admin"}) - - table_df = pd.read_sql("select * from nba", con=engine) + engine_url = sa.engine.url.URL('sqream', + username='sqream', + password='12345', + host='127.0.0.1', + port=3108, + database='master') + + engine = sa.create_engine(engine_url,connect_args={"clustered": True, "service": "admin"}) + table_df = pd.read_sql("select * from nba", con=engine) API === @@ -230,9 +235,14 @@ As before, you must import the library and create a :py:meth:`~Connection`, foll .. code-block:: python import pysqream - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) + + + con = pysqream.connect(host='127.0.0.1', + port=3108, + database='master', + username='rhendricks', + password='Tr0ub4dor&3', + clustered=True) cur = con.cursor() # Create a new cursor # The select statement: @@ -292,18 +302,22 @@ When you execute a statement, the connection object also contains metadata about The metadata is stored in the :py:attr:`Connection.description` object of the cursor: -.. code-block:: pycon +.. code-block:: python - >>> import pysqream - >>> con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - ... , username='rhendricks', password='Tr0ub4dor&3' - ... , clustered=True) - >>> cur = con.cursor() - >>> statement = 'SELECT * FROM nba' - >>> cur.execute(statement) - <pysqream.dbapi.Connection object at 0x000002EA952139B0> - >>> print(cur.description) - [('Name', 'STRING', 24, 24, None, None, True), ('Team', 'STRING', 22, 22, None, None, True), ('Number', 'NUMBER', 1, 1, None, None, True), ('Position', 'STRING', 2, 2, None, None, True), ('Age (as of 2018)', 'NUMBER', 1, 1, None, None, True), ('Height', 'STRING', 4, 4, None, None, True), ('Weight', 'NUMBER', 2, 2, None, None, True), ('College', 'STRING', 21, 21, None, None, True), ('Salary', 'NUMBER', 4, 4, None, None, True)] + import pysqream + + + con = pysqream.connect(host='127.0.0.1', + port=3108, + database='master', + username='rhendricks', + password='Tr0ub4dor&3', + clustered=True) + cur = con.cursor() + statement = 'SELECT * FROM nba' + cur.execute(statement) + print(cur.description) + # [('Name', 'STRING', 24, 24, None, None, True), ('Team', 'STRING', 22, 22, None, None, True), ('Number', 'NUMBER', 1, 1, None, None, True), ('Position', 'STRING', 2, 2, None, None, True), ('Age (as of 2018)', 'NUMBER', 1, 1, None, None, True), ('Height', 'STRING', 4, 4, None, None, True), ('Weight', 'NUMBER', 2, 2, None, None, True), ('College', 'STRING', 21, 21, None, None, True), ('Salary', 'NUMBER', 4, 4, None, None, True)] You can fetch a list of column names by iterating over the ``description`` list: @@ -327,10 +341,15 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea from datetime import date, datetime from time import time - con = pysqream.connect(host='127.0.0.1', port=3108, database='master' - , username='rhendricks', password='Tr0ub4dor&3' - , clustered=True) - , cur = con.cursor() + + con = pysqream.connect(host='127.0.0.1', + port=3108, + database='master', + username='rhendricks', + password='Tr0ub4dor&3', + clustered=True) + + cur = con.cursor() 2. Create a table for loading: @@ -339,11 +358,15 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text(12), ss text, dt date, dtt datetime)' cur.execute(create) -3. Load your data into table using the ``INSERT`` command. +3. Create a session: - :: + .. code-block:: python -4. Create dummy data matching the table you created: + session = orm.sessionmaker(bind=engine)() + +4. Load your data into table using the ``INSERT`` command. + +5. Create dummy data matching the table you created: .. code-block:: python @@ -351,7 +374,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea row_count = 10**4 -5. Get a new cursor: +6. Get a new cursor: .. code-block:: python @@ -360,13 +383,13 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea cur.executemany(insert, [data] * row_count) print (f"Total insert time for {row_count} rows: {time() - start} seconds") -6. Close this cursor: +7. Close this cursor: .. code-block:: python cur.close() -7. Verify that the data was inserted correctly: +8. Verify that the data was inserted correctly: .. code-block:: python @@ -375,13 +398,13 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea result = cur.fetchall() # `fetchall` collects the entire data set print (f"Count of inserted rows: {result[0][0]}") -8. Close the cursor: +9. Close the cursor: .. code-block:: python cur.close() -9. Close the connection: +10. Close the connection: .. code-block:: python @@ -419,12 +442,12 @@ This section shows how to use the ORM to create and populate tables from Python .. code-block:: python employees = sa.Table( - 'employees' - , metadata - , sa.Column('id', sa.Integer) - , sa.Column('name', sa.TEXT(32)) - , sa.Column('lastname', sa.TEXT(32)) - , sa.Column('salary', sa.Float) + 'employees', + metadata, + sa.Column('id', sa.Integer), + sa.Column('name', sa.TEXT(32)), + sa.Column('lastname', sa.TEXT(32)), + sa.Column('salary', sa.Float) ) The ``create_all()`` function uses the SQream engine object. @@ -436,17 +459,14 @@ This section shows how to use the ORM to create and populate tables from Python metadata.create_all(engine) 5. Populate your table. - - :: 6. Build the data rows: .. code-block:: python - insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks', 'salary': 12000.75} - ,{'id': 3, 'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0} - ,{'id': 8, 'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40} - ] + insert_data = [ {'id': 1, 'name': 'Richard','lastname': 'Hendricks', 'salary': 12000.75}, + {'id': 3, 'name': 'Bertram', 'lastname': 'Gilfoyle', 'salary': 8400.0}, + {'id': 8, 'name': 'Donald', 'lastname': 'Dunn', 'salary': 6500.40}] 7. Build the ``INSERT`` command: @@ -458,6 +478,6 @@ This section shows how to use the ORM to create and populate tables from Python .. code-block:: python - result = engine.execute(ins) + result = session.execute(ins) For more information, see the :ref:`python_api_reference_guide`. From 6dfc5d11d9aa7ac82225ff9aa08d37398b377995 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 10 Mar 2024 13:48:01 +0200 Subject: [PATCH 1209/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 3f086434e..f2bdbe212 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -122,7 +122,6 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins $ pip3.9 install pysqream pysqream-sqlalchemy -U - SQLAlchemy ========== From 343edd1dc3b0e3ba70139025e325a7d1ee37718f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 11:49:06 +0200 Subject: [PATCH 1210/1892] Update ldap.rst --- configuration_guides/ldap.rst | 161 ++++++++++++++++------------------ 1 file changed, 77 insertions(+), 84 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 8b5a18812..6c18da2d3 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -1,80 +1,40 @@ .. _ldap: -******************** +**** LDAP -******************** +**** +Lightweight Directory Access Protocol (LDAP) is an authentication management service used with Microsoft Active Directory and other directory services. -Lightweight Directory Access Protocol (LDAP) is an authentication management service used with Microsoft Active Directory and other directory services. Once LDAP authentication has been configured for SQream, authorization for all existing and newly added roles must be handled by the LDAP server, except for the initial system deployment ``sqream`` role, which was immediately given full control permissions when SQream was initially deployed. - -Before integrating SQream with LDAP consider the following: - -* If SQream DB is being installed within an environment where LDAP is already configured, it is best practice to ensure that the newly created SQream role names are consistent with existing LDAP user names. - -* If SQream DB has been installed and LDAP has not yet been integrated with SQream, it is best practice to ensure that the newly created LDAP user names are consistent with existing SQream role names. Previously existing SQream roles that were mistakenly not configured in LDAP or that have names which are different than in LDAP, will be recreated in SQream as roles that cannot log in, have no permissions, and have no default schema. +Once LDAP has been configured as an authentication service for SQreamDB, authentication for all existing and newly added roles is handled by an LDAP server. The exception for this rule is the out-of-the-box administrative ``sqream`` role, which will always use the conventional SQreamDB authentication instead LDAP authentication. .. contents:: :local: :depth: 1 -Configuring SQream roles -======================== - -Follow this procedure if you already have LDAP configured for your environment. - -1. Create a new role: - -.. code-block:: postgres - - CREATE ROLE <new_role>; - -2. Grant the new role login permission: - -.. code-block:: postgres - - GRANT LOGIN TO <new_role>; - -3. Grant the new role ``CONNECT`` permission: - -.. code-block:: postgres +Before You Begin +================ - GRANT CONNECT ON DATABASE <my_database> TO <new_role>; +* If SQreamDB is being installed within an environment where LDAP is already configured, it is best practice to ensure that the newly created SQreamDB role names are consistent with existing LDAP user names. -You may also wish to :ref:`rename SQream roles<rename_role>` so that they are consistent with existing LDAP user names. +* When setting up LDAP for an existing SQreamDB installation, it's recommended to ensure that newly created LDAP usernames match existing SQreamDB role names. If SQreamDB roles were not configured in LDAP or have different names, they'll be recreated in SQreamDB as roles without login capabilities, permissions, or default schemas. +Setting LDAP Authentication Management +====================================== -Configuring LDAP Authentication -=============================== +To set LDAP authentication for SQreamDB, choose one of the following configuration methods: .. contents:: :local: :depth: 1 -Configuration Methods ---------------------- - -To configure LDAP authentication for SQream, you may choose one of the following configuration methods: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Method - - Description - * - Basic method - - A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given access to SQream. - * - Advanced method - - This approach allows for compartmentalization, which means that users can be grouped into categories, and each category can be assigned or denied access to SQream. This allows administrators to control access to SQream. - - - Basic Method ------------ -Flag Attributes -~~~~~~~~~~~~~~~ +A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given access to SQream. -To enable basic LDAP authentication, configure the following cluster flag attributes using the ``ALTER SYSTEM SET`` command: +Flag Attributes +^^^^^^^^^^^^^^^ .. list-table:: :widths: auto @@ -99,54 +59,52 @@ To enable basic LDAP authentication, configure the following cluster flag attrib Basic Method Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^ Only roles with admin privileges or higher may enable LDAP Authentication. -**Procedure** - 1. Set the ``authenticationMethod`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; 2. Set the ``ldapIpAddress`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapIpAddress = '<ldaps://...>'; 3. Set the ``ldapPrefix`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapPrefix = '<DN_binding_string_prefix>='; 4. Set the ``ldapSuffix`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapSuffix = '<DN_binding_string_suffix>'; 5. To set the ``ldapPort`` attribute (Optional), run: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapPort = <port_number> 6. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapConnTimeoutSec = <15>; 7. Restart all sqreamd servers. Example -~~~~~~~ +^^^^^^^ -After completing the setup above, we can try to bind to a user by a distinguished name. For example, if the DN of the user is: +After completing the setup above, we can bind to a user by a distinguished name. For example, if the DN of the user is: .. code-block:: postgres @@ -169,10 +127,10 @@ Logging in will be possible using the username ElonMusk using sqream client Advanced Method --------------- -Flag Attributes -~~~~~~~~~~~~~~~ +This method lets users be grouped into categories. Each category can then be given or denied access to SQreamDB, giving administrators control over access. -To enable advanced LDAP authentication, configure the following cluster flag attributes using the ``ALTER SYSTEM SET`` command: +Flag Attributes +^^^^^^^^^^^^^^^ .. list-table:: :widths: auto @@ -201,77 +159,112 @@ To enable advanced LDAP authentication, configure the following cluster flag att * - ``ldapSearchFilter`` - Filters ``ldapAdvancedMode`` authentication. ``ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)';`` + +Preparing LDAP Users +^^^^^^^^^^^^^^^^^^^^ + +If installing SQreamDB in an environment with LDAP already set up, it's best to ensure the new SQreamDB role names match the existing LDAP user names. + +It is also recommended to: + +* Group Active Directory users so that they may be filtered during setup, using the ``ldapSearchFilter`` flag. + +* Provide a unique attribute to each user name, such as an employee ID, to be easily searched for when using the ``ldapSearchAttribute`` flag. + +Preparing SQreamDB Roles +^^^^^^^^^^^^^^^^^^^^^^^^ + +For a SQreamDB admin to be able to manage role permissions, for every Active Directory user connecting to SQreamDB, there must be an existing SQreamDb role name that is consistent with existing LDAP user names. + +You may either :ref:`rename SQream roles<rename_role>` or create new roles, such as in the following example: + +1. Create a new role: + + .. code-block:: postgres + + CREATE ROLE role12345; + +2. Grant the new role login permission: + + .. code-block:: postgres + + GRANT LOGIN TO role12345; + +3. Grant the new role ``CONNECT`` permission: + + .. code-block:: postgres + + GRANT CONNECT ON DATABASE master TO role12345; + Advanced Method Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Only roles with admin privileges and higher may enable LDAP Authentication. -**Procedure** - 1. Set the ``authenticationMethod`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; 2. Set the ``ldapAdvancedMode`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapAdvancedMode = true; 3. Set the ``ldapIpAddress`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapIpAddress = '<ldaps://<IpAddress>'; 4. Set the ``ldapBindDn`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapBindDn = <binding_user_DN>; 5. Set the ``ldapBindDnPassword`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapBindDnPassword = '<binding_user_password>'; 6. Set the ``ldapBaseDn`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapBaseDn = '<search_root_DN>'; 7. Set the ``ldapSearchAttribute`` attribute: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapSearchAttribute = '<search_attribute>'; 8. To set the ``ldapSearchFilter`` attribute (Optional), run: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)'; 9. To set the ``ldapPort`` attribute (Optional), run: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapPort = <port_number> 10. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET ldapConnTimeoutSec = <15>; 11. Restart all sqreamd servers. Example -~~~~~~~ +^^^^^^^ After completing the setup above we can try to bind to a user by locating it by one of its unique attributes. @@ -315,13 +308,13 @@ Logging in will be possible using the username elonm using sqream client Disabling LDAP Authentication ------------------------------ +============================= To disable LDAP authentication and configure sqream authentication: 1. Execute the following syntax: -.. code-block:: postgres + .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'sqream'; From 77ccef01a78888db45e7687e6d8c51b34e47ffa5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 12:05:31 +0200 Subject: [PATCH 1211/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index d65eff6b8..bfb85acf3 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -122,7 +122,7 @@ The following table shows SQreamDB's recommended metadata server specifications: * - Component - Type * - Server - - + - Dell R750, Dell R940xa, HP ProLiant DL380 Gen10 or similar (Intel only) * - Processors - 2x Intel Xeon Gold 6342 2.8 Ghz 24C processors or similar * - RAM From 206b7f28e2789982f863defd64f8937a1f5ebf34 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 13:52:26 +0200 Subject: [PATCH 1212/1892] Update sso.rst --- configuration_guides/sso.rst | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 390c4e6b1..1518f591f 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -19,9 +19,9 @@ It is essential you have the following installed: * There should be an NGINX (or similar) service installed on your Acceleration Studio machine, which will serve as a reverse proxy. This service will accept HTTPS traffic from external sources and communicate with Studio via HTTP internally Setting SQreamDB Acceleration Studio -========================================================== +==================================== -1. Set :ref:`ldap` as your authentication management service. +1. Set :ref:`ldap` to be your authentication management service. The ``authenticationMethod`` flag value should be ``ldap`` @@ -29,19 +29,23 @@ Setting SQreamDB Acceleration Studio "authenticationMethod": "ldap" -2. Set Acceleration Studio to use SSO by choosing one of the following methods: - - * Manually paste your IdP URL to your ``sqream_admin_config.json`` file (recommended method) - - * Set the IdP URL during an Acceleration Studio installation process by pasting it to the questionnaire prompted following the ``npm run setup`` command - -3. In your ``sqream_legacy.json`` file, add the ``pingoneValidateUrl`` flag with the IdP URL. +2. In your ``sqream_legacy.json`` file, add the following flags: + * ``SSOValidateUrl`` flag with the IdP URL + * ``mfaLogoutUrl`` flag with the logout URL + Example: .. code-block:: json - "pingoneValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" + "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" + "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" + +3. Set Acceleration Studio to use SSO by manually pasting your IdP URL to your ``sqream_admin_config.json`` file. + + Alternatively, you can set the IdP URL during an Acceleration Studio installation process by pasting it to the questionnaire prompted following the ``npm run setup`` command, but this approach is less recommended. + + 4. Restart SQreamDB. 5. Restart SQreamDB Acceleration Studio. From 90487306fd199e06c4496196401c01613ad8b396 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:02:33 +0200 Subject: [PATCH 1213/1892] sso --- architecture/concurrency_and_scaling_in_sqream.rst | 4 ++-- configuration_guides/sso.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 740a5ff10..342f9f28c 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -105,7 +105,7 @@ The provided examples assume a configuration with 2T of RAM, 8 workers running o Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: -.. code-block:: console +.. code-block:: json { “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, @@ -121,7 +121,7 @@ Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: Configuring the ``spoolMemoryGB`` using the legacy configuration file: -.. code-block:: console +.. code-block:: json { "diskSpaceMinFreePercent": 10, diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 1518f591f..2dc0eb2fc 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -39,7 +39,7 @@ Setting SQreamDB Acceleration Studio .. code-block:: json "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" - "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" + "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" 3. Set Acceleration Studio to use SSO by manually pasting your IdP URL to your ``sqream_admin_config.json`` file. From 975353aff53e7804123fab7dc1a21e89f3580f41 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:11:28 +0200 Subject: [PATCH 1214/1892] Update concurrency_and_scaling_in_sqream.rst --- .../concurrency_and_scaling_in_sqream.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 342f9f28c..9f5b2fd69 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -108,15 +108,15 @@ Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: .. code-block:: json { - “cluster”: “/home/test_user/sqream_testing_temp/sqreamdb”, - “gpu”: 0, - “licensePath”: “home/test_user/SQream/tests/license.enc”, - “machineIP”: “127.0.0.1”, - “metadataServerIp”: 127.0.0.1, - “metadataServerPort”: 3105, - “port”: 5000, - “useConfigIP”: true, - “limitQueryMemoryGB" : 225, + "cluster”: "/home/test_user/sqream_testing_temp/sqreamdb", + "gpu": 0, + "licensePath": "home/test_user/SQream/tests/license.enc", + "machineIP": "127.0.0.1", + "metadataServerIp": 127.0.0.1, + "metadataServerPort": 3105, + "port": 5000, + "useConfigIP": true, + "limitQueryMemoryGB" : 225, } Configuring the ``spoolMemoryGB`` using the legacy configuration file: From a5b14fa556e7bc33616394b36368be7e0dcb49df Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:15:26 +0200 Subject: [PATCH 1215/1892] Update concurrency_and_scaling_in_sqream.rst --- architecture/concurrency_and_scaling_in_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index 9f5b2fd69..b7cc3e76c 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -108,7 +108,7 @@ Configuring the ``limitQueryMemoryGB`` using the Worker configuration file: .. code-block:: json { - "cluster”: "/home/test_user/sqream_testing_temp/sqreamdb", + "cluster": "/home/test_user/sqream_testing_temp/sqreamdb", "gpu": 0, "licensePath": "home/test_user/SQream/tests/license.enc", "machineIP": "127.0.0.1", From 807edde75b836d5f323ccb89571206fe4f96479d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:26:46 +0200 Subject: [PATCH 1216/1892] Update sso.rst --- configuration_guides/sso.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 2dc0eb2fc..dfb6fcf73 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -25,7 +25,7 @@ Setting SQreamDB Acceleration Studio The ``authenticationMethod`` flag value should be ``ldap`` - .. code-block:: json + .. code-block:: json "authenticationMethod": "ldap" @@ -36,8 +36,8 @@ Setting SQreamDB Acceleration Studio Example: - .. code-block:: json - + .. code-block:: json + "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" From 3480122f2eb28245c39e427bf4a51bb4632fb5ca Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:29:25 +0200 Subject: [PATCH 1217/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index f2bdbe212..df6aed69e 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -131,14 +131,6 @@ SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the :local: :depth: 1 -Before You Begin ----------------- - -Pysqream supports the following SQLalchemy versions: - -* SQLalchemy version 2.0.27 (recommended) -* SQLalchemy version 1.4.46 - Limitations ----------- From 51cce823f96fdcf43ebcdecc7cdb0a7bf476388c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 14:38:18 +0200 Subject: [PATCH 1218/1892] sqlalchemy 2 --- connecting_to_sqream/client_drivers/python/index.rst | 3 ++- releases/4.6.rst | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index df6aed69e..3528d9eb5 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -110,7 +110,7 @@ Installing via PIP without an internet connection #Install all packages with --no-index --find-links . python3 -m pip install *.whl -U --no-index --find-links . python3.9 -m pip install pysqream-5.0.0.zip -U --no-index --find-links . - python3.9 -m pip install pysqream-sqlalchemy-0.8.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-sqlalchemy-1.0.zip -U --no-index --find-links . Upgrading an Existing Installation ---------------------------------- @@ -121,6 +121,7 @@ The Python drivers are updated periodically. To upgrade an existing pysqream ins $ pip3.9 install pysqream pysqream-sqlalchemy -U +.. _sqlalchemy: SQLAlchemy ========== diff --git a/releases/4.6.rst b/releases/4.6.rst index acea25777..ad58f2a8a 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -47,6 +47,8 @@ New Features and Enhancements ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. +► Our :ref:`Pysqream<sqlalchemy>` connector now support SQLAlchemy version 2.0.27. + Known Issues ------------ From bb2419d1f9209940a00e762b3a2351fa6db2a9d7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 15:32:19 +0200 Subject: [PATCH 1219/1892] Update sso.rst --- configuration_guides/sso.rst | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index dfb6fcf73..01c1dda04 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -17,36 +17,36 @@ It is essential you have the following installed: * SQreamDB Acceleration Studio v5.9.0 * There should be an NGINX (or similar) service installed on your Acceleration Studio machine, which will serve as a reverse proxy. This service will accept HTTPS traffic from external sources and communicate with Studio via HTTP internally +* You have :ref:`ldap` set as your authentication management service. Setting SQreamDB Acceleration Studio ==================================== -1. Set :ref:`ldap` to be your authentication management service. - - The ``authenticationMethod`` flag value should be ``ldap`` +#. In your ``sqream_legacy.json`` file, add the ``SSOValidateUrl`` flag with your IdP URL. + Example: + .. code-block:: json - "authenticationMethod": "ldap" + "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" -2. In your ``sqream_legacy.json`` file, add the following flags: +#. Set Acceleration Studio to use SSO by adding the following flags to your ``sqream_admin_config.json`` file: + + * ``mfaRedirectUrl`` flag with your redirect URL + * ``mfaLogoutUrl`` flag with your logout URL - * ``SSOValidateUrl`` flag with the IdP URL - * ``mfaLogoutUrl`` flag with the logout URL - Example: .. code-block:: json - - "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" - "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" - -3. Set Acceleration Studio to use SSO by manually pasting your IdP URL to your ``sqream_admin_config.json`` file. + + "mfaRedirectUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/authorize?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user", + "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" - Alternatively, you can set the IdP URL during an Acceleration Studio installation process by pasting it to the questionnaire prompted following the ``npm run setup`` command, but this approach is less recommended. + If Acceleration Studio is not yet installed, you can set both URLs during its installation process. + + +#. Restart SQreamDB. - -4. Restart SQreamDB. -5. Restart SQreamDB Acceleration Studio. +#. Restart SQreamDB Acceleration Studio. From 346b5de61b8324aab93b4f6883c12058b4fddeca Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 11 Mar 2024 16:26:56 +0200 Subject: [PATCH 1220/1892] Update create_schema.rst --- .../sql/sql_statements/ddl_commands/create_schema.rst | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_schema.rst b/reference/sql/sql_statements/ddl_commands/create_schema.rst index cba68bc73..dfa471dd3 100644 --- a/reference/sql/sql_statements/ddl_commands/create_schema.rst +++ b/reference/sql/sql_statements/ddl_commands/create_schema.rst @@ -24,7 +24,8 @@ The **CREATE SCHEMA** statement can be used to query tables from different schem .. code-block:: postgres - select <schema_name>.table_name.column_name from <schema_name>.table_name + SELECT <schema_name>.table_name.column_name + FROM <schema_name>.table_name See also: :ref:`drop_schema`, :ref:`alter_default_schema`, :ref:`rename_schema`. @@ -40,11 +41,11 @@ The following example shows the correct syntax for creating a schema: .. code-block:: postgres - create_schema_statement ::= - CREATE SCHEMA schema_name - ; + CREATE SCHEMA [database_name.]schema_name - schema_name ::= identifier + + schema_name ::= identifier + database_name ::= identifier Parameters From 3aa68b493b39ee0e5d550a775977a07b2aaf06a4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Mar 2024 10:09:49 +0200 Subject: [PATCH 1221/1892] Update sso.rst --- configuration_guides/sso.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 01c1dda04..57f6b5648 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -22,13 +22,13 @@ It is essential you have the following installed: Setting SQreamDB Acceleration Studio ==================================== -#. In your ``sqream_legacy.json`` file, add the ``SSOValidateUrl`` flag with your IdP URL. +#. In your ``sqream_legacy.json`` file, add the ``ssoValidateUrl`` flag with your IdP URL. Example: .. code-block:: json - "SSOValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" + "ssoValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" #. Set Acceleration Studio to use SSO by adding the following flags to your ``sqream_admin_config.json`` file: From b9b348dd75ea165d7ab27b236ce179c2b0a0c5e6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:44:58 +0200 Subject: [PATCH 1222/1892] Maintenance --- configuration_guides/block_new_varchar_objects.rst | 5 +++-- configuration_guides/cache_persistent_dir.rst | 5 +++-- configuration_guides/cache_ram_gb.rst | 5 +++-- configuration_guides/compiler_gets_only_ufs.rst | 5 +++-- configuration_guides/csv_limit_row_length.rst | 5 +++-- configuration_guides/cuda_mem_cpy_synchronous.rst | 5 +++-- configuration_guides/developer_mode.rst | 5 +++-- configuration_guides/enable_device_debug_messages.rst | 5 +++-- configuration_guides/enable_log_debug.rst | 7 ++++--- configuration_guides/enable_nv_prof_markers.rst | 5 +++-- configuration_guides/end_log_message.rst | 5 +++-- configuration_guides/extent_storage_file_size_mb.rst | 5 +++-- configuration_guides/gather_mem_stat.rst | 5 +++-- configuration_guides/graceful_shutdown.rst | 5 +++-- configuration_guides/increase_chunk_size_before_reduce.rst | 5 +++-- configuration_guides/increase_mem_factors.rst | 7 ++++--- configuration_guides/limit_query_memory_gb.rst | 5 +++-- configuration_guides/machine_ip.rst | 5 +++-- .../max_avg_blob_size_to_compress_on_gpu.rst | 5 +++-- configuration_guides/max_connection_inactivity_seconds.rst | 4 ++-- configuration_guides/memory_reset_trigger_mb.rst | 5 +++-- configuration_guides/mt_read.rst | 5 +++-- configuration_guides/mt_read_workers.rst | 5 +++-- configuration_guides/orc_implicit_casts.rst | 5 +++-- configuration_guides/statement_lock_timeout.rst | 5 +++-- configuration_guides/use_config_ip.rst | 5 +++-- configuration_guides/use_legacy_decimal_literals.rst | 5 +++-- configuration_guides/use_legacy_string_literals.rst | 5 +++-- connecting_to_sqream/client_drivers/jdbc/index.rst | 4 ---- 29 files changed, 85 insertions(+), 62 deletions(-) diff --git a/configuration_guides/block_new_varchar_objects.rst b/configuration_guides/block_new_varchar_objects.rst index a64ff7995..d78fa8e98 100644 --- a/configuration_guides/block_new_varchar_objects.rst +++ b/configuration_guides/block_new_varchar_objects.rst @@ -1,8 +1,9 @@ .. _block_new_varchar_objects: -************************* +**************************** Blocking New VARCHAR Objects -************************* +**************************** + The ``blockNewVarcharObjects`` flag disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. The following describes the ``blockNewVarcharObjects`` flag: diff --git a/configuration_guides/cache_persistent_dir.rst b/configuration_guides/cache_persistent_dir.rst index c3e298189..fbc7eb147 100644 --- a/configuration_guides/cache_persistent_dir.rst +++ b/configuration_guides/cache_persistent_dir.rst @@ -1,8 +1,9 @@ .. _cache_persistent_dir: -************************* +****************************************************** Setting Spool Persistent Saved File Directory Location -************************* +****************************************************** + The ``cachePersistentDir`` flag sets the persistent directory location for the spool to save files on. The following describes the ``cachePersistentDir`` flag: diff --git a/configuration_guides/cache_ram_gb.rst b/configuration_guides/cache_ram_gb.rst index 31d56613b..bf91ddc21 100644 --- a/configuration_guides/cache_ram_gb.rst +++ b/configuration_guides/cache_ram_gb.rst @@ -1,8 +1,9 @@ .. _cache_ram_gb: -************************* +***************************** Setting InMemory Spool Memory -************************* +***************************** + The ``cacheRamGB`` flag sets the amount of memory (GB) to be used by Spool InMemory. The following describes the ``cacheRamGB`` flag: diff --git a/configuration_guides/compiler_gets_only_ufs.rst b/configuration_guides/compiler_gets_only_ufs.rst index 1190adc3e..d7d3d9151 100644 --- a/configuration_guides/compiler_gets_only_ufs.rst +++ b/configuration_guides/compiler_gets_only_ufs.rst @@ -1,8 +1,9 @@ .. _compiler_gets_only_ufs: -************************* +************************************* Limiting Runtime to Utility Functions -************************* +************************************* + The ``compilerGetsOnlyUFs`` flag sets the runtime to pass only utility functions names to the compiler. The following describes the ``compilerGetsOnlyUFs`` flag: diff --git a/configuration_guides/csv_limit_row_length.rst b/configuration_guides/csv_limit_row_length.rst index 03f31c697..a4558f923 100644 --- a/configuration_guides/csv_limit_row_length.rst +++ b/configuration_guides/csv_limit_row_length.rst @@ -1,8 +1,9 @@ .. _csv_limit_row_length: -************************* +****************************** Setting Maximum CSV Row Length -************************* +****************************** + The ``csvLimitRowLength`` flag sets the maximum supported CSV row length. The following describes the ``csvLimitRowLength`` flag: diff --git a/configuration_guides/cuda_mem_cpy_synchronous.rst b/configuration_guides/cuda_mem_cpy_synchronous.rst index 81e762071..adbedce48 100644 --- a/configuration_guides/cuda_mem_cpy_synchronous.rst +++ b/configuration_guides/cuda_mem_cpy_synchronous.rst @@ -1,8 +1,9 @@ .. _cuda_mem_cpy_synchronous: -************************* +**************************** Indicating GPU Synchronicity -************************* +**************************** + The ``CudaMemcpySynchronous`` flag indicates if copying from/to GPU is synchronous. The following describes the ``CudaMemcpySynchronous`` flag: diff --git a/configuration_guides/developer_mode.rst b/configuration_guides/developer_mode.rst index fbb6c0cec..7b78e2806 100644 --- a/configuration_guides/developer_mode.rst +++ b/configuration_guides/developer_mode.rst @@ -1,8 +1,9 @@ .. _developer_mode: -************************* +********************************** Enabling Modification of R&D Flags -************************* +********************************** + The ``developerMode`` flag enables modifying R&D flags. The following describes the ``developerMode`` flag: diff --git a/configuration_guides/enable_device_debug_messages.rst b/configuration_guides/enable_device_debug_messages.rst index c7d340b65..ac9ddb09f 100644 --- a/configuration_guides/enable_device_debug_messages.rst +++ b/configuration_guides/enable_device_debug_messages.rst @@ -1,8 +1,9 @@ .. _enable_device_debug_messages: -************************* +**************************************** Checking for Post-Production CUDA Errors -************************* +**************************************** + The ``enableDeviceDebugMessages`` flag checks for CUDA errors after producing each chunk. The following describes the ``enableDeviceDebugMessages`` flag: diff --git a/configuration_guides/enable_log_debug.rst b/configuration_guides/enable_log_debug.rst index 1566c4882..6706de6a9 100644 --- a/configuration_guides/enable_log_debug.rst +++ b/configuration_guides/enable_log_debug.rst @@ -1,8 +1,9 @@ .. _enable_log_debug: -************************* -Enabling Modification of clientLogger_debug File -************************* +************************************************ +Enabling Modification of ClientLogger Debug File +************************************************ + The ``enableLogDebug`` flag enables creating and logging in the **clientLogger_debug** file. The following describes the ``enableLogDebug`` flag: diff --git a/configuration_guides/enable_nv_prof_markers.rst b/configuration_guides/enable_nv_prof_markers.rst index 9edbf28e3..6d1d0422d 100644 --- a/configuration_guides/enable_nv_prof_markers.rst +++ b/configuration_guides/enable_nv_prof_markers.rst @@ -1,8 +1,9 @@ .. _enable_nv_prof_markers: -************************* +************************************** Activating the NVidia Profiler Markers -************************* +************************************** + The ``enableNvprofMarkers`` flag activates the NVidia Profiler (nvprof) markers. The following describes the ``enableNvprofMarkers`` flag: diff --git a/configuration_guides/end_log_message.rst b/configuration_guides/end_log_message.rst index 46a1c71ae..60df1a6a3 100644 --- a/configuration_guides/end_log_message.rst +++ b/configuration_guides/end_log_message.rst @@ -1,8 +1,9 @@ .. _end_log_message: -************************* +************************************ Appending String at End of Log Lines -************************* +************************************ + The ``endLogMessage`` flag appends a string at the end of each log line. The following describes the ``endLogMessage`` flag: diff --git a/configuration_guides/extent_storage_file_size_mb.rst b/configuration_guides/extent_storage_file_size_mb.rst index dd4cddec7..cdbce6b6c 100644 --- a/configuration_guides/extent_storage_file_size_mb.rst +++ b/configuration_guides/extent_storage_file_size_mb.rst @@ -1,8 +1,9 @@ .. _extent_storage_file_size_mb: -************************* +*********************************************** Setting Minimum Extent Size for Bulk Table Data -************************* +*********************************************** + The ``extentStorageFileSizeMB`` flag sets the minimum size in mebibytes of extents for bulk table data. The following describes the ``extentStorageFileSizeMB`` flag: diff --git a/configuration_guides/gather_mem_stat.rst b/configuration_guides/gather_mem_stat.rst index 802e12b1f..19756ff2a 100644 --- a/configuration_guides/gather_mem_stat.rst +++ b/configuration_guides/gather_mem_stat.rst @@ -1,8 +1,9 @@ .. _gather_mem_stat: -************************* +************************************************* Monitoring and Printing Pinned Allocation Reports -************************* +************************************************* + The ``gatherMemStat`` flag monitors all pinned allocations and all **memcopies** to and from a device, and prints a report of pinned allocations that were not **memcopied** to and from the device using the **dump_pinned_misses** utility function. The following describes the ``gatherMemStat`` flag: diff --git a/configuration_guides/graceful_shutdown.rst b/configuration_guides/graceful_shutdown.rst index 8b4f4b55c..f136f87d7 100644 --- a/configuration_guides/graceful_shutdown.rst +++ b/configuration_guides/graceful_shutdown.rst @@ -1,8 +1,9 @@ .. _graceful_shutdown: -************************* +************************************ Setting the Graceful Server Shutdown -************************* +************************************ + The ``defaultGracefulShutdownTimeoutMinutes`` flag is used for setting the amount of time to pass before SQream performs a graceful server shutdown. The following describes the ``defaultGracefulShutdownTimeoutMinutes`` flag: diff --git a/configuration_guides/increase_chunk_size_before_reduce.rst b/configuration_guides/increase_chunk_size_before_reduce.rst index 982d3db35..a817c7bff 100644 --- a/configuration_guides/increase_chunk_size_before_reduce.rst +++ b/configuration_guides/increase_chunk_size_before_reduce.rst @@ -1,8 +1,9 @@ .. _increase_chunk_size_before_reduce: -************************* +******************************************* Increasing Chunk Size to Reduce Query Speed -************************* +******************************************* + The ``increaseChunkSizeBeforeReduce`` flag increases the chunk size to reduce query speed. The following describes the ``increaseChunkSizeBeforeReduce`` flag: diff --git a/configuration_guides/increase_mem_factors.rst b/configuration_guides/increase_mem_factors.rst index 166a57e14..f3421a7b5 100644 --- a/configuration_guides/increase_mem_factors.rst +++ b/configuration_guides/increase_mem_factors.rst @@ -1,8 +1,9 @@ .. _increase_mem_factors: -************************* -Adding Rechunker before Expensing Chunk Producer -************************* +************************************************ +Adding Rechunker Before Expensing Chunk Producer +************************************************ + The ``increaseMemFactors`` flag adds a rechunker before expensive chunk producer. The following describes the ``increaseMemFactors`` flag: diff --git a/configuration_guides/limit_query_memory_gb.rst b/configuration_guides/limit_query_memory_gb.rst index 7099674f2..7a27bd3ee 100644 --- a/configuration_guides/limit_query_memory_gb.rst +++ b/configuration_guides/limit_query_memory_gb.rst @@ -1,8 +1,9 @@ .. _limit_query_memory_gb: -************************* +************************************* Setting Query Memory Processing Limit -************************* +************************************* + The ``limitQueryMemoryGB`` flag prevents a query from processing more memory than the defined value. The following describes the ``limitQueryMemoryGB`` flag: diff --git a/configuration_guides/machine_ip.rst b/configuration_guides/machine_ip.rst index 66a8a9a10..56ecb8edb 100644 --- a/configuration_guides/machine_ip.rst +++ b/configuration_guides/machine_ip.rst @@ -1,8 +1,9 @@ .. _machine_ip: -************************* +************************************* Enabling Manually Setting Reported IP -************************* +************************************* + The ``machineIP`` flag enables you to manually set the reported IP. The following describes the ``machineIP`` flag: diff --git a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst index 1081e0225..c3e026835 100644 --- a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst +++ b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst @@ -1,8 +1,9 @@ .. _max_avg_blob_size_to_compress_on_gpu: -************************* +*************************************** Setting CPU to Compress Defined Columns -************************* +*************************************** + The ``maxAvgBlobSizeToCompressOnGpu`` flag sets the CPU to compress columns with size above <flag value> * <row count>. The following describes the ``maxAvgBlobSizeToCompressOnGpu`` flag: diff --git a/configuration_guides/max_connection_inactivity_seconds.rst b/configuration_guides/max_connection_inactivity_seconds.rst index 31a4f36c7..195660df8 100644 --- a/configuration_guides/max_connection_inactivity_seconds.rst +++ b/configuration_guides/max_connection_inactivity_seconds.rst @@ -1,8 +1,8 @@ .. _max_connection_inactivity_seconds: -******************************** +********************************* MAX CONNECTION INACTIVITY SECONDS -******************************** +********************************* The ``maxConnectionInactivitySeconds`` determines the maximum period of session idleness, after which the connection is terminated. diff --git a/configuration_guides/memory_reset_trigger_mb.rst b/configuration_guides/memory_reset_trigger_mb.rst index bb8a383bb..def2c02df 100644 --- a/configuration_guides/memory_reset_trigger_mb.rst +++ b/configuration_guides/memory_reset_trigger_mb.rst @@ -1,8 +1,9 @@ .. _memory_reset_trigger_mb: -************************* +*********************************** Setting Memory Used to Abort Server -************************* +*********************************** + The ``memoryResetTriggerMB`` flag sets the size of memory used during a query to trigger aborting the server. The following describes the ``memoryResetTriggerMB`` flag: diff --git a/configuration_guides/mt_read.rst b/configuration_guides/mt_read.rst index 4aca17185..d56584536 100644 --- a/configuration_guides/mt_read.rst +++ b/configuration_guides/mt_read.rst @@ -1,8 +1,9 @@ .. _mt_read: -************************* +********************************************** Splitting Large Reads for Concurrent Execution -************************* +********************************************** + The ``mtRead`` flag splits large reads into multiple smaller ones and executes them concurrently. The following describes the ``mtRead`` flag: diff --git a/configuration_guides/mt_read_workers.rst b/configuration_guides/mt_read_workers.rst index 5f18fd4b3..52a9ef07b 100644 --- a/configuration_guides/mt_read_workers.rst +++ b/configuration_guides/mt_read_workers.rst @@ -1,8 +1,9 @@ .. _mt_read_workers: -************************* +************************************************ Setting Worker Amount to Handle Concurrent Reads -************************* +************************************************ + The ``mtReadWorkers`` flag sets the number of workers to handle smaller concurrent reads. The following describes the ``mtReadWorkers`` flag: diff --git a/configuration_guides/orc_implicit_casts.rst b/configuration_guides/orc_implicit_casts.rst index 04cc903e9..39d4d6d6c 100644 --- a/configuration_guides/orc_implicit_casts.rst +++ b/configuration_guides/orc_implicit_casts.rst @@ -1,8 +1,9 @@ .. _orc_implicit_casts: -************************* +*********************************** Setting Implicit Casts in ORC Files -************************* +*********************************** + The ``orcImplicitCasts`` flag sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. The following describes the ``orcImplicitCasts`` flag: diff --git a/configuration_guides/statement_lock_timeout.rst b/configuration_guides/statement_lock_timeout.rst index 639f5d02d..bcb7cdd60 100644 --- a/configuration_guides/statement_lock_timeout.rst +++ b/configuration_guides/statement_lock_timeout.rst @@ -1,8 +1,9 @@ .. _statement_lock_timeout: -************************* +********************************************************************* Setting Timeout Limit for Locking Objects before Executing Statements -************************* +********************************************************************* + The ``statementLockTimeout`` flag sets the timeout (seconds) for acquiring object locks before executing statements. The following describes the ``statementLockTimeout`` flag: diff --git a/configuration_guides/use_config_ip.rst b/configuration_guides/use_config_ip.rst index 8779899b1..3d80204c7 100644 --- a/configuration_guides/use_config_ip.rst +++ b/configuration_guides/use_config_ip.rst @@ -1,8 +1,9 @@ .. _use_config_ip: -************************* +************************** Assigning Local Network IP -************************* +************************** + The ``useConfigIP`` flag activates the machineIP (``true``). Setting this flag to ``false`` ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). The following describes the ``useConfigIP`` flag: diff --git a/configuration_guides/use_legacy_decimal_literals.rst b/configuration_guides/use_legacy_decimal_literals.rst index 63650a95b..e839e69ed 100644 --- a/configuration_guides/use_legacy_decimal_literals.rst +++ b/configuration_guides/use_legacy_decimal_literals.rst @@ -1,8 +1,9 @@ .. _use_legacy_decimal_literals: -************************* +********************************************************** Interpreting Decimal Literals as Double Instead of Numeric -************************* +********************************************************** + The ``useLegacyDecimalLiterals`` flag interprets decimal literals as **Double** instead of **Numeric**. This flag is used to preserve legacy behavior in existing customers. The following describes the ``useLegacyDecimalLiterals`` flag: diff --git a/configuration_guides/use_legacy_string_literals.rst b/configuration_guides/use_legacy_string_literals.rst index 164801084..325c95713 100644 --- a/configuration_guides/use_legacy_string_literals.rst +++ b/configuration_guides/use_legacy_string_literals.rst @@ -1,8 +1,9 @@ .. _use_legacy_string_literals: -************************* +**************************** Using Legacy String Literals -************************* +**************************** + The ``useLegacyStringLiterals`` flag interprets ASCII-only strings as **VARCHAR** instead of **TEXT**. This flag is used to preserve legacy behavior in existing customers. The following describes the ``useLegacyStringLiterals`` flag: diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 78e6ea589..0c8df7265 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -25,12 +25,8 @@ Prerequisites The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: * **Oracle Java** - Download and install `Java 8 <https://www.java.com/en/download/manual.jsp>`_ from Oracle for your platform. - - :: * **OpenJDK** - Install `OpenJDK <https://openjdk.java.net/install/>`_ - - :: * **Windows** - SQream recommends installing `Zulu 8 <https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk>`_ From a4e60ec29c5edfaa195a6bd8b14935473fc2c67e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:50:41 +0200 Subject: [PATCH 1223/1892] Maintenance --- .../sql/sql_statements/dml_commands/copy_from.rst | 11 ++++++----- troubleshooting/identifying_configuration_issues.rst | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index ebed5658b..dd41cb935 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -329,7 +329,8 @@ For example, ASCII character ``15``, known as "shift in", can be specified using .. _capturing_rejected_rows: Unsupported Field Delimiters -========================== +============================ + The following ASCII field delimiters (octal range 001 - 176) are not supported: +---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ @@ -407,7 +408,7 @@ All CSV files should be prepared according to these recommendations: Other modes of escaping are not supported (e.g. ``1,"What are \"birds\"?"`` is not a valid way of escaping CSV values). Marking Null Markers ---------------- +-------------------- ``NULL`` values can be marked in two ways in the CSV: @@ -436,7 +437,7 @@ Skipping Faulty Rows Skipping a Maximum of 100 Faulty Rows ------------------------------------ +------------------------------------- .. code-block:: postgres @@ -497,7 +498,7 @@ In the file below, the separator is ``DC1``, which is represented by ASCII 17 de COPY table_name FROM WRAPPER psv_fdw OPTIONS (location = '/tmp/file.txt', delimiter = E'\021'); Loading a Text File with Multi-Character Delimiters --------------------------------------------------- +--------------------------------------------------- In the file below, the separator is ``^|``. @@ -607,7 +608,7 @@ Saving Rejected Rows to a File Loading CSV Files from a Set of Directories ------------------------------------------- +------------------------------------------- .. code-block:: postgres diff --git a/troubleshooting/identifying_configuration_issues.rst b/troubleshooting/identifying_configuration_issues.rst index 25708cda6..9ed4b850b 100644 --- a/troubleshooting/identifying_configuration_issues.rst +++ b/troubleshooting/identifying_configuration_issues.rst @@ -1,8 +1,8 @@ .. _identifying_configuration_issues: -*********************** +******************************** Identifying Configuration Issues -*********************** +******************************** The **Troubleshooting Common Issues** page describes how to troubleshoot the following common issues: From f21c6123f2fc7e9ce21f8490d778430f4da44ceb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Mar 2024 11:57:25 +0200 Subject: [PATCH 1224/1892] Maintenance --- connecting_to_sqream/client_drivers/python/index.rst | 1 - data_ingestion/ingesting_from_databases.rst | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 3528d9eb5..49413e8d1 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -472,4 +472,3 @@ This section shows how to use the ORM to create and populate tables from Python result = session.execute(ins) -For more information, see the :ref:`python_api_reference_guide`. diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 81fa07370..7710d03c3 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: linux curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file +.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: console curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: console tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file From 6c39f1dca4fe5c2ffff53c02c7b612af9b51ae2d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 12 Mar 2024 16:48:02 +0200 Subject: [PATCH 1225/1892] 4.7 --- .../ddl_commands/create_table.rst | 44 +++++++++++-------- releases/4.7.rst | 41 ++++++----------- 2 files changed, 39 insertions(+), 46 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index ffe4395eb..196e324af 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -1,8 +1,8 @@ .. _create_table: -***************** +************ CREATE TABLE -***************** +************ The ``CREATE TABLE`` statement is used to create a new table in an existing database. @@ -10,21 +10,24 @@ The ``CREATE TABLE`` statement is used to create a new table in an existing data * To create a table based on the result of a select query, see :ref:`CREATE TABLE AS <create_table_as>`. * To create a table based on files like Parquet and ORC, see :ref:`CREATE FOREIGN TABLE <create_foreign_table>` - +.. contents:: + :local: + :depth: 1 Syntax -========== +====== The following is the correct syntax for creating a table: .. code-block:: postgres create_table_statement ::= - CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( - { column_def [, ...] } - ) - [ CLUSTER BY { column_name [, ...] } ] - ; + CREATE [ OR REPLACE ] TABLE [<schema_name>.]<table_name> + { + (<column_def> [, ...] [{NULL | NOT NULL}] + | LIKE <source_table> [INCLUDE PERMISSIONS] + } + [ CLUSTER BY <column_name> [, ...] ] schema_name ::= identifier @@ -33,9 +36,7 @@ The following is the correct syntax for creating a table: column_def :: = { column_name type_name [ default ] [ column_constraint ] } column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } + default ::= DEFAULT default_value @@ -71,14 +72,19 @@ The following parameters can be used when creating a table: .. _default_values: +Usage Notes +=========== + +When using ``CREATE TABLE... LIKE``, the permissions from the source table are inherited by the newly created table. To add extra permissions to the new table, you can utilize the ``INCLUDE PERMISSIONS`` clause. + Default Value Constraints =========================== -The ``DEFAULT`` value constraint specifies a value to use if one is not defined in an :ref:`insert` or :ref:`copy_from` statement. +The ``DEFAULT`` value constraint specifies a default value to use if none is provided in an :ref:`insert` or :ref:`copy_from` statement. This value can be a literal or ``NULL``. It's worth noting that even for nullable columns, you can still explicitly insert a ``NULL`` value using the ``NULL`` keyword, as demonstrated in the example: -The default value may be a literal or NULL. +.. code-block:: postgres -.. note:: The ``DEFAULT`` constraint only applies if the column does not have a value specified in the :ref:`insert` or :ref:`copy_from` statement. You can still insert a ``NULL`` into a nullable column by explicitly inserting ``NULL``. For example, ``INSERT INTO cool_animals VALUES (1, 'Gnu', NULL)``. + INSERT INTO cool_animals VALUES (1, 'Gnu', NULL) Syntax --------- @@ -229,10 +235,10 @@ The following is the correct syntax for duplicating the column structure of an e .. code-block:: postgres - CREATE [OR REPLACE] TABLE table_name + CREATE [OR REPLACE] TABLE <table_name> { - (column_name column_type [{NULL | NOT NULL}] [,...]) - | LIKE source_table_name + (<column_name> <column_type> [{NULL | NOT NULL}] [,...]) + | LIKE <source_table_name> [INCLUDE PERMISSIONS] } [CLUSTER BY ...] ; @@ -308,4 +314,4 @@ The following table describes which properties are copied from the target table Permissions ============= -The role must have the ``CREATE`` permission at the schema level. +``CREATE TABLE`` requires ``CREATE`` permission at the schema level. diff --git a/releases/4.7.rst b/releases/4.7.rst index dc821f613..4c1297e85 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,6 +35,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +Single Sign-On Known Issues @@ -45,33 +46,19 @@ Known Issues Version 4.7 resolved Issues --------------------------- -+--------------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+====================+================================================================================================+ -| SQ-16727 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16592 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16534 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16531 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16397 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16038 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-16003 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15947 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15690 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15570 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-14398 | | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13621 | | -+--------------------+------------------------------------------------------------------------------------------------+ ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+=====================================================================================================================+ +| SQ-16592 | | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16531 | Resolved the error encountered when trying to create a ``VIEW`` using a table that necessitates a cleanup operation | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16397 | Fixed database tree UI rendering issue | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-15690 | | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ Deprecations From 26d1e19c2a6ab37a5ec934f1ccda7da05e44baeb Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:30:16 +0200 Subject: [PATCH 1226/1892] Update power_bi.rst --- connecting_to_sqream/client_platforms/power_bi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index 2c19567d3..4b38c97a4 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -20,7 +20,7 @@ SQream integrates with Power BI Desktop to do the following: SQream uses Power BI for extracting data sets using the following methods: -* **Direct query** - Direct queries lets you connect easily with no errors, and refreshes Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the `SQream SQL CLI Reference guide <https://docs.sqream.com/en/v2022.1/reference/cli/sqream_sql.html>`_. +* **Direct query** - Direct queries let you connect easily with no errors, and refresh Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the :ref:`SQream SQL CLI Reference guide <sqream_sql>`. :: From d2b5f0eaa33b372464a9e932936ec77ee8a659cb Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 13 Mar 2024 10:34:40 +0200 Subject: [PATCH 1227/1892] Update power_bi.rst --- connecting_to_sqream/client_platforms/power_bi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/power_bi.rst b/connecting_to_sqream/client_platforms/power_bi.rst index 4b38c97a4..d29aca30c 100644 --- a/connecting_to_sqream/client_platforms/power_bi.rst +++ b/connecting_to_sqream/client_platforms/power_bi.rst @@ -20,7 +20,7 @@ SQream integrates with Power BI Desktop to do the following: SQream uses Power BI for extracting data sets using the following methods: -* **Direct query** - Direct queries let you connect easily with no errors, and refresh Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the :ref:`SQream SQL CLI Reference guide <sqream_sql>`. +* **Direct query** - Direct queries let you connect easily with no errors, and refresh Power BI artifacts, such as graphs and reports, in a considerable amount of time in relation to the time taken for queries to run using the :ref:`SQream SQL CLI Reference guide <sqream_sql_cli_reference>`. :: From 9ba336ff3182f33d8cbc3b0f6f61463c683b87d3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Wed, 13 Mar 2024 12:31:15 +0200 Subject: [PATCH 1228/1892] Update 4.7.rst --- releases/4.7.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 4c1297e85..73cf8e84d 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -49,9 +49,9 @@ Version 4.7 resolved Issues +--------------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+=====================================================================================================================+ -| SQ-16592 | | +| SQ-16592 | Fixed a discrepancy issue following ``OR`` condition execution | +--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16531 | Resolved the error encountered when trying to create a ``VIEW`` using a table that necessitates a cleanup operation | +| SQ-16531 | Resolved the error encountered when trying to create a ``VIEW`` using a table that requires a cleanup operation | +--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16397 | Fixed database tree UI rendering issue | +--------------------+---------------------------------------------------------------------------------------------------------------------+ From ce94e20d0c22401fd4ed10d0504dac73ee9eb294 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Wed, 13 Mar 2024 13:30:50 +0200 Subject: [PATCH 1229/1892] Update 4.7.rst --- releases/4.7.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 73cf8e84d..dcdf54a30 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,7 +35,11 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -Single Sign-On +► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. + +► The ``clientReconnectionTimeout`` configuration flag is now classified as a cluster configuration flag. :ref:`Cluster flags<current_method_configuration_levels>`, as opposed to session flags, apply to your entire cluster and are persistent; meaning that once configured with a certain value, the value you set is retained even after the system is restarted or shut down. + +The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` Known Issues From 321639754d7e9568d6ce272c70d2fb022e259bf5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 14 Mar 2024 17:07:20 +0200 Subject: [PATCH 1230/1892] JAVA CLI + 4.7 --- .../monitoring_query_performance.rst | 86 +-- reference/cli/index.rst | 1 + reference/cli/multi_platform_cli.rst | 516 ++++++++++++++++++ reference/cli/sqream_console.rst | 6 +- reference/cli/sqream_sql.rst | 3 +- releases/4.7.rst | 10 +- 6 files changed, 571 insertions(+), 51 deletions(-) create mode 100644 reference/cli/multi_platform_cli.rst diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index a2ec79564..25e3f3b8c 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -5,7 +5,7 @@ Monitoring Query Performance **************************** When analyzing options for query tuning, the first step is to analyze the query plan and execution. -The query plan and execution details explain how SQream DB processes a query and where time is spent. +The query plan and execution details explain how SQreamDB processes a query and where time is spent. This document details how to analyze query performance with execution plans. This guide focuses specifically on identifying bottlenecks and possible optimization techniques to improve query performance. Performance tuning options for each query are different. You should adapt the recommendations and tips for your own workloads. @@ -19,7 +19,7 @@ See also our :ref:`sql_best_practices` guide for more information about data loa Setting Up the System for Monitoring ==================================== -By default, SQream DB logs execution details for every statement that runs for more than 60 seconds. +By default, SQreamDB logs execution details for every statement that runs for more than 60 seconds. If you want to see the execution details for a currently running statement, see :ref:`using_show_node_info` below. Adjusting the Logging Frequency @@ -28,7 +28,7 @@ Adjusting the Logging Frequency To adjust the frequency of logging for statements, you may want to reduce the interval from 60 seconds down to, say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggingSec`` parameter as you see fit: -.. code-block:: sql +.. code-block:: console :emphasize-lines: 7 @@ -43,7 +43,7 @@ say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggi "server":{ } } -After restarting the SQream DB cluster, the execution plan details will be logged to the :ref:`standard SQream DB logs directory<logging>`, as a message of type ``200``. +After restarting the SQreamDB cluster, the execution plan details will be logged to the :ref:`standard SQreamDB logs directory<logging>`, as a message of type ``200``. You can see these messages with a text viewer or with queries on the log :ref:`foreign_tables`. Reading Execution Plans with a Foreign Table @@ -51,7 +51,7 @@ Reading Execution Plans with a Foreign Table First, create a foreign table for the logs -.. code-block:: sql +.. code-block:: postgres CREATE FOREIGN TABLE logs ( @@ -81,7 +81,7 @@ First, create a foreign table for the logs Once you've defined the foreign table, you can run queries to observe the previously logged execution plans. This is recommended over looking at the raw logs. -.. code-block:: sql +.. code-block:: postgres t=> SELECT message . FROM logs @@ -121,7 +121,7 @@ To inspect a currently running statement, execute the ``show_node_info`` utility In this example, we inspect a statement with statement ID of 176. The command looks like this: -.. code-block:: sql +.. code-block:: postgres t=> SELECT SHOW_NODE_INFO(176); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum @@ -323,7 +323,7 @@ In the following examples you will learn how to identify and solve some common i Spooling to Disk ---------------- -When there is not enough RAM to process a statement, SQream DB will spill over data to the ``temp`` folder in the storage disk. +When there is not enough RAM to process a statement, SQreamDB will spill over data to the ``temp`` folder in the storage disk. While this ensures that a statement can always finish processing, it can slow down the processing significantly. It's worth identifying these statements, to figure out if the cluster is configured correctly, as well as potentially reduce the statement size. @@ -339,7 +339,7 @@ Identifying the Offending Nodes For example, a query from the TPC-H benchmark: - .. code-block:: sql + .. code-block:: postgres SELECT o_year, SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share @@ -365,7 +365,7 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``LoopJoin``: - .. code-block:: sql + .. code-block:: postgres :emphasize-lines: 33,35,37,39 @@ -410,7 +410,7 @@ Identifying the Offending Nodes : 150,LoopJoin ,182369485,10,18236948,2020-09-04 18:31:47,149,12860MB,12860MB,inner,23.62 [...] : 199,ReadTable ,20000000,1,20000000,2020-09-04 18:30:33,198,0MB,,public.part,0.83 - Because of the relatively low amount of RAM in the machine and because the data set is rather large at around 10TB, SQream DB needs to spool. + Because of the relatively low amount of RAM in the machine and because the data set is rather large at around 10TB, SQreamDB needs to spool. The total spool used by this query is around 20GB (1915MB + 2191MB + 3064MB + 12860MB). @@ -419,7 +419,7 @@ Common Solutions for Reducing Spool * Increase the amount of spool memory available for the workers, as a proportion of the maximum statement memory. - When the amount of spool memory is increased, SQream DB may not need to write to disk. + When the amount of spool memory is increased, SQreamDB may not need to write to disk. This setting is called ``spoolMemoryGB``. Refer to the :ref:`configuration` guide. * @@ -440,7 +440,7 @@ Identifying the Offending Nodes For example, a modified query from the TPC-H benchmark: - .. code-block:: sql + .. code-block:: postgres SELECT s.*, l.*, @@ -469,7 +469,7 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``DeferredGather``: - .. code-block:: sql + .. code-block:: postgres :emphasize-lines: 7,9,11 @@ -493,7 +493,7 @@ Identifying the Offending Nodes #. Modify the statement to see the difference Altering the select clause to be more restrictive will reduce the deferred gather time back to a few milliseconds. - .. code-block:: sql + .. code-block:: postgres SELECT DATEPART(year, o_orderdate) AS o_year, l_extendedprice * (1 - l_discount / 100.0) as volume, @@ -509,8 +509,8 @@ Common Solutions for Reducing Gather Time Inefficient Filtering --------------------- -When running statements, SQream DB tries to avoid reading data that is not needed for the statement by :ref:`skipping chunks<chunks_and_extents>`. -If statements do not include efficient filtering, SQream DB will read a lot of data off disk. +When running statements, SQreamDB tries to avoid reading data that is not needed for the statement by :ref:`skipping chunks<chunks_and_extents>`. +If statements do not include efficient filtering, SQreamDB will read a lot of data off disk. In some cases, you need the data and there's nothing to do about it. However, if most of it gets pruned further down the line, it may be efficient to skip reading the data altogether by using the :ref:`metadata<metadata_system>`. @@ -526,7 +526,7 @@ For example: In this example, we execute a modified query from the TPC-H benchmark. Our ``lineitem`` table contains 600,037,902 rows. - .. code-block:: sql + .. code-block:: postgres SELECT o_year, SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share @@ -553,7 +553,7 @@ For example: The execution below has been shortened, but note the highlighted rows for ``ReadTable`` and ``Filter``: - .. code-block:: sql + .. code-block:: postgres :linenos: :emphasize-lines: 9,17,19,27 @@ -597,9 +597,9 @@ For example: of the data, but the entire table was read. However, this table is small enough that we can ignore it. #. Modify the statement to see the difference - Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQream DB skip reading the data. + Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQreamDB skip reading the data. - .. code-block:: sql + .. code-block:: postgres :emphasize-lines: 15 @@ -623,7 +623,7 @@ For example: GROUP BY o_year ORDER BY o_year; - .. code-block:: sql + .. code-block:: postgres :linenos: :emphasize-lines: 5,13 @@ -665,7 +665,7 @@ Identifying the Situation When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. For example, consider these two table structures: -.. code-block:: sql +.. code-block:: postgres CREATE TABLE t_a ( @@ -687,7 +687,7 @@ For example, consider these two table structures: In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``TEXT(50)``. - .. code-block:: sql + .. code-block:: postgres SELECT AVG(t_b.j :: BIGINT), t_a.country_code @@ -702,7 +702,7 @@ For example, consider these two table structures: The ``Join`` node is by far the most time-consuming part of this statement - clocking in at 69.7 seconds joining 1.5 billion records. - .. code-block:: sql + .. code-block:: postgres :linenos: :emphasize-lines: 8 @@ -733,7 +733,7 @@ Improving Query Performance For example: - .. code-block:: sql + .. code-block:: postgres SELECT AVG(t_b.j::BIGINT), t_a.country_code FROM "public"."t_a" @@ -743,7 +743,7 @@ Improving Query Performance The execution below has been shortened, but note the highlighted rows for ``Join``. The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. - .. code-block:: sql + .. code-block:: postgres :linenos: :emphasize-lines: 8 @@ -768,7 +768,7 @@ Improving Query Performance Sorting on big ``TEXT`` fields ------------------------------ -In general, SQream DB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. +In general, SQreamDB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. When running a ``GROUP BY`` on large ``TEXT`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. Identifying the Situation @@ -783,7 +783,7 @@ For example: Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: - .. code-block:: sql + .. code-block:: postgres :emphasize-lines: 5 @@ -798,7 +798,7 @@ For example: We will run a query, and inspect it's execution details: - .. code-block:: psql + .. code-block:: postgres t=> SELECT country_code, . SUM(amt) @@ -815,7 +815,7 @@ For example: [...] - .. code-block:: sql + .. code-block:: postgres :emphasize-lines: 8,9 @@ -837,7 +837,7 @@ For example: #. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key - .. code-block:: sql + .. code-block:: postgres t=> SELECT MAX(LEN(country_code)) FROM t_inefficient; max @@ -847,7 +847,7 @@ For example: #. We can recreate the table with a more restrictive ``TEXT(3)``, and can examine the difference in performance: - .. code-block:: sql + .. code-block:: postgres t=> CREATE TABLE t_efficient . AS SELECT i, @@ -888,11 +888,11 @@ High Selectivity Data --------------------- Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` -SQream DB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. -The hint signals to SQream DB that the result of the condition will be very sparse, and that it should attempt to rechunk +SQreamDB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. +The hint signals to SQreamDB that the result of the condition will be very sparse, and that it should attempt to rechunk the results into fewer, fuller chunks. .. note:: - SQream DB doesn't do this automatically because it adds a significant overhead on naturally ordered and + SQreamDB doesn't do this automatically because it adds a significant overhead on naturally ordered and well-clustered data, which is the more common scenario. Identifying the Situation @@ -901,7 +901,7 @@ Identifying the Situation This is easily identifiable - when the amount of average of rows in a chunk is small, following a ``Filter`` operation. Consider this execution plan: -.. code-block:: sql +.. code-block:: postgres t=> select show_node_info(30); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum @@ -935,7 +935,7 @@ In this case, we're also interested in the number of chunks produced by these no Consider this execution plan: -.. code-block:: sql +.. code-block:: postgres :emphasize-lines: 6,11 @@ -964,12 +964,12 @@ All of these rows could fit in one single chunk, instead of spanning 74 rather s Improving Join Performance when Data is Sparse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -You can tell SQream DB to reduce the amount of chunks involved, if you know that the filter is going to be quite +You can tell SQreamDB to reduce the amount of chunks involved, if you know that the filter is going to be quite agressive by using the :ref:`HIGH_SELECTIVITY<high_selectivity>` hint described :ref:`above<high_selectivity_data_opt>`. This forces the compiler to rechunk the data into fewer chunks. -To tell SQream DB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: +To tell SQreamDB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: -.. code-block:: sql +.. code-block:: postgres :emphasize-lines: 13 @@ -1009,7 +1009,7 @@ Always prefer to join the smallest tables first. Changing the join order can reduce the query runtime significantly. In the examples below, we reduce the time from 27.3 seconds to just 6.4 seconds. -.. code-block:: sql +.. code-block:: postgres :caption: Original query @@ -1029,7 +1029,7 @@ from 27.3 seconds to just 6.4 seconds. AND l_shipdate <= dateadd(DAY,122,'1994-01-01') GROUP BY c_nationkey -.. code-block:: sql +.. code-block:: postgres :caption: Modified query with improved join order diff --git a/reference/cli/index.rst b/reference/cli/index.rst index 588e8d54a..1000154dd 100644 --- a/reference/cli/index.rst +++ b/reference/cli/index.rst @@ -49,6 +49,7 @@ This topic contains the reference for these programs, as well as flags and confi metadata_server sqreamd + multi_platform_cli sqream_console server_picker sqream_storage diff --git a/reference/cli/multi_platform_cli.rst b/reference/cli/multi_platform_cli.rst new file mode 100644 index 000000000..95b9cbba9 --- /dev/null +++ b/reference/cli/multi_platform_cli.rst @@ -0,0 +1,516 @@ +.. _multi_platform_cli: + +********************************* +Multi-Platform Sqream SQL +********************************* + +SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. + +This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +Sqream SQL requires Java 8 + +Installing Sqream SQL +===================== + +If you have a SQreamDB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQreamDB installation, under the name ``sqream``. + + +To run ``sqream sql`` on any other Linux host: + +#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. +#. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` +#. Start the client: + + .. code-block:: psql + + $ cd sqream-sql-v2020.1.1_stable.x86_64 + $ ./sqream sql --port=5000 --username=jdoe --databasename=master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +Troubleshooting Sqream SQL Installation +--------------------------------------- + +Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. + +Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. + +* Ubuntu: + + #. Install ``libtinfo``: + + ``$ sudo apt-get install -y libtinfo`` + #. Depending on your Ubuntu version, you may need to create a symbolic link to the newer libtinfo that was installed. + + For example, if ``libtinfo`` was installed as ``/lib/x86_64-linux-gnu/libtinfo.so.6.2``: + + ``$ sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6.2 /lib/x86_64-linux-gnu/libtinfo.so.5`` + +* CentOS / RHEL: + + #. Install ``ncurses``: + + ``$ sudo yum install -y ncurses-libs`` + #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. + + For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: + + ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` + +Using Sqream SQL +================ + +By default, sqream sql runs in interactive mode. You can issue commands or SQL statements. + +Running Commands Interactively (SQL shell) +------------------------------------------ + +When starting sqream sql, after entering your password, you are presented with the SQL shell. + +To exit the shell, type ``\q`` or :kbd:`Ctrl-d`. + +.. code-block:: psql + + $ sqream sql --port=5000 --username=jdoe --databasename=master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +The database name shown means you are now ready to run statements and queries. + +Statements and queries are standard SQL, followed by a semicolon (``;``). Statement results are usually formatted as a valid CSV, +followed by the number of rows and the elapsed time for that statement. + +.. code-block:: psql + + master=> SELECT TOP 5 * FROM nba; + Avery Bradley ,Boston Celtics ,0,PG,25,6-2 ,180,Texas ,7730337 + Jae Crowder ,Boston Celtics ,99,SF,25,6-6 ,235,Marquette ,6796117 + John Holland ,Boston Celtics ,30,SG,27,6-5 ,205,Boston University ,\N + R.J. Hunter ,Boston Celtics ,28,SG,22,6-5 ,185,Georgia State ,1148640 + Jonas Jerebko ,Boston Celtics ,8,PF,29,6-10,231,\N,5000000 + 5 rows + time: 0.001185s + +.. note:: Null values are represented as \\N. + +When writing long statements and queries, it may be beneficial to use line-breaks. +The prompt for a multi-line statement will change from ``=>`` to ``.``, to alert users to the change. The statement will not execute until a semicolon is used. + + +.. code-block:: psql + :emphasize-lines: 13 + + $ sqream sql --port=5000 --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> SELECT "Age", + . AVG("Salary") + . FROM NBA + . GROUP BY 1 + . ORDER BY 2 ASC + . LIMIT 5 + . ; + 38,1840041 + 19,1930440 + 23,2034746 + 21,2067379 + 36,2238119 + 5 rows + time: 0.009320s + + +Executing Batch Scripts (``-f``) +-------------------------------- + +To run an SQL script, use the ``-f <filename>`` argument. + +For example, + +.. code-block:: console + + $ sqream sql --port=5000 --username=jdoe -d master -f sql_script.sql --results-only + +.. tip:: Output can be saved to a file by using redirection (``>``). + +Executing Commands Immediately (``-c``) +--------------------------------------- + +To run a statement from the console, use the ``-c <statement>`` argument. + +For example, + +.. code-block:: console + + $ sqream sql --port=5000 --username=jdoe -d nba -c "SELECT TOP 5 * FROM nba" + Avery Bradley ,Boston Celtics ,0,PG,25,6-2 ,180,Texas ,7730337 + Jae Crowder ,Boston Celtics ,99,SF,25,6-6 ,235,Marquette ,6796117 + John Holland ,Boston Celtics ,30,SG,27,6-5 ,205,Boston University ,\N + R.J. Hunter ,Boston Celtics ,28,SG,22,6-5 ,185,Georgia State ,1148640 + Jonas Jerebko ,Boston Celtics ,8,PF,29,6-10,231,\N,5000000 + 5 rows + time: 0.202618s + +.. tip:: Remove the timing and row count by passing the ``--results-only`` parameter + + +Examples +======== + +Starting a Regular Interactive Shell +------------------------------------ + +Connect to local server 127.0.0.1 on port 5000, to the default built-in database, `master`: + +.. code-block:: psql + + $ sqream sql --port=5000 --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + +Connect to local server 127.0.0.1 via the built-in load balancer on port 3108, to the default built-in database, `master`: + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + +Executing Statements in an Interactive Shell +-------------------------------------------- + +Note that all SQL commands end with a semicolon. + +Creating a new database and switching over to it without reconnecting: + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=oldmcd -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> create database farm; + executed + time: 0.003811s + master=> \c farm + farm=> + +.. code-block:: psql + + farm=> create table animals(id int not null, name text(30) not null, is_angry bool not null); + executed + time: 0.011940s + + farm=> insert into animals values(1,'goat',false); + executed + time: 0.000405s + + farm=> insert into animals values(4,'bull',true) ; + executed + time: 0.049338s + + farm=> select * from animals; + 1,goat ,0 + 4,bull ,1 + 2 rows + time: 0.029299s + +Executing SQL Statements from the Command Line +---------------------------------------------- + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals WHERE is_angry = true" + 4,bull ,1 + 1 row + time: 0.095941s + +.. _controlling_output: + +Controlling the Client Output +----------------------------- + +Two parameters control the dispay of results from the client: + +* ``--results-only`` - removes row counts and timing information +* ``--delimiter`` - changes the record delimiter + +Exporting SQL Query Results to CSV +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using the ``--results-only`` flag removes the row counts and timing. + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals" --results-only > file.csv + $ cat file.csv + 1,goat ,0 + 2,sow ,0 + 3,chicken ,0 + 4,bull ,1 + +Changing a CSV to a TSV +^^^^^^^^^^^^^^^^^^^^^^^ + +The ``--delimiter`` parameter accepts any printable character. + +.. tip:: To insert a tab, use :kbd:`Ctrl-V` followed by :kbd:`Tab ↹` in Bash. + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals" --delimiter ' ' > file.tsv + $ cat file.tsv + 1 goat 0 + 2 sow 0 + 3 chicken 0 + 4 bull 1 + + +Executing a Series of Statements From a File +-------------------------------------------- + +Assuming a file containing SQL statements (separated by semicolons): + +.. code-block:: console + + $ cat some_queries.sql + CREATE TABLE calm_farm_animals + ( id INT IDENTITY(0, 1), name TEXT(30) + ); + + INSERT INTO calm_farm_animals (name) + SELECT name FROM animals WHERE is_angry = false; + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -f some_queries.sql + executed + time: 0.018289s + executed + time: 0.090697s + +Connecting Using Environment Variables +-------------------------------------- + +You can save connection parameters as environment variables: + +.. code-block:: console + + $ export SQREAM_USER=sqream; + $ export SQREAM_DATABASE=farm; + $ sqream sql --port=3105 --clustered --username=$SQREAM_USER -d $SQREAM_DATABASE + +Connecting to a Specific Queue +------------------------------ + +When using the :ref:`dynamic workload manager<workload_manager>` - connect to ``etl`` queue instead of using the default ``sqream`` queue. + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=mjordan -d master --service=etl + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + + +Operations and Flag References +============================== + +Command Line Arguments +---------------------- + +**Sqream SQL** supports the following command line arguments: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Argument + - Default + - Description + * - ``-c`` or ``--command`` + - None + - Changes the mode of operation to single-command, non-interactive. Use this argument to run a statement and immediately exit. + * - ``-f`` or ``--file`` + - None + - Changes the mode of operation to multi-command, non-interactive. Use this argument to run a sequence of statements from an external file and immediately exit. + * - ``--host`` + - ``127.0.0.1`` + - Address of the SQreamDB worker. + * - ``--port`` + - ``5000`` + - Sets the connection port. + * - ``--databasename`` or ``-d`` + - None + - Specifies the database name for queries and statements in this session. + * - ``--username`` + - None + - Username to connect to the specified database. + * - ``--password`` + - None + - Specify the password using the command line argument. If not specified, the client will prompt the user for the password. + * - ``--clustered`` + - False + - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQreamDB worker. + * - ``--service`` + - ``sqream`` + - :ref:`Service name (queue)<workload_manager>` that statements will file into. + * - ``--results-only`` + - False + - Outputs results only, without timing information and row counts + * - ``--no-history`` + - False + - When set, prevents command history from being saved in ``~/.sqream/clientcmdhist`` + * - ``--delimiter`` + - ``,`` + - Specifies the field separator. By default, ``sqream sql`` outputs valid CSVs. Change the delimiter to modify the output to another delimited format (e.g. TSV, PSV). See the section :ref:`supported record delimiters<supported_record_delimiters>` below for more information. + +.. tip:: Run ``$ sqream sql --help`` to see a full list of arguments + +.. _supported_record_delimiters: + +Supported Record Delimiters +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The supported record delimiters are printable ASCII values (32-126). + +* Recommended delimiters for use are: ``,``, ``|``, tab character. + +* The following characters are **not supported**: ``\``, ``N``, ``-``, ``:``, ``"``, ``\n``, ``\r``, ``.``, lower-case latin letters, digits (0-9) + +Meta-Commands +------------- + +* Meta-commands in Sqream SQL start with a backslash (``\``) + +.. note:: Meta commands do not end with a semicolon + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Command + - Example + - Description + * - ``\q`` or ``\quit`` + - .. code-block:: psql + + master=> \q + - Quit the client. (Same as :kbd:`Ctrl-d`) + * - ``\c <database>`` or ``\connect <database>`` + - .. code-block:: psql + + master=> \c fox + fox=> + - Changes the current connection to an alternate database + +Basic Commands +-------------- + +.. list-table:: + :widths: 20 30 50 + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-l` + - Clear the screen. + * - :kbd:`Ctrl-c` + - Terminate the current command. + * - :kbd:`Ctrl-z` + - Suspend/stop the command. + * - :kbd:`Ctrl-d` + - Quit SQream SQL + + + +Moving Around the Command Line +------------------------------ + +.. list-table:: + :widths: 17 83 + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-a` + - Goes to the beginning of the command line. + * - :kbd:`Ctrl-e` + - Goes to the end of the command line. + * - :kbd:`Ctrl-u` + - Deletes from cursor to the beginning of the command line. + * - :kbd:`Ctrl-k` + - Deletes from the cursor to the end of the command line. + * - :kbd:`Ctrl-w` + - Delete from cursor to beginning of a word. + * - :kbd:`Ctrl-y` + - Pastes a word or text that was cut using one of the deletion shortcuts (such as the one above) after the cursor. + * - :kbd:`Alt-b` + - Moves back one word (or goes to the beginning of the word where the cursor is). + * - :kbd:`Alt-f` + - Moves forward one word (or goes to the end of word the cursor is). + * - :kbd:`Alt-d` + - Deletes to the end of a word starting at the cursor. Deletes the whole word if the cursor is at the beginning of that word. + * - :kbd:`Alt-c` + - Capitalizes letters in a word starting at the cursor. Capitalizes the whole word if the cursor is at the beginning of that word. + * - :kbd:`Alt-u` + - Capitalizes from the cursor to the end of the word. + * - :kbd:`Alt-l` + - Makes lowercase from the cursor to the end of the word. + * - :kbd:`Ctrl-f` + - Moves forward one character. + * - :kbd:`Ctrl-b` + - Moves backward one character. + * - :kbd:`Ctrl-h` + - Deletes characters located before the cursor. + * - :kbd:`Ctrl-t` + - Swaps a character at the cursor with the previous character. + +Searching +--------- + +.. list-table:: + :widths: 17 83 + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-r` + - Searches the history backward. + * - :kbd:`Ctrl-g` + - Escapes from history-searching mode. + * - :kbd:`Ctrl-p` + - Searches the previous command in history. + * - :kbd:`Ctrl-n` + - Searches the next command in history. diff --git a/reference/cli/sqream_console.rst b/reference/cli/sqream_console.rst index ac46fdbb0..ba1849475 100644 --- a/reference/cli/sqream_console.rst +++ b/reference/cli/sqream_console.rst @@ -1,10 +1,10 @@ .. _sqream_console_cli_reference: ********************************* -sqream Linux console +SqreamDB Console ********************************* -``sqream-console`` is an interactive shell designed to help manage a dockerized SQream DB installation. +``sqream-console`` is an interactive shell designed to help manage a dockerized SQreamDB installation. The console itself is a dockerized application. @@ -15,7 +15,7 @@ The console itself is a dockerized application. Starting the console ====================== -``sqream-console`` can be found in your SQream DB installation, under the name ``sqream-console``. +``sqream-console`` can be found in your SQreamDB installation, under the name ``sqream-console``. Start the console by executing it from the shell diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index 132f9679c..ae37f9d0c 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -1,7 +1,7 @@ .. _sqream_sql_cli_reference: ************************ -Sqream SQL CLI Reference +Linux Sqream SQL ************************ SQream DB comes with a built-in client for executing SQL statements either interactively or from the command-line. @@ -17,7 +17,6 @@ Installing Sqream SQL If you have a SQream DB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. - .. versionchanged:: 2020.1 As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. diff --git a/releases/4.7.rst b/releases/4.7.rst index dcdf54a30..96ca8e326 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -37,9 +37,13 @@ New Features and Enhancements ► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. -► The ``clientReconnectionTimeout`` configuration flag is now classified as a cluster configuration flag. :ref:`Cluster flags<current_method_configuration_levels>`, as opposed to session flags, apply to your entire cluster and are persistent; meaning that once configured with a certain value, the value you set is retained even after the system is restarted or shut down. +► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` + +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + +► Multi-platform CLI + -The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` Known Issues @@ -61,7 +65,7 @@ Version 4.7 resolved Issues +--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | +--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-15690 | | +| SQ-15690 | **Not fixed yet** - JDBC connector connectivity issue resulting in stuck queries | +--------------------+---------------------------------------------------------------------------------------------------------------------+ From 18d9798f74ebddb0adaee4915a7d69e8aae83ae1 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:20:52 +0200 Subject: [PATCH 1231/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 0c8df7265..3a1832c59 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -41,18 +41,18 @@ Setting Up the Class Path To use the driver, you must include the JAR named ``sqream-jdbc-<version>.jar`` in the class path, either by inserting it in the ``CLASSPATH`` environment variable, or by using flags on the relevant Java command line. -For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-5.1.0.jar``, the following command is used to run application: +For example, if the JDBC driver has been unzipped to ``/home/sqream/sqream-jdbc-5.2.0.jar``, the following command is used to run application: .. code-block:: console - $ export CLASSPATH=/home/sqream/sqream-jdbc-5.1.0.jar:$CLASSPATH + $ export CLASSPATH=/home/sqream/sqream-jdbc-5.2.0.jar:$CLASSPATH $ java my_java_app Alternatively, you can pass ``-classpath`` to the Java executable file: .. code-block:: console - $ java -classpath .:/home/sqream/sqream-jdbc-5.1.0.jar my_java_app + $ java -classpath .:/home/sqream/sqream-jdbc-5.2.0.jar my_java_app Connecting to SQream Using a JDBC Application ============================================= @@ -187,4 +187,4 @@ You may download the :download:`Prepared statement <samplepreparedstatement.java .. literalinclude:: samplePreparedStatement.java :language: java :caption: Prepared Statement Sample - :linenos: \ No newline at end of file + :linenos: From 468803fccbb3ec305a312daeeea5993492d49136 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:21:18 +0200 Subject: [PATCH 1232/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 3525e1de5..3bfa2aa5d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.1.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.1.0.jar>`_ + - `sqream-jdbc 5.1.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.2.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From a80e4c66568a60ac04d09f92b1a00f0f8aade0d4 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 17 Mar 2024 18:21:48 +0200 Subject: [PATCH 1233/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index ad58f2a8a..ca799223d 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -23,7 +23,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.1.0 | +| Driver compatibility | * JDBC 5.2.0 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | From 6a55ffd3e7653bf9f7819c69821679bc30496c46 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:10:17 +0200 Subject: [PATCH 1234/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 3bfa2aa5d..21a4db9b6 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.1.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.2.0.jar>`_ + - `sqream-jdbc 5.2.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.2.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From c6bc4e67b80e340b867315e8f42d917120982525 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Mar 2024 08:53:09 +0200 Subject: [PATCH 1235/1892] rechunk --- reference/sql/sql_statements/index.rst | 52 +++++++++++-------- .../utility_commands/rechunk.rst | 40 ++++++++++++++ releases/4.7.rst | 2 +- 3 files changed, 70 insertions(+), 24 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/rechunk.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 25699492b..cf93d9be6 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -3,6 +3,7 @@ *************** SQL Statements *************** + The **SQL Statements** page describes the following commands: .. contents:: @@ -15,6 +16,7 @@ SQream supports commands from ANSI SQL. Data Definition Commands (DDL) ================================ + The following table shows the Data Definition commands: .. list-table:: @@ -71,6 +73,7 @@ The following table shows the Data Definition commands: Data Manipulation Commands (DML) ================================ + The following table shows the Data Manipulation commands: .. list-table:: @@ -101,6 +104,7 @@ The following table shows the Data Manipulation commands: Utility Commands ================== + The following table shows the Utility commands: .. list-table:: @@ -109,38 +113,38 @@ The following table shows the Utility commands: * - Command - Usage - * - :ref:`GET TOTAL CHUNKS SIZE<get_total_chunks_size>` - - Returns the total size of all data chunks saved in the system + * - :ref:`DATA READ METRICS<select_data_read_metrics>` + - Monitor license quota usage by reviewing monthly or daily data read usage * - :ref:`DROP SAVED QUERY<drop_saved_query>` - Drops a saved query + * - :ref:`DUMP DATABASE DDL<dump_database_ddl>` + - View the ``CREATE TABLE`` statement for an current database * - :ref:`EXECUTE SAVED QUERY<execute_saved_query>` - Executes a previously saved query * - :ref:`EXPLAIN<explain>` - Returns a static query plan, which can be used to debug query plans + * - :ref:`GET DDL<get_ddl>` + - View the ``CREATE TABLE`` statement for a table + * - :ref:`GET FUNCTION DDL<get_function_ddl>` + - View the ``CREATE FUNCTION`` statement for a UDF + * - :ref:`GET LICENSE INFO<get_license_info>` + - View a user's license information + * - :ref:`GPU METRICS<select_gpu_metrics>` + - Monitor license quota usage by reviewing monthly or daily GPU usage + * - :ref:`GET TOTAL CHUNKS SIZE<get_total_chunks_size>` + - Returns the total size of all data chunks saved in the system + * - :ref:`GET VIEW DDL<get_view_ddl>` + - View the ``CREATE VIEW`` statement for a view + * - :ref:`HEALTH CHECK MONITORING<select_health_check_monitoring>` + - Returns system health monitoring logs * - :ref:`LIST SAVED QUERIES<list_saved_queries>` - Lists previously saved query names, one per row. + * - :ref:`RECHUNK<rechunk>` + - * - :ref:`RECOMPILE SAVED QUERY<recompile_saved_query>` - Recompiles a saved query that has been invalidated due to a schema change - * - :ref:`SELECT GET LICENSE INFO<get_license_info>` - - View a user's license information - * - :ref:`SELECT GET DDL<get_ddl>` - - View the ``CREATE TABLE`` statement for a table - * - :ref:`SELECT GET FUNCTION DDL<get_function_ddl>` - - View the ``CREATE FUNCTION`` statement for a UDF - * - :ref:`SELECT GET TOTAL CHUNKS SIZE<get_total_chunks_size>` - - Shows the total size of all data chunks saved in the system in both compressed and uncompressed formats - * - :ref:`SELECT GET VIEW DDL<get_view_ddl>` - - View the ``CREATE VIEW`` statement for a view - * - :ref:`SELECT DATA READ METRICS<select_data_read_metrics>` - - Monitor license quota usage by reviewing monthly or daily data read usage - * - :ref:`SELECT GPU METRICS<select_gpu_metrics>` - - Monitor license quota usage by reviewing monthly or daily GPU usage - * - :ref:`SELECT HEALTH CHECK MONITORING<select_health_check_monitoring>` - - Returns system health monitoring logs - * - :ref:`SELECT RECOMPILE VIEW<recompile_view>` + * - :ref:`RECOMPILE VIEW<recompile_view>` - Recreate a view after schema changes - * - :ref:`SELECT DUMP DATABASE DDL<dump_database_ddl>` - - View the ``CREATE TABLE`` statement for an current database * - :ref:`SHOW CONNECTIONS<show_connections>` - Returns a list of active sessions on the current worker * - :ref:`SHOW LOCKS<show_locks>` @@ -151,16 +155,17 @@ The following table shows the Utility commands: - Returns a single row result containing the saved query string * - :ref:`SHOW SERVER STATUS<show_server_status>` - Returns a list of active sessions across the cluster - * - :ref:`SHOW VERSION<show_version>` - - Returns the system version for SQream DB * - :ref:`SHUTDOWN SERVER<shutdown_server_command>` - Sets your server to finish compiling all active queries before shutting down according to a user-defined time value * - :ref:`STOP STATEMENT<stop_statement>` - Stops or aborts an active statement + * - :ref:`SHOW VERSION<show_version>` + - Returns the system version for SQream DB Workload Management ====================== + The following table shows the Workload Management commands: .. list-table:: @@ -178,6 +183,7 @@ The following table shows the Workload Management commands: Access Control Commands ================================ + The following table shows the Access Control commands: .. list-table:: diff --git a/reference/sql/sql_statements/utility_commands/rechunk.rst b/reference/sql/sql_statements/utility_commands/rechunk.rst new file mode 100644 index 000000000..649e75b24 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/rechunk.rst @@ -0,0 +1,40 @@ +.. _rechunk: + +******* +RECHUNK +******* + +SQreamDB is most efficient processing large data chunks. The ``rechunk`` function improves performance when handling tables with small data chunks by allowing you to consolidate these small chunks into larger ones. Additionally, this function also addresses mixed chunks, which are those containing one or more deleted records. When applied to mixed chunks, the function performs a :ref:`cleanup operation<delete_guide>`, resulting in clean, large data chunks. + +Syntax +========== + +.. code-block:: postgres + + SELECT rechunk('<schema_name>', '<table_name>') + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema in which the table to rechunk is in + * - ``table_name`` + - The name of the table to rechunk + +Example +======= + +.. code-block:: postgres + + SELECT rechunk('public', 't'); + +Permissions +============= + +Using the ``rechunk`` command requires no special permissions. \ No newline at end of file diff --git a/releases/4.7.rst b/releases/4.7.rst index 96ca8e326..66e6d0c78 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -23,7 +23,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.1.0 | +| Driver compatibility | * JDBC 5.2.0 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | From cdac27d5ffd3440892d712f2d2c4d9e7485fa59c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Mar 2024 09:04:43 +0200 Subject: [PATCH 1236/1892] Update 4.7.rst --- releases/4.7.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.7.rst b/releases/4.7.rst index 66e6d0c78..670b5633e 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -41,6 +41,8 @@ New Features and Enhancements ► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + ► Multi-platform CLI From 639af4297e71d273a230366ae7fa4c78ac7b5b30 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:34:45 +0200 Subject: [PATCH 1237/1892] Update multi_platform_cli.rst --- reference/cli/multi_platform_cli.rst | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/reference/cli/multi_platform_cli.rst b/reference/cli/multi_platform_cli.rst index 95b9cbba9..09dde7d4f 100644 --- a/reference/cli/multi_platform_cli.rst +++ b/reference/cli/multi_platform_cli.rst @@ -40,34 +40,6 @@ To run ``sqream sql`` on any other Linux host: master=> _ -Troubleshooting Sqream SQL Installation ---------------------------------------- - -Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. - -Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. - -* Ubuntu: - - #. Install ``libtinfo``: - - ``$ sudo apt-get install -y libtinfo`` - #. Depending on your Ubuntu version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/lib/x86_64-linux-gnu/libtinfo.so.6.2``: - - ``$ sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6.2 /lib/x86_64-linux-gnu/libtinfo.so.5`` - -* CentOS / RHEL: - - #. Install ``ncurses``: - - ``$ sudo yum install -y ncurses-libs`` - #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: - - ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` Using Sqream SQL ================ From 0185cf69ed2143d6ad9082a70e4ae66472ec7905 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 18 Mar 2024 14:02:45 +0200 Subject: [PATCH 1238/1892] Removing _seeing_system_objects_as_ddl: --- operational_guides/index.rst | 1 - .../seeing_system_objects_as_ddl.rst | 171 ------------------ ...ts_and_running_queries_from_the_editor.rst | 2 +- 3 files changed, 1 insertion(+), 173 deletions(-) delete mode 100644 operational_guides/seeing_system_objects_as_ddl.rst diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 8f2b5be45..9bbb4530d 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -23,6 +23,5 @@ This section summarizes the following operational guides: monitoring_query_performance security saved_queries - seeing_system_objects_as_ddl optimization_best_practices \ No newline at end of file diff --git a/operational_guides/seeing_system_objects_as_ddl.rst b/operational_guides/seeing_system_objects_as_ddl.rst deleted file mode 100644 index 2aacb49e8..000000000 --- a/operational_guides/seeing_system_objects_as_ddl.rst +++ /dev/null @@ -1,171 +0,0 @@ -.. _seeing_system_objects_as_ddl: - -******************************** -Seeing System Objects as DDL -******************************** - -Dump specific objects -=========================== - -Tables ----------- - -See :ref:`get_ddl` for more information. - -.. rubric:: Examples - -Getting the DDL for a table -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT GET_DDL('cool_animals'); - create table "public"."cool_animals" ( - "id" int not null, - "name" text(30) not null, - "weight" double null, - "is_agressive" bool default false not null ) - ; - -Exporting table DDL to a file -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: postgres - - COPY (SELECT GET_DDL('cool_animals')) TO '/home/rhendricks/animals.ddl'; - -Views ----------- - -See :ref:`get_view_ddl` for more information. - -.. rubric:: Examples - -Listing all views -^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT view_name FROM sqream_catalog.views; - view_name - ---------------------- - angry_animals - only_agressive_animals - - -Getting the DDL for a view -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - farm=> SELECT GET_VIEW_DDL('angry_animals'); - create view "public".angry_animals as - select - "cool_animals"."id" as "id", - "cool_animals"."name" as "name", - "cool_animals"."weight" as "weight", - "cool_animals"."is_agressive" as "is_agressive" - from - "public".cool_animals as cool_animals - where - "cool_animals"."is_agressive" = false; - -Exporting view DDL to a file -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: postgres - - COPY (SELECT GET_VIEW_DDL('angry_animals')) TO '/home/rhendricks/angry_animals.sql'; - -User defined functions -------------------------- - -See :ref:`get_function_ddl` for more information. - -.. rubric:: Examples - -Listing all UDFs -^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - master=> SELECT * FROM sqream_catalog.user_defined_functions; - database_name | function_id | function_name - --------------+-------------+-------------- - master | 1 | my_distance - -Getting the DDL for a function -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: psql - - master=> SELECT GET_FUNCTION_DDL('my_distance'); - create function "my_distance" (x1 float, - y1 float, - x2 float, - y2 float) returns float as - $$ - import math - if y1 < x1: - return 0.0 - else: - return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) - $$ - language python volatile; - -Exporting function DDL to a file ------------------------------------- - -.. code-block:: postgres - - COPY (SELECT GET_FUNCTION_DDL('my_distance')) TO '/home/rhendricks/my_distance.sql'; - -Saved queries ------------------ - -See :ref:`list_saved_queries`, :ref:`show_saved_query` for more information. - -Dump entire database DDLs -================================== - -Dumping the database DDL includes tables and views, but not UDFs and saved queries. - -See :ref:`dump_database_ddl` for more information. - -.. rubric:: Examples - -Exporting database DDL to a client ---------------------------------------- - -.. code-block:: psql - - farm=> SELECT DUMP_DATABASE_DDL(); - create table "public"."cool_animals" ( - "id" int not null, - "name" text(30) not null, - "weight" double null, - "is_agressive" bool default false not null - ) - ; - - create view "public".angry_animals as - select - "cool_animals"."id" as "id", - "cool_animals"."name" as "name", - "cool_animals"."weight" as "weight", - "cool_animals"."is_agressive" as "is_agressive" - from - "public".cool_animals as cool_animals - where - "cool_animals"."is_agressive" = false; - -Exporting database DDL to a file ---------------------------------------- - -.. code-block:: postgres - - COPY (SELECT DUMP_DATABASE_DDL()) TO '/home/rhendricks/database.ddl'; - - - -.. note:: To export data in tables, see :ref:`copy_to`. diff --git a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index 840fe283d..c57bd7d58 100644 --- a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -177,7 +177,7 @@ The database object functions are used to perform the following: * - Drop table statement - Generates a ``DROP`` statement for the selected object in the editing area. * - Table DDL - - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. See :ref:`Seeing System Objects as DDL <seeing_system_objects_as_ddl>`. + - Generates a DDL statement for the selected object in the editing area. To get the entire database DDL, click the |icon-ddl-edit| icon next to the database name in the tree root. * - DDL Optimizer - The :ref:`DDL Optimizer<executing_statements_and_running_queries_from_the_editor>` lets you analyze database tables and recommends possible optimizations. From 97dbb7229486f4af90bc656a3dd7bf3bfe2770c9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Mar 2024 09:57:33 +0200 Subject: [PATCH 1239/1892] 4.7 --- reference/sql/sql_functions/index.rst | 4 ++ .../conditionals/is_table_exists.rst | 50 +++++++++++++++++++ .../conditionals/is_view_exists.rst | 50 +++++++++++++++++++ .../sql_statements/dml_commands/select.rst | 3 ++ releases/4.7.rst | 7 +++ 5 files changed, 114 insertions(+) create mode 100644 reference/sql/sql_functions/scalar_functions/conditionals/is_table_exists.rst create mode 100644 reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 692a84be4..4f7bf1c5a 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -66,6 +66,10 @@ The following table shows the **conditionals** functions: - Test a ``TEXT`` for ASCII-only characters * - :ref:`is_null` - Check for ``NULL`` [ or non-``NULL`` ] values + * - :ref:`is_table_exists` + - Checks if the mentioned table exists in the mentioned schema + * - :ref:`is_view_exists` + - Checks if the mentioned view exists in the mentioned schema Conversion ^^^^^^^^^^^^ diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_table_exists.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_table_exists.rst new file mode 100644 index 000000000..9531f8e56 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_table_exists.rst @@ -0,0 +1,50 @@ +.. _is_table_exists: + +************************** +IS TABLE EXISTS +************************** + +The ``IS TABLE EXISTS`` check whether a table exists in a specified schema within the database. + +Syntax +========== + +.. code-block:: postgres + + SELECT is_table_exists(<'schema_name'>, <'table_name'>) + + +Arguments +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema to search for the table within + * - ``table_name`` + - The name of the table to check for existence + +Returns +======= + +* ``1`` if table exists +* ``0`` if table does not exist + + +Example +======== + +.. code-block:: psql + + SELECT is_table_exists('public', 'my_table'); + + ----- + 1 + + + + diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst new file mode 100644 index 000000000..ca6152c59 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst @@ -0,0 +1,50 @@ +.. _is_view_exists: + +************************** +IS VIEW EXISTS +************************** + +The ``IS VIEW EXISTS`` check whether a view exists in a specified schema within the database. + +Syntax +========== + +.. code-block:: postgres + + SELECT is_view_exists(<'schema_name'>, <'table_name'>) + + +Arguments +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The schema to search for the view within + * - ``table_name`` + - The name of the view to check for existence + +Returns +======= + +* ``1`` if view exists +* ``0`` if view does not exist + + +Example +======== + +.. code-block:: psql + + SELECT is_view_exists('public', 'my_view'); + + ----- + 1 + + + + diff --git a/reference/sql/sql_statements/dml_commands/select.rst b/reference/sql/sql_statements/dml_commands/select.rst index bb1e44af4..60bf2fa0b 100644 --- a/reference/sql/sql_statements/dml_commands/select.rst +++ b/reference/sql/sql_statements/dml_commands/select.rst @@ -12,6 +12,7 @@ When used alone, the statement is known as a "``SELECT`` statement" or "``SELECT .. contents:: In this topic: :local: + :depth: 1 Permissions =========== @@ -111,6 +112,8 @@ Elements - Restricts the operation to only retrieve the first ``num_rows`` rows. * - ``UNION ALL`` - Concatenates the results of two queries together. ``UNION ALL`` does not remove duplicates. + * - ``TOP`` + - Limits the number of rows returned by a query. The ``TOP`` clause takes a numeric expression and a **subtraction** :ref:`arithmetic operator<arithmetic_operators>` ``TOP(a-b)``. Notes ===== diff --git a/releases/4.7.rst b/releases/4.7.rst index 670b5633e..9ccf318b0 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -43,6 +43,13 @@ New Features and Enhancements ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. +► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. + +► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: + +* :ref:`is_table_exists` +* :ref:`is_view_exists` + ► Multi-platform CLI From 7bcd37e111197a1ede42a08e83d6402ce6958360 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:16:13 +0200 Subject: [PATCH 1240/1892] 4.7 --- reference/cli/metadata_server.rst | 14 +++++------ releases/4.7.rst | 39 ++++++++++++++++++++++++++++++- releases/index.rst | 5 ++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 1393d436a..5658b4c87 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -1,15 +1,15 @@ .. _metadata_server_cli_reference: -************************* +*************** metadata_server -************************* +*************** SQream DB's cluster manager/coordinator is called ``metadata_server``. In general, you should not need to run ``metadata_server`` manually, but it is sometimes useful for testing. Command Line Arguments -================================== +====================== .. list-table:: :widths: 2 3 5 @@ -42,10 +42,10 @@ Command Line Arguments Starting metadata server -============================ +======================== Starting temporarily ---------------------- +-------------------- .. code-block:: console @@ -59,7 +59,7 @@ Using ``nohup`` and ``&`` sends metadata server to run in the background. * The default listening port is 3105 Starting temporarily with non-default port ------------------------------------------------- +------------------------------------------ To use a non-default port, specify the logging path as well. @@ -75,7 +75,7 @@ Using ``nohup`` and ``&`` sends metadata server to run in the background. * The listening port is 9241 Stopping metadata server ----------------------------- +------------------------ To stop metadata server: diff --git a/releases/4.7.rst b/releases/4.7.rst index 9ccf318b0..46f30fe76 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -4,7 +4,7 @@ Release Notes 4.7 ***************** -The 4.7 release notes were released on XXXXX, 2024 +The 4.7 release notes were released on March XX, 2024 .. contents:: :local: @@ -52,6 +52,43 @@ New Features and Enhancements ► Multi-platform CLI +► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. + +:ref:`metadata_server_cli_reference` + +* Using the ``metadata_server_config.json`` file: + + .. code-block:: json + + { + "logPath": "home/logs/my_logs" + } + +* Using the CLI: + + .. code-block:: console + + ./metadata_server --log_path=home/logs/my_logs + +:ref:`server_picker_cli_reference` + + Using the CLI: + + .. code-block:: console + + ./server_picker --log_path=home/logs/my_logs + +:ref:`Worker<current_method_modification_methods>` + + Using the ``sqream_config_legacy.json``: + + .. code-block:: json + + { + "DefaultPathToLogs": "home/logs/my_logs" + } + + diff --git a/releases/index.rst b/releases/index.rst index 347cacef1..4b082aa8b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,11 @@ Release Notes ************* +:ref:`Version 4.7 - March XX, 2024<4.7>` + +* +* + :ref:`Version 4.6 - February 19, 2024<4.6>` * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. From 1172c2c0ff74b2c21974dcf77d823bdc17909ea0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Mar 2024 12:26:31 +0200 Subject: [PATCH 1241/1892] 4.7 --- reference/cli/metadata_server.rst | 3 ++- reference/cli/server_picker.rst | 3 +++ releases/4.7.rst | 8 ++++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/reference/cli/metadata_server.rst b/reference/cli/metadata_server.rst index 5658b4c87..89bf3cae7 100644 --- a/reference/cli/metadata_server.rst +++ b/reference/cli/metadata_server.rst @@ -25,7 +25,7 @@ Command Line Arguments - ``3105`` - The metadata server listening port * - ``--log_path`` - - ``./metadata_server_log`` + - ``./metadata_server_logs`` - The ``metadata_server`` log file output contains information about the activities and events related to the metadata server of a system. * - ``--log4_config`` - None @@ -39,6 +39,7 @@ Command Line Arguments * - ``--help`` - None - Used to display a help message or documentation for a particular program or command. + Starting metadata server diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index b4a44af4a..ecbeffe1c 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -43,6 +43,9 @@ Parameters * - ``--help`` - None - Used to display a help message or documentation for a particular program or command + * - ``--log_path`` + - ``./server_picker_logs`` + - Configures the default location for the log file Example --------- diff --git a/releases/4.7.rst b/releases/4.7.rst index 46f30fe76..9a1000e82 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -61,14 +61,14 @@ New Features and Enhancements .. code-block:: json { - "logPath": "home/logs/my_logs" + "logPath": "<home/logs/my_logs>" } * Using the CLI: .. code-block:: console - ./metadata_server --log_path=home/logs/my_logs + ./metadata_server --log_path=<home/logs/my_logs> :ref:`server_picker_cli_reference` @@ -76,7 +76,7 @@ New Features and Enhancements .. code-block:: console - ./server_picker --log_path=home/logs/my_logs + ./server_picker --log_path=<home/logs/my_logs> :ref:`Worker<current_method_modification_methods>` @@ -85,7 +85,7 @@ New Features and Enhancements .. code-block:: json { - "DefaultPathToLogs": "home/logs/my_logs" + "DefaultPathToLogs": "<home/logs/my_logs>" } From 7148659acee386e9e4c3d90fa6d234d9ab2a251e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:02:55 +0200 Subject: [PATCH 1242/1892] 4.7 --- .../scalar_functions/conditionals/is_view_exists.rst | 2 +- releases/4.7.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst b/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst index ca6152c59..d98408683 100644 --- a/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst +++ b/reference/sql/sql_functions/scalar_functions/conditionals/is_view_exists.rst @@ -11,7 +11,7 @@ Syntax .. code-block:: postgres - SELECT is_view_exists(<'schema_name'>, <'table_name'>) + SELECT is_view_exists(<'schema_name'>, <'view_name'>) Arguments diff --git a/releases/4.7.rst b/releases/4.7.rst index 9a1000e82..f7e0bde05 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -52,6 +52,8 @@ New Features and Enhancements ► Multi-platform CLI +► + ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. :ref:`metadata_server_cli_reference` From c743e15b03a768dc8bbfe1f2205f883fe8a8b7f5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:08:30 +0200 Subject: [PATCH 1243/1892] Update 4.7.rst --- releases/4.7.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/releases/4.7.rst b/releases/4.7.rst index f7e0bde05..5825b1fe7 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -54,6 +54,10 @@ New Features and Enhancements ► +Flag: ``ldapGetAttributeList`` - Declare in a list format which LDAP attributes are required to be seen for each role in MD. + +Utility function: ``SELECT ldap_get_attr()`` - Shows required attributes mentioned in ``ldapGetAttributeList`` per MD role. + ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. :ref:`metadata_server_cli_reference` From 8595e77b7230ef580beabe72a30ba88e058df32d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Mar 2024 11:53:32 +0200 Subject: [PATCH 1244/1892] LDAP user attributes --- configuration_guides/ldap.rst | 58 +++++++++++-------- reference/sql/sql_statements/index.rst | 10 ++-- .../utility_commands/ldap_get_attr.rst | 42 ++++++++++++++ releases/4.7.rst | 8 +-- 4 files changed, 84 insertions(+), 34 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/ldap_get_attr.rst diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 6c18da2d3..e7f631354 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -33,14 +33,14 @@ Basic Method A traditional approach to authentication in which the user provides a username and password combination to authenticate with the LDAP server. In this approach, all users are given access to SQream. -Flag Attributes -^^^^^^^^^^^^^^^ +Flags +^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - Attribute + * - Flag - Description * - ``authenticationMethod`` - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap`` @@ -63,37 +63,37 @@ Basic Method Configuration Only roles with admin privileges or higher may enable LDAP Authentication. -1. Set the ``authenticationMethod`` attribute: +1. Set the ``authenticationMethod`` flag: .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; -2. Set the ``ldapIpAddress`` attribute: +2. Set the ``ldapIpAddress`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapIpAddress = '<ldaps://...>'; -3. Set the ``ldapPrefix`` attribute: +3. Set the ``ldapPrefix`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapPrefix = '<DN_binding_string_prefix>='; -4. Set the ``ldapSuffix`` attribute: +4. Set the ``ldapSuffix`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapSuffix = '<DN_binding_string_suffix>'; -5. To set the ``ldapPort`` attribute (Optional), run: +5. To set the ``ldapPort`` flag (optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapPort = <port_number> -6. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: +6. To set the ``ldapConnTimeoutSec`` flag (optional), run: .. code-block:: postgres @@ -129,14 +129,14 @@ Advanced Method This method lets users be grouped into categories. Each category can then be given or denied access to SQreamDB, giving administrators control over access. -Flag Attributes -^^^^^^^^^^^^^^^ +Flags +^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - Attribute + * - Flag - Description * - ``authenticationMethod`` - Configure an authentication method: ``sqream`` or ``ldap``. To configure LDAP authentication, choose ``ldap`` @@ -158,6 +158,8 @@ Flag Attributes - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used * - ``ldapSearchFilter`` - Filters ``ldapAdvancedMode`` authentication. ``ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)';`` + * - ``ldapGetAttributeList`` + - Enables you to include LDAP user attributes, as they appear in LDAP, in your SQreamDB metadata. After having set this flag, you may execute the :ref:`ldap_get_attr` utility function which will show you the attribute values associated with each SQreamDB role. Preparing LDAP Users @@ -201,67 +203,75 @@ Advanced Method Configuration Only roles with admin privileges and higher may enable LDAP Authentication. -1. Set the ``authenticationMethod`` attribute: +1. Set the ``authenticationMethod`` flag: .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; -2. Set the ``ldapAdvancedMode`` attribute: +2. Set the ``ldapAdvancedMode`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapAdvancedMode = true; -3. Set the ``ldapIpAddress`` attribute: +3. Set the ``ldapIpAddress`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapIpAddress = '<ldaps://<IpAddress>'; -4. Set the ``ldapBindDn`` attribute: +4. Set the ``ldapBindDn`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapBindDn = <binding_user_DN>; -5. Set the ``ldapBindDnPassword`` attribute: +5. Set the ``ldapBindDnPassword`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapBindDnPassword = '<binding_user_password>'; -6. Set the ``ldapBaseDn`` attribute: +6. Set the ``ldapBaseDn`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapBaseDn = '<search_root_DN>'; -7. Set the ``ldapSearchAttribute`` attribute: +7. Set the ``ldapSearchAttribute`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapSearchAttribute = '<search_attribute>'; -8. To set the ``ldapSearchFilter`` attribute (Optional), run: +8. To set the ``ldapSearchFilter`` flag (optional), run: .. code-block:: postgres - ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)(…)'; + ALTER SYSTEM SET ldapSearchFilter = '(<attribute>=<value>)(<attribute2>=<value2>)[...]'; -9. To set the ``ldapPort`` attribute (Optional), run: +9. To set the ``ldapPort`` flag (optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapPort = <port_number> -10. To set the ``ldapConnTimeoutSec`` attribute (Optional), run: +10. To set the ``ldapConnTimeoutSec`` flag (optional), run: .. code-block:: postgres ALTER SYSTEM SET ldapConnTimeoutSec = <15>; + +11. To set the ``ldapGetAttributeList`` flag (optional), run: + + .. code-block:: postgres + + ALTER SYSTEM SET ldapGetAttributeList = <'ldap_attribute1'>,<'ldap_attribute2'>,<'ldap_attribute3'>,[,...]; + + a. To see the LDAP user attributes associated with SQreamDB roles in your metadata, execute the :ref:`ldap_get_attr` utility function. -11. Restart all sqreamd servers. +12. Restart all sqreamd servers. Example ^^^^^^^ diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index cf93d9be6..013721e4b 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -126,7 +126,7 @@ The following table shows the Utility commands: * - :ref:`GET DDL<get_ddl>` - View the ``CREATE TABLE`` statement for a table * - :ref:`GET FUNCTION DDL<get_function_ddl>` - - View the ``CREATE FUNCTION`` statement for a UDF + - View the ``CREATE FUNCTION`` statement for a UDF * - :ref:`GET LICENSE INFO<get_license_info>` - View a user's license information * - :ref:`GPU METRICS<select_gpu_metrics>` @@ -136,11 +136,13 @@ The following table shows the Utility commands: * - :ref:`GET VIEW DDL<get_view_ddl>` - View the ``CREATE VIEW`` statement for a view * - :ref:`HEALTH CHECK MONITORING<select_health_check_monitoring>` - - Returns system health monitoring logs + - Returns system health monitoring logs + * - :ref:`LDAP GET ATTR<ldap_get_attr>` + - Enables you to specify the LDAP attributes you want the SQreamDB role catalog table to show * - :ref:`LIST SAVED QUERIES<list_saved_queries>` - - Lists previously saved query names, one per row. + - Lists previously saved query names, one per row * - :ref:`RECHUNK<rechunk>` - - + - Enables you to merge small data chunks into larger ones * - :ref:`RECOMPILE SAVED QUERY<recompile_saved_query>` - Recompiles a saved query that has been invalidated due to a schema change * - :ref:`RECOMPILE VIEW<recompile_view>` diff --git a/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst b/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst new file mode 100644 index 000000000..a9bf67aff --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst @@ -0,0 +1,42 @@ +.. _ldap_get_attr: + +************* +LDAP GET ATTR +************* + +The ``ldap_get_attr()`` utility function may be used only after having set :ref:`ldap` as your authentication service. This function enables you to specify LDAP attributes you want your SQreamDB role catalog table to include when executing ``SELECT`` on the ``sqream_catalog.roles`` metadata object. + +Syntax +========== + +.. code-block:: postgres + + SELECT ldap_get_attr() + +Example +======= + +Assume the following LDAP attributes are set to be associated with SQreamDB roles: + +* distinguishedName +* primaryGroupID +* userprincipalname + +.. code-block:: psql + + SELECT ldap_get_attr(); + +Output + +.. code-block:: console + + role_name | distinguishedName | primaryGroupID| userprincipalname + ------------------+-------------------------------------------+---------------+--------------------- + public | | | + sqream | CN=sqream,OU=Sqream Users,DC=sqream,DC=loc| 513 | sqream@sqream.loc + test_user | CN=test_user,OU=test,DC=sqream,DC=loc | 513 | test_user@sqream.loc + +Permissions +=========== + +Using the ``ldap_get_attr`` command requires no special permissions. \ No newline at end of file diff --git a/releases/4.7.rst b/releases/4.7.rst index 5825b1fe7..3c4a0f71e 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -50,13 +50,9 @@ New Features and Enhancements * :ref:`is_table_exists` * :ref:`is_view_exists` -► Multi-platform CLI - -► +► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. -Flag: ``ldapGetAttributeList`` - Declare in a list format which LDAP attributes are required to be seen for each role in MD. - -Utility function: ``SELECT ldap_get_attr()`` - Shows required attributes mentioned in ``ldapGetAttributeList`` per MD role. +► Multi-platform CLI ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. From 2ff0f76158c352c59b6eb3d2803141f3a5b41407 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Mar 2024 14:54:28 +0200 Subject: [PATCH 1245/1892] Update is_castable.rst --- .../scalar_functions/conversion/is_castable.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst index 328a2eaa5..4633eeab2 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -22,12 +22,12 @@ Syntax | BIGINT | REAL | DOUBLE - | FLOAT + | FLOAT | TEXT | NUMERIC | DATE | DATETIME - | ARRAY + | ARRAY , BOOL | TINYINT | SMALLINT @@ -35,12 +35,12 @@ Syntax | BIGINT | REAL | DOUBLE - | FLOAT + | FLOAT | TEXT | NUMERIC | DATE | DATETIME - | ARRAY + | ARRAY ) -- Checking if cast is supported for columns: @@ -55,12 +55,12 @@ Syntax | BIGINT | REAL | DOUBLE - | FLOAT + | FLOAT | TEXT | NUMERIC | DATE | DATETIME - | ARRAY + | ARRAY ) FROM <table_name>; From 9241ef6bd5ebb2abd6bef354fdaaec6765267e14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Mar 2024 16:13:24 +0200 Subject: [PATCH 1246/1892] Update 4.3.rst --- releases/4.3.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.3.rst b/releases/4.3.rst index fd8244ceb..e5cdbba1f 100644 --- a/releases/4.3.rst +++ b/releases/4.3.rst @@ -62,6 +62,8 @@ Known Issues * Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression +* In SQreamDB minor versions 4.3.9 and 4.3.10, granting permissions through the Acceleration Studio might result in an error, even though the permission has been successfully granted. + Version 4.3 resolved Issues --------------------------- From 4656971bfd67ed082ae58d2dde681ed210dc32c7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 21 Mar 2024 16:44:23 +0200 Subject: [PATCH 1247/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 49413e8d1..1cdc8439e 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -181,7 +181,7 @@ Creating a Standard Connection database='<database_name>') engine = sa.create_engine(engine_url,connect_args={"clustered": False, "service": "<service_name>"}) - session = orm.sessionmaker(bind=engine)() + Pulling a Table into Pandas From 7f238ef4c6afa7eef6f3968530566fae4edd0057 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 25 Mar 2024 08:13:44 +0200 Subject: [PATCH 1248/1892] Update remedying_slow_queries.rst --- troubleshooting/remedying_slow_queries.rst | 128 ++++++++++----------- 1 file changed, 60 insertions(+), 68 deletions(-) diff --git a/troubleshooting/remedying_slow_queries.rst b/troubleshooting/remedying_slow_queries.rst index 2c18f5278..c8e7c5896 100644 --- a/troubleshooting/remedying_slow_queries.rst +++ b/troubleshooting/remedying_slow_queries.rst @@ -4,76 +4,68 @@ Remedying Slow Queries *********************** -The **Remedying Slow Queries** page describes how to troubleshoot the causes of slow queries. - -The following table is a checklist you can use to identify the cause of your slow queries: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Step - - Description - - Results - * - 1 - - A single query is slow - - - If a query isn't performing as you expect, follow the :ref:`Query best practices<query_best_practices>` part of the :ref:`sql_best_practices` guide. - - If all queries are slow, continue to step 2. - * - 2 - - All queries on a specific table are slow - - - #. If all queries on a specific table aren't performing as you expect, follow the :ref:`Table design best practices<table_design_best_practices>` part of the :ref:`sql_best_practices` guide. - #. Check for active delete predicates in the table. Consult the :ref:`delete_guide` guide for more information. - - If the problem spans all tables, continue to step 3. - * - 3 - - Check that all workers are up - - - Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. - - If the worker list is incomplete, locate and start the missing worker(s). - - If all workers are up, continue to step 4. - * - 4 - - Check that all workers are performing well - - - #. Identify if a specific worker is slower than others by running the same query on different workers. (e.g. by connecting directly to the worker or through a service queue) - #. If a specific worker is slower than others, investigate performance issues on the host using standard monitoring tools (e.g. ``top``). - #. Restart SQream DB workers on the problematic host. - - If all workers are performing well, continue to step 5. - * - 5 - - Check if the workload is balanced across all workers - - - #. Run the same query several times and check that it appears across multiple workers (use ``SELECT show_server_status()`` to monitor) - #. If some workers have a heavier workload, check the service queue usage. Refer to the :ref:`workload_manager` guide. +This page describes how to troubleshoot the causes of slow queries. + +Slow queries may be the result of various factors, including inefficient query practices, suboptimal table designs, or issues with system resources. If you're experiencing sluggish query performance, it's essential to diagnose and address the underlying causes promptly. + +.. glossary:: + + Step 1: A single query is slow + If a query isn't performing as you expect, follow the :ref:`Query best practices<query_best_practices>` part of the :ref:`sql_best_practices` guide. - If the workload is balanced, continue to step 6. - * - 6 - - Check if there are long running statements - - - #. Identify any currently running statements (use ``SELECT show_server_status()`` to monitor) - #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. - #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement(<statement id>)``). + If all queries are slow, continue to step 2. + + Step 2: All queries on a specific table are slow + #. If all queries on a specific table aren't performing as you expect, follow the :ref:`Table design best practices<table_design_best_practices>` part of the :ref:`sql_best_practices` guide. + #. Check for active delete predicates in the table. Consult the :ref:`delete_guide` guide for more information. - If the statement does not stop correctly, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. + If the problem spans all tables, continue to step 3. + + + Step 3: Check that all workers are up + Use ``SELECT show_cluster_nodes();`` to list the active cluster workers. - If there are no long running statements or this does not help, continue to step 7. - * - 7 - - Check if there are active locks - - - #. Use ``SELECT show_locks()`` to list any outstanding locks. - #. If a statement is locking some objects, consider waiting for that statement to end or stop it. - #. If after a statement is completed the locks don't free up, refer to the :ref:`concurrency_and_locks` guide. + If the worker list is incomplete, locate and start the missing worker(s). - If performance does not improve after the locks are released, continue to step 8. - * - 8 - - Check free memory across hosts - - - #. Check free memory across the hosts by running ``$ free -th`` from the terminal. - #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`spooling` guide. - #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. + If all workers are up, continue to step 4. + + Step 4: Check that all workers are performing well + + #. Identify if a specific worker is slower than others by running the same query on different workers. (e.g. by connecting directly to the worker or through a service queue) + #. If a specific worker is slower than others, investigate performance issues on the host using standard monitoring tools (e.g. ``top``). + #. Restart SQream DB workers on the problematic host. + + If all workers are performing well, continue to step 5. + + Step 5: Check if the workload is balanced across all workers + + #. Run the same query several times and check that it appears across multiple workers (use ``SELECT show_server_status()`` to monitor) + #. If some workers have a heavier workload, check the service queue usage. Refer to the :ref:`workload_manager` guide. - If performance does not improve, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. \ No newline at end of file + If the workload is balanced, continue to step 6. + + Step 6: Check if there are long running statements + + #. Identify any currently running statements (use ``SELECT show_server_status()`` to monitor) + #. If there are more statements than available resources, some statements may be in an ``In queue`` mode. + #. If there is a statement that has been running for too long and is blocking the queue, consider stopping it (use ``SELECT stop_statement(<statement id>)``). + + If the statement does not stop correctly, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. + + If there are no long running statements or this does not help, continue to step 7. + + Step 7: Check if there are active locks + + #. Use ``SELECT show_locks()`` to list any outstanding locks. + #. If a statement is locking some objects, consider waiting for that statement to end or stop it. + #. If after a statement is completed the locks don't free up, refer to the :ref:`concurrency_and_locks` guide. + + If performance does not improve after the locks are released, continue to step 8. + + Step 8: Check free memory across hosts + + #. Check free memory across the hosts by running ``$ free -th`` from the terminal. + #. If the machine has less than 5% free memory, consider **lowering** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. Refer to the :ref:`spooling` guide. + #. If the machine has a lot of free memory, consider **increasing** the ``limitQueryMemoryGB`` and ``spoolMemoryGB`` settings. + + If performance does not improve, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. \ No newline at end of file From e312238c94c264827d1f7a92197a73794fa06fe6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Mar 2024 15:27:50 +0200 Subject: [PATCH 1249/1892] array and is_castable --- data_type_guides/sql_data_type_array.rst | 184 +++++++++++------- .../conversion/is_castable.rst | 6 +- 2 files changed, 122 insertions(+), 68 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 863f2824c..0b9bc3a62 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -16,11 +16,6 @@ The maximum size of an ``ARRAY``, indicating the number of elements it can hold, .. seealso:: A full list of :ref:`data types<supported_data_types>` supported by SQreamDB. -Limitation -------------- - -Please note that SQLAlchemy does not support the ``ARRAY`` data type. - Syntax ====== @@ -28,9 +23,13 @@ Defining an ``ARRAY`` is done by appending the ``[]`` notation to a supported da .. code-block:: sql - CREATE TABLE <table_name> (<column1> TEXT[], <column2> INT[]) + CREATE TABLE + < table_name > (< column1 > TEXT [], < column2 > INT []) - INSERT INTO TABLE <table_name> VALUES (ARRAY['a','b','c'], ARRAY[1,2,NULL]) + INSERT INTO + TABLE < table_name > + VALUES + (ARRAY ['a','b','c'], ARRAY [1,2,NULL]) Supported Operators @@ -100,6 +99,10 @@ Supported Operators Examples ======== +.. contents:: + :local: + :depth: 1 + ``ARRAY`` Statements -------------------- @@ -107,19 +110,33 @@ Creating a table with arrayed columns: .. code-block:: sql - CREATE TABLE my_array (clmn1 TEXT[], clmn2 TEXT[], clmn3 INT[], clmn4 NUMERIC(38,20)[]); + CREATE TABLE + my_array ( + clmn1 TEXT [], + clmn2 TEXT [], + clmn3 INT [], + clmn4 NUMERIC(38, 20) [] + ); Inserting arrayed values into a table: .. code-block:: sql - INSERT INTO my_array VALUES (ARRAY['1','2','3'], ARRAY['4','5','6'], ARRAY[7,8,9,10]); + INSERT INTO + my_array + VALUES + ( + ARRAY ['1','2','3'], + ARRAY ['4','5','6'], + ARRAY [7,8,9,10] + ); Converting arrayed elements into a set of rows: .. code-block:: sql - SELECT UNNEST(ARRAY['1','2','3'], ARRAY['4','5','6']); + SELECT + UNNEST(ARRAY ['1','2','3'], ARRAY ['4','5','6']); .. code-block:: console @@ -133,9 +150,15 @@ Updating table values: .. code-block:: sql - UPDATE my_array SET clmn1[0] = 'A'; + UPDATE + my_array + SET + clmn1 [0] = 'A'; - SELECT * FROM my_array; + SELECT + * + FROM + my_array; .. code-block:: console @@ -150,48 +173,70 @@ Consider the following JSON file named ``t``, located under ``/tmp/``: .. code-block:: json - [{ - "name": "Avery Bradley", - "age": 25, - "position": "PG", - "years_in_nba": [2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] - }, - { - "name": "Jae Crowder", - "age": 25, - "position": "PG", - "years_in_nba": [2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021] - }, - { - "name": "John Holland", - "age": 27, - "position": "SG", - "years_in_nba": [2017, 2018] - } - ] + + { + "name": "Avery Bradley", + "age": 25, + "position": "PG", + "years_in_nba": [ + 2010, + 2011, + 2012, + 2013, + 2014, + 2015, + 2016, + 2017, + 2018, + 2019, + 2020, + 2021 + ] + }, + { + "name": "Jae Crowder", + "age": 25, + "position": "PG", + "years_in_nba": [ + 2012, + 2013, + 2014, + 2015, + 2016, + 2017, + 2018, + 2019, + 2020, + 2021 + ] + }, + { + "name": "John Holland", + "age": 27, + "position": "SG", + "years_in_nba": [ + 2017, + 2018 + ] + } +] Execute the following statement: .. code-block:: sql - CREATE FOREIGN TABLE nba - ( - name text, - age int, - position text, - years_in_nba int[] - ) - - WRAPPER json_fdw - OPTIONS - ( - location ='/tmp/t.json' - ) - ; + CREATE FOREIGN TABLE nba (name text, age int, position text, years_in_nba int []) + WRAPPER + json_fdw + OPTIONS + (location = '/tmp/t.json'); - SELECT * FROM nba; + SELECT + * + FROM + nba; -Result: +Output: .. code-block:: console @@ -204,19 +249,11 @@ Result: Limitations =========== -Connectors ------------- - -Limitations -=============== - -Please note that the SQreamDB ODBC and .NET connectors do not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using these connectors. - -Casting +Casting Limitations ------------------- -Numeric -^^^^^^^ +``NUMERIC`` +""""""""""" Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and ``BOOL``, must explicitly be cast. @@ -228,8 +265,8 @@ Numeric data types smaller than ``INT``, such as ``TINYINT``, ``SMALLINT``, and CREATE OR REPLACE TABLE my_array (clmn1 bool []); SELECT array_replace(clmn1 , 0::bool, 1::bool) FROM my_array; -TEXT -^^^^ +``TEXT`` +"""""""" Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not supported. @@ -241,11 +278,24 @@ Casting ``TEXT`` to non-``TEXT`` and non-``TEXT`` to ``TEXT`` data types is not INSERT INTO t_int VALUES (array[1,2,3]); INSERT INTO t_text SELECT xint::TEXT[] FROM t_int; -Function --------------------- +Connectors +---------- + +``.NET`` and ``ODBC`` +""""""""""""""""""""" + +Please note that the SQreamDB ODBC and .NET connectors do not support the use of ARRAY data types. If your database schema includes ARRAY columns, you may encounter compatibility issues when using these connectors. + +``Pysqream`` +"""""""""""" + +Please note that SQLAlchemy does not support the ``ARRAY`` data type. + +Functions +--------- -|| (Concatenate) -^^^^^^^^^^^^^^^^ +``|| (Concatenate)`` +"""""""""""""""""""" Using the ``||`` (Concatenate) function with two different data types requires explicit casting. @@ -253,13 +303,13 @@ Using the ``||`` (Concatenate) function with two different data types requires e SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) FROM my_array; -UNNEST -^^^^^^ +``UNNEST`` +"""""""""" It is possible to use the ``UNNEST`` operator within a statement only once. Window -^^^^^^ +"""""" Window functions are not supported. diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst index 4633eeab2..577bf4a52 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -4,7 +4,11 @@ IS CASTABLE ************ -The ``IsCastable`` function checks whether a data type cast operation is supported for any given rows. If the cast is not supported, the ``CASE`` statement handles the exception by providing an alternative. +The ``IsCastable`` function checks whether a data type cast operation is supported for any given row. If the cast is not supported, the ``CASE`` statement handles the exception by providing an alternative. + +.. tip:: + + See BLUE :ref:`supported casts table <supported_casts>` Syntax ====== From 334c15b43a8b1e2b7de6f0b8f554c890510752a1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:01:01 +0200 Subject: [PATCH 1250/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 357450a7d..ab4dc42f3 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -30,8 +30,10 @@ SQream supports the following three data conversion types: Supported Casts --------------- +The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. + +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME** | **VARCHAR**/**TEXT** | +| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME** | **VARCHAR**/**TEXT** | +==============================================+===========+==============================================+=================+==============+========================+=======================+ | **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ From dd4dd100c9955b741410cc857ef06061716677d0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:22:47 +0200 Subject: [PATCH 1251/1892] Update create_table.rst --- .../ddl_commands/create_table.rst | 69 ++++++++----------- 1 file changed, 30 insertions(+), 39 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 196e324af..9e0f81e59 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -17,8 +17,6 @@ The ``CREATE TABLE`` statement is used to create a new table in an existing data Syntax ====== -The following is the correct syntax for creating a table: - .. code-block:: postgres create_table_statement ::= @@ -68,30 +66,31 @@ The following parameters can be used when creating a table: See :ref:`cluster_by` for more information. * - ``LIKE`` - Duplicates the column structure of an existing table. - - -.. _default_values: Usage Notes =========== When using ``CREATE TABLE... LIKE``, the permissions from the source table are inherited by the newly created table. To add extra permissions to the new table, you can utilize the ``INCLUDE PERMISSIONS`` clause. +.. _default_values: + Default Value Constraints -=========================== +========================= The ``DEFAULT`` value constraint specifies a default value to use if none is provided in an :ref:`insert` or :ref:`copy_from` statement. This value can be a literal or ``NULL``. It's worth noting that even for nullable columns, you can still explicitly insert a ``NULL`` value using the ``NULL`` keyword, as demonstrated in the example: .. code-block:: postgres - INSERT INTO cool_animals VALUES (1, 'Gnu', NULL) + INSERT INTO + cool_animals + VALUES + (1, 'Gnu', NULL); Syntax ---------- +------ The following is the correct syntax for using the **DEFAULT** value constraints: - .. code-block:: postgres column_def :: = { column_name type_name [ default ] [ column_constraint ] } @@ -115,7 +114,7 @@ The following is the correct syntax for using the **DEFAULT** value constraints: .. _identity: Identity ------------------------ +-------- The ``Identity`` (or sequence) columns can be used for generating key values. Some databases call this ``AUTOINCREMENT``. @@ -138,9 +137,7 @@ The following table describes the identity parameters: - Incremental value that is added to the identity value of the previous row that was loaded. Examples -=========== - -This section includes the following examples: +======== .. contents:: :local: @@ -149,8 +146,6 @@ This section includes the following examples: Creating a Standard Table -------------------------- -The following is an example of the syntax used to create a standard table: - .. code-block:: postgres CREATE TABLE cool_animals ( @@ -161,10 +156,7 @@ The following is an example of the syntax used to create a standard table: ); Creating a Table with Default Value Constraints for Some Columns --------------------------------------------------------------------- - -The following is an example of the syntax used to create a table with default value constraints for some columns: - +---------------------------------------------------------------- .. code-block:: postgres @@ -178,10 +170,7 @@ The following is an example of the syntax used to create a table with default va .. note:: The nullable/non-nullable constraint appears at the end, after the default option Creating a Table with an Identity Column ---------------------------------------------------- - -The following is an example of the syntax used to create a table with an identity (auto-increment) column: - +---------------------------------------- .. code-block:: postgres @@ -193,25 +182,27 @@ The following is an example of the syntax used to create a table with an identit .. note:: Identity does not enforce the uniqueness of values. The identity value can be bypassed by specifying it in an :ref:`insert` command. -Creating a Table from a SELECT Query ------------------------------------------ - -The following is an example of the syntax used to create a table from a SELECT query: +Creating a Table from a ``SELECT`` Query +---------------------------------------- .. code-block:: postgres - CREATE TABLE users_uk AS SELECT * FROM users WHERE country = 'United Kingdom'; + CREATE TABLE + users_uk AS + SELECT + * + FROM + users + WHERE + country = 'United Kingdom'; -For more information on creating a new table from the results of a SELECT query, see :ref:`CREATE TABLE AS <create_table_as>`. +For more information on creating a new table from the results of a ``SELECT`` query, see :ref:`CREATE TABLE AS <create_table_as>`. Creating a Table with a Clustering Key ----------------------------------------------- - -When data in a table is stored in a sorted order, the sorted columns are considered clustered. Good clustering can have a significant positive impact on performance. +-------------------------------------- -In the following example, we expect the ``start_date`` column to be naturally clustered, as new users sign up and get a newer start date. -When the clustering key is set, if the incoming data isn’t naturally clustered, it will be clustered by SQream DB during insert or bulk load. +When data within a table is organized in a sorted manner, the columns responsible for this sorting are termed as clustered. Effective clustering can greatly enhance performance. For instance, in the scenario provided, the ``start_date`` column is anticipated to naturally cluster due to the continuous influx of new users and their corresponding start dates. However, in cases where the clustering of incoming data isn't inherent, SQreamDB will automatically cluster it during insertion or bulk loading processes once the clustering key is set. The following is an example of the syntax used to create a table with a clustering key: @@ -226,10 +217,10 @@ The following is an example of the syntax used to create a table with a clusteri For more information on data clustering, see :ref:`cluster_by`. Duplicating the Column Structure of an Existing Table ------------------------------------------------------------- +----------------------------------------------------- Syntax -************ +****** The following is the correct syntax for duplicating the column structure of an existing table: @@ -244,7 +235,7 @@ The following is the correct syntax for duplicating the column structure of an e ; Examples -************** +******** This section includes the following examples of duplicating the column structure of an existing table using the ``LIKE`` clause: @@ -253,7 +244,7 @@ This section includes the following examples of duplicating the column structure :depth: 3 Creating a Table Using an Explicit Column List -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The following is an example of creating a table using an explicit column list: @@ -262,7 +253,7 @@ The following is an example of creating a table using an explicit column list: CREATE TABLE t1(x int default 0 not null, y text(10) null); Creating a Second Table Based on the Structure of Another Table -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Either of the following examples can be used to create a second table based on the structure of another table. From 99d516d62b7756e0f115a3a0f55f693cc3ae279a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 27 Mar 2024 21:13:14 +0200 Subject: [PATCH 1252/1892] Update ingesting_data.rst --- data_ingestion/ingesting_data.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index e069b25be..1a3200512 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -136,6 +136,11 @@ Handing Extended Errors While you can use foreign tables to load CSVs, the ``COPY FROM`` statement provides more fine-grained error handling options and extended support for non-standard CSVs with multi-character delimiters, alternate timestamp formats, and more. For more information, see :ref:`foreign tables<foreign_tables>`. + +Foreign Data Wrapper Best Practice +================================== + +A recommended approach when working with :ref:`foreign_tables` and Foreign Data Wrapper (FDW) is storing files belonging to distinct file families and files with similar schemas in separate folders. Best Practices for CSV ---------------------- From a0447728fee5a3abd50393a1c9e8e3dec263c391 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 28 Mar 2024 17:42:11 +0200 Subject: [PATCH 1253/1892] Align file types --- data_ingestion/avro.rst | 210 ++++++++++++++++++------------- data_ingestion/csv.rst | 249 ++++++++++++++++++++++++++++--------- data_ingestion/json.rst | 2 +- data_ingestion/orc.rst | 166 ++++++++++++++++--------- data_ingestion/parquet.rst | 160 +++++++++++++++--------- 5 files changed, 528 insertions(+), 259 deletions(-) diff --git a/data_ingestion/avro.rst b/data_ingestion/avro.rst index 8fe2b13ff..64aac34a1 100644 --- a/data_ingestion/avro.rst +++ b/data_ingestion/avro.rst @@ -11,7 +11,7 @@ Avro :depth: 1 Foreign Data Wrapper Prerequisites -=================================== +================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: @@ -62,24 +62,21 @@ The following example shows the correct file structure used to create the ``CREA .. code-block:: postgres - CREATE TABLE ext_nba - ( - - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) - WRAPPER avro_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.avro' - ); + CREATE TABLE nba ( + name TEXT(40), + team TEXT(40), + number BIGINT, + position TEXT(2), + age BIGINT, + height TEXT(4), + weight BIGINT, + college TEXT(40), + salary FLOAT + ) + WRAPPER + avro_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/nba.avro'); .. tip:: @@ -103,24 +100,21 @@ The following example shows the correct file structure used to create the ``CREA .. code-block:: postgres - CREATE FOREIGN TABLE ext_nba - ( - - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) - WRAPPER avro_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.avro' - ); + CREATE FOREIGN TABLE nba ( + name TEXT(40), + team TEXT(40), + number BIGINT, + position TEXT(2), + age BIGINT, + height TEXT(4), + weight BIGINT, + college TEXT(40), + salary FLOAT + ) + WRAPPER + avro_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/nba.avro'); .. tip:: @@ -241,9 +235,11 @@ Before ingesting data into SQream from an Avro file, you must create a table usi .. code-block:: postgres - COPY [schema name.]table_name - FROM WRAPPER fdw_name - ; + COPY + [<schema name>.] <table_name> + FROM + WRAPPER + fdw_<name>; After creating a table you can ingest data from an Avro file into SQream using the following syntax: @@ -258,13 +254,13 @@ The following is an example of creating a table: .. code-block:: postgres - COPY t - FROM WRAPPER fdw_name - OPTIONS - ( - [ copy_from_option [, ...] ] - ) - ; + COPY + < table_name > + FROM + WRAPPER + fdw_name + OPTIONS + ([ <copy_from_option> [, ...] ]); The following is an example of loading data from an Avro file into SQream: @@ -273,7 +269,7 @@ The following is an example of loading data from an Avro file into SQream: WRAPPER avro_fdw OPTIONS ( - LOCATION = 's3://sqream-demo-data/nba.avro' + LOCATION = 's3://sqream-docs/nba.avro' ); For more examples, see :ref:`additional_examples`. @@ -301,19 +297,20 @@ The following is an example of the output based on the **nba.avro** table: .. code-block:: psql - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + SELECT * FROM ext_nba LIMIT 10; + + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 .. note:: If your table output has errors, verify that the structure of the Avro files correctly corresponds to the foreign table structure that you created. @@ -337,8 +334,20 @@ In the example below, the ``Position`` column is not supported due its type. .. code-block:: postgres - CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + CREATE TABLE + nba AS + SELECT + Name, + Team, + Number, + NULL as Position, + Age, + Height, + Weight, + College, + Salary + FROM + ext_nba; Modifying Data Before Loading ----------------------------- @@ -351,10 +360,21 @@ In the example below, the ``Position`` column is set to the default ``NULL``. .. code-block:: postgres - CREATE FOREIGN TABLE nba AS - SELECT name, team, number, NULL as Position, age, height, (weight / 2.205) as weight, college, salary - FROM ext_nba - ORDER BY weight; + CREATE FOREIGN TABLE nba AS + SELECT + name, + team, + number, + NULL as Position, + age, + height, + (weight / 2.205) as weight, + college, + salary + FROM + ext_nba + ORDER BY + weight; Loading a Table from a Directory of Avro Files on HDFS ------------------------------------------------------ @@ -363,15 +383,24 @@ The following is an example of loading a table from a directory of Avro files on .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER avro_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.avro' - ); + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + avro_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.avro' + ); - CREATE TABLE users AS SELECT * FROM ext_users; + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. @@ -382,13 +411,26 @@ The following is an example of loading a table from a directory of Avro files on .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER avro_fdw - OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.avro', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + avro_fdw + OPTIONS + ( + LOCATION = 's3:/sqream-docs/users/*.avro', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; + - CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 2fe6b16a8..e7dc19ddf 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -94,18 +94,18 @@ We will make note of the file structure to create a matching ``CREATE TABLE`` st .. code-block:: postgres - CREATE TABLE nba - ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float - ); + CREATE TABLE + nba ( + Name text(40), + Team text(40), + Number tinyint, + Position text(2), + Age tinyint, + Height text(4), + Weight real, + College text(40), + Salary float + ); Bulk load the data with COPY FROM @@ -118,28 +118,34 @@ The CSV is a standard CSV, but with two differences from SQream DB defaults: * The first row of the file is a header containing column names, which we'll want to skip. .. code-block:: postgres - - COPY nba - FROM 's3://sqream-demo-data/nba.csv' - WITH RECORD DELIMITER '\r\n' - OFFSET 2; - -Repeat steps 3 and 4 for every CSV file you want to import. + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + RECORD_DELIMITER = '\r\n', + OFFSET = 2; + ); -Loading different types of CSV files -==================================== - -:ref:`copy_from` contains several configuration options. See more in :ref:`the COPY FROM elements section<copy_from_config_options>`. +Repeat steps 3 and 4 for every CSV file you want to import. -Loading a standard CSV file from a local filesystem +Loading a standard CSV File From a Local Filesystem --------------------------------------------------- .. code-block:: postgres - COPY table_name FROM '/home/rhendricks/file.csv'; + COPY + table_name + FROM + WRAPPER + csv_fdw + OPTIONS (LOCATION = '/home/rhendricks/file.csv'); Loading a PSV (pipe separated value) file @@ -147,14 +153,32 @@ Loading a PSV (pipe separated value) file .. code-block:: postgres - COPY table_name FROM '/home/rhendricks/file.psv' WITH DELIMITER '|'; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = '|' + ); Loading a TSV (tab separated value) file ---------------------------------------- .. code-block:: postgres - COPY table_name FROM '/home/rhendricks/file.tsv' WITH DELIMITER '\t'; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = '\t'; + ); Loading a text file with non-printable delimiter ------------------------------------------------ @@ -163,18 +187,36 @@ In the file below, the separator is ``DC1``, which is represented by ASCII 17 de .. code-block:: postgres - COPY table_name FROM 'file.txt' WITH DELIMITER E'\021'; - -Loading a text file with multi-character delimiters + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = E'\021' + ); + +Loading a Text File With Multi-Character Delimiters --------------------------------------------------- In the file below, the separator is ``'|``. .. code-block:: postgres - COPY table_name FROM 'file.txt' WITH DELIMITER '''|'; - -Loading files with a header row + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = '''|' + ); + +Loading Files With a Header Row ------------------------------- Use ``OFFSET`` to skip rows. @@ -183,32 +225,74 @@ Use ``OFFSET`` to skip rows. .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' OFFSET 2; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = '|', + OFFSET 2 + ); .. _changing_record_delimiter: -Loading files formatted for Windows (``\r\n``) +Loading Files Formatted for Windows (``\r\n``) ---------------------------------------------- .. code-block:: postgres - COPY table_name FROM 'filename.psv' WITH DELIMITER '|' RECORD DELIMITER '\r\n'; - -Loading a file from a public S3 bucket + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DELIMITER = '|', + RECORD_DELIMITER = '\r\n' + ); + +Loading a File From a Public S3 Bucket -------------------------------------- .. note:: The bucket must be publicly available and objects can be listed .. code-block:: postgres - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + OFFSET = 2, + RECORD_DELIMITER = '\r\n' + ); Loading files from an authenticated S3 bucket --------------------------------------------- .. code-block:: postgres - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' AWS_SECRET 'super_secretive_secret'; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + OFFSET = 2, + RECORD_DELIMITER = '\r\n', + AWS_ID = '12345678', + AWS_SECRET = 'super_secretive_secret' + ); .. _hdfs_copy_from_example: @@ -217,8 +301,17 @@ Loading files from an HDFS storage .. code-block:: postgres - COPY nba FROM 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; - + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', + OFFSET = 2, + RECORD DELIMITER = '\r\n' + ); Saving rejected rows to a file ------------------------------ @@ -227,24 +320,41 @@ See :ref:`capturing_rejected_rows` for more information about the error handling .. code-block:: postgres - COPY table_name FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/file.psv' - ,delimiter = '|' - ,continue_on_error = True - ,error_log = '/temp/load_error.log' -- Save error log - ,rejected_data = '/temp/load_rejected.log' -- Only save rejected rows - ); - + COPY + t + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = '/tmp/file.psv', + DELIMITER = '|', + CONTINUE_ON_ERROR = True, + ERROR_LOG = '/temp/load_error.log' -- Save error log, + REJECTED_DATA = '/temp/load_rejected.log' -- Only save rejected rows + ); Stopping the load if a certain amount of rows were rejected ----------------------------------------------------------- .. code-block:: postgres - COPY table_name FROM 'filename.csv' WITH delimiter '|' - ERROR_LOG '/temp/load_err.log' -- Save error log - OFFSET 2 -- skip header row - LIMIT 100 -- Only load 100 rows - STOP AFTER 5 ERRORS; -- Stop the load if 5 errors reached + COPY + table + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 'filename.csv', + DELIMITER = '|', + ERROR_LOG = '/temp/load_err.log', -- Save error log + OFFSET = 2 -- skip header row + ) + LIMIT 100 -- Only load 100 rows + STOP AFTER 5 ERRORS; + + -- Stop the load if 5 errors reached; Load CSV files from a set of directories ---------------------------------------- @@ -253,7 +363,15 @@ Use glob patterns (wildcards) to load multiple files to one table. .. code-block:: postgres - COPY table_name from '/path/to/files/2019_08_*/*.csv'; + COPY + table + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = '/path/to/files/2019_08_*/*.csv' + ); Rearrange destination columns @@ -263,7 +381,15 @@ When the source of the files does not match the table structure, tell the ``COPY .. code-block:: postgres - COPY table_name (fifth, first, third) FROM '/path/to/files/*.csv'; + COPY + table (fifth, first, third) + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = '/path/to/files/*.csv' + ); .. note:: Any column not specified will revert to its default value or ``NULL`` value if nullable @@ -276,6 +402,15 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. .. code-block:: postgres - COPY table_name FROM '/path/to/files/*.csv' WITH PARSERS 'date_col1=YMD,date_col2=MDY,date_col3=default'; + COPY + nba + FROM + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/nba.csv', + DATETIME_FORMAT = 'date_col1=YMD,date_col2=MDY,date_col3=default' + ); .. tip:: The full list of supported date formats can be found under the :ref:`Supported date formats section<copy_date_parsers>` of the :ref:`copy_from` reference. diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 589966102..1c273e614 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE t WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY t FROM WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY t TO WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t ( id int not null ) WRAPPER json_fdw OPTIONS ( location = 'somefile.json' ) ; The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS ( LOCATION = 'somefile.json' ); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE nba WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY nba FROM WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY nba TO WRAPPER json_fdw OPTIONS (location = 's3://sqream-docs/nba.json'); When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t (id int not null) WRAPPER json_fdw OPTIONS (location = 'sqream-docs.json'); The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS (LOCATION = 'sqream-docs.json'); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index c0dffd842..d52ca002c 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -199,23 +199,21 @@ We will make note of the file structure to create a matching ``CREATE FOREIGN TA .. code-block:: postgres - CREATE FOREIGN TABLE ext_nba - ( - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) - WRAPPER orc_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.orc' - ); + CREATE FOREIGN TABLE ext_nba ( + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER + orc_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/nba.orc'); .. tip:: @@ -231,19 +229,20 @@ External tables do not verify file integrity or structure, so verify that the ta .. code-block:: psql - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + SELECT * FROM ext_nba LIMIT 10; + + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 If any errors show up at this stage, verify the structure of the ORC files and match them to the external table structure you created. @@ -254,10 +253,14 @@ To load the data into SQream DB, use the :ref:`create_table_as` statement: .. code-block:: postgres - CREATE TABLE nba AS - SELECT * FROM ext_nba; - -Working around unsupported column types + CREATE TABLE + nba AS + SELECT + * + FROM + ext_nba; + +Working Around Unsupported Column Types --------------------------------------- Suppose you only want to load some of the columns - for example, if one of the columns isn't supported. @@ -267,9 +270,21 @@ By ommitting unsupported columns from queries that access the ``EXTERNAL TABLE`` For this example, assume that the ``Position`` column isn't supported because of its type. .. code-block:: postgres - - CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + + CREATE TABLE + nba AS + SELECT + Name, + Team, + Number, + NULL as Position, + Age, + Height, + Weight, + College, + Salary + FROM + ext_nba; -- We ommitted the unsupported column `Position` from this query, and replaced it with a default ``NULL`` value, to maintain the same table structure. @@ -285,10 +300,22 @@ Similar to the previous example, we will also set the ``Position`` column as a d .. code-block:: postgres - CREATE TABLE nba AS - SELECT name, team, number, NULL as position, age, height, (weight / 2.205) as weight, college, salary - FROM ext_nba - ORDER BY weight; + CREATE TABLE + nba AS + SELECT + name, + team, + number, + NULL as position, + age, + height, + (weight / 2.205) as weight, + college, + salary + FROM + ext_nba + ORDER BY + weight; Further ORC loading examples @@ -302,29 +329,48 @@ Loading a table from a directory of ORC files on HDFS .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER orc_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.ORC' - ); + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + orc_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.ORC' + ); - CREATE TABLE users AS SELECT * FROM ext_users; + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; Loading a table from a bucket of files on S3 -------------------------------------------- .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER orc_fdw - OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.ORC', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ) - ; - - CREATE TABLE users AS SELECT * FROM ext_users; \ No newline at end of file + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + orc_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/users/*.ORC', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; \ No newline at end of file diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 12b409740..0fd82f923 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -204,23 +204,21 @@ The following example shows the correct file structure used for creating a :ref: .. code-block:: postgres - CREATE FOREIGN TABLE ext_nba - ( - Name TEXT(40), - Team TEXT(40), - Number BIGINT, - Position TEXT(2), - Age BIGINT, - Height TEXT(4), - Weight BIGINT, - College TEXT(40), - Salary FLOAT - ) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba.parquet' - ); + CREATE FOREIGN TABLE ext_nba ( + Name TEXT(40), + Team TEXT(40), + Number BIGINT, + Position TEXT(2), + Age BIGINT, + Height TEXT(4), + Weight BIGINT, + College TEXT(40), + Salary FLOAT + ) + WRAPPER + parquet_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/nba.parquet'); .. tip:: An exact match must exist between the SQream and Parquet types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. @@ -236,8 +234,12 @@ You can use the :ref:`create_table_as` statement to load the data into SQream, a .. code-block:: postgres - CREATE TABLE nba AS - SELECT * FROM ext_nba; + CREATE TABLE + nba AS + SELECT + * + FROM + ext_nba; Examples -------- @@ -255,8 +257,20 @@ In the example below, the ``Position column`` is not supported due its type. .. code-block:: postgres - CREATE TABLE nba AS - SELECT Name, Team, Number, NULL as Position, Age, Height, Weight, College, Salary FROM ext_nba; + CREATE TABLE + nba AS + SELECT + Name, + Team, + Number, + NULL as Position, + Age, + Height, + Weight, + College, + Salary + FROM + ext_nba; Modifying Data Before Loading ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -268,10 +282,22 @@ In the example below, the ``Position column`` is set to the default ``NULL``. .. code-block:: postgres - CREATE TABLE nba AS - SELECT name, team, number, NULL as position, age, height, (weight / 2.205) as weight, college, salary - FROM ext_nba - ORDER BY weight; + CREATE TABLE + nba AS + SELECT + name, + team, + number, + NULL as position, + age, + height, + (weight / 2.205) as weight, + college, + salary + FROM + ext_nba + ORDER BY + weight; Loading a Table from a Directory of Parquet Files on HDFS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -280,15 +306,24 @@ The following is an example of loading a table from a directory of Parquet files .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); + + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; Loading a Table from a Directory of Parquet Files on S3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -297,16 +332,26 @@ The following is an example of loading a table from a directory of Parquet files .. code-block:: postgres - CREATE FOREIGN TABLE ext_users - (id INT NOT NULL, name TEXT(30) NOT NULL, email TEXT(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( LOCATION = 's3://pp-secret-bucket/users/*.parquet', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); - - CREATE TABLE users AS SELECT * FROM ext_users; + CREATE FOREIGN TABLE ext_users ( + id INT NOT NULL, + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL + ) + WRAPPER + parquet_fdw + OPTIONS + ( + LOCATION = 's3://sqream-docs/users/*.parquet', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); + + CREATE TABLE + users AS + SELECT + * + FROM + ext_users; For more configuration option examples, navigate to the :ref:`create_foreign_table` page and see the **Parameters** table. @@ -319,18 +364,19 @@ The following is an example of the output based on the **nba.parquet** table: .. code-block:: psql - t=> SELECT * FROM ext_nba LIMIT 10; - Name | Team | Number | Position | Age | Height | Weight | College | Salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 + SELECT * FROM ext_nba LIMIT 10; + + Name | Team | Number | Position | Age | Height | Weight | College | Salary + --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- + Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 + Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 + John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | + R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 + Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 + Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 + Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 + Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 + Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 + Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 .. note:: If your table output has errors, verify that the structure of the Parquet files correctly corresponds to the external table structure that you created. \ No newline at end of file From c6df62dbea567de505adaac3abbca606f4c84ea0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 31 Mar 2024 14:13:56 +0300 Subject: [PATCH 1254/1892] Haskell cli deprecation note 4.7 --- .DS_Store | Bin 0 -> 6148 bytes releases/4.7.rst | 6 +++++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..536e8fa46ab58c197597811bcf9191ae1dacaef7 GIT binary patch literal 6148 zcmeHK&2G~`5S~o~byOj8C{m9r^%{vLNR*0;70L_XsvH0X8;5j-@mBt64pAhZ;e~h- zo~PgJE)ftAH;B-TH1myTXV%_trCkpZscD;!iH1ZJK^c1km|qBwvu;T*MD~En&0%Ok zEmf3Kvz0A@U1Wgw?vUP*rIOy$_xopDZ02^<P)>8IZ<4AkY`H)U_M7fwmn&qolu^Os zbcH92sKIQDY*}Ath0T!pCA%(6-JG0!RlU9boxA(desmDMNv`ZNY0{>xr)l+ypDwH| zvTuHxU7GoFHavW0%O*ADymAF5pCje<OH<}{Ikjz>*RD441JNKF%!Ws+)!AgECyySl zM|w3r9iNT#>66KNJ%}D0KYaRP_M!M#+E4g4h~m|--1D%ppW*#sl|ON^DHTT;5C(*S z9cCb$deOlSf1`YwFdz*48wU7%&``!WVCT^t9Wbs10QM1f0-t*cuF(PGfSpH-K$I^9 z`cf5I4CTua*C8(s*m?Bjq(bwd!kbm-P?UQ+=GQKrRP0f#Fdz*4$N=|#kRjjy&wt<l zyCgBffH3fXGNAhB$@vs(3wP_*D*3L}(6>+)&g(pGO5nJw7`c2EA3>cUuGs;`0XvU~ QK;%cj(I7?`_^S-u0?d0}F#rGn literal 0 HcmV?d00001 diff --git a/releases/4.7.rst b/releases/4.7.rst index 3c4a0f71e..b2b5f518f 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -120,9 +120,13 @@ Version 4.7 resolved Issues Deprecations ------------------- +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. + ► **CentOS Linux 7.x** -* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. Upgrading to Version 4.7 ------------------------- From 38a6cfcb5c8533f0224552d8e090968cf2297b4f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Apr 2024 11:24:26 +0300 Subject: [PATCH 1255/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 1cdc8439e..b5f64c3b7 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -330,6 +330,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea .. code-block:: python import pysqream + import sqlalchemy.orm as orm from datetime import date, datetime from time import time From e660dc4155c55865c7eb1512040a00500a4811a3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Apr 2024 11:25:36 +0300 Subject: [PATCH 1256/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index b5f64c3b7..436dbd469 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -330,7 +330,7 @@ This example shows how to load 10,000 rows of dummy data to an instance of SQrea .. code-block:: python import pysqream - import sqlalchemy.orm as orm + import sqlalchemy.orm as orm from datetime import date, datetime from time import time From 6bc03ebb707ce2c64d46310c74299bb660986289 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:48:59 +0300 Subject: [PATCH 1257/1892] UI installation update1 --- .../installing_dashboard_data_collector.rst | 164 ------------- ...ing_nginx_proxy_over_secure_connection.rst | 74 +++--- .../installing_prometheus_exporters.rst | 196 --------------- ...lling_prometheus_using_binary_packages.rst | 230 ------------------ ...nstalling_studio_on_stand_alone_server.rst | 123 +++++----- .../sqream_studio_installation.rst | 3 - troubleshooting/log_related_issues.rst | 4 +- 7 files changed, 105 insertions(+), 689 deletions(-) delete mode 100644 installation_guides/installing_dashboard_data_collector.rst delete mode 100644 installation_guides/installing_prometheus_exporters.rst delete mode 100644 installation_guides/installing_prometheus_using_binary_packages.rst diff --git a/installation_guides/installing_dashboard_data_collector.rst b/installation_guides/installing_dashboard_data_collector.rst deleted file mode 100644 index 0c154da9d..000000000 --- a/installation_guides/installing_dashboard_data_collector.rst +++ /dev/null @@ -1,164 +0,0 @@ -.. _installing_dashboard_data_collector: - - - -*************************************** -Installing the Dashboard Data Collector -*************************************** - -Installing the Dashboard Data Collector -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After accessing the Prometheus user interface, you can install the **Dashboard Data Collector**. You must install the Dashboard Data Collector to enable the Dashboard in Studio. - -.. note:: Before installing the Dashboard Data collector, verify that Prometheus has been installed and configured for the cluster. - -How to install Prometheus from tarball - **Comment - this needs to be its own page.** - -**To install the Dashboard Data Collector:** - -1. Store the Data Collector Package obtained from `SQream Artifactory <http://artifactory.host-98.sq.l/artifactory/dashboard/data_collector/tarball>`_. - - :: - -2. Extract and rename the package: - - .. code-block:: console - - $ tar -xvf dashboard-data-collector-0.5.2.tar.gz - $ mv package dashboard-data-collector - -3. Change your directory to the location of the package folder: - - .. code-block:: console - - $ cd dashboard-data-collector - -4. Set up the data collection by modifying the SQream and Data Collector IPs, ports, user name, and password according to the cluster: - - .. code-block:: console - - $ npm run setup -- \ - $ --host=127.0.0.1 \ - $ --port=3108 \ - $ --database=master \ - $ --is-cluster=true \ - $ --service=sqream \ - $ --dashboard-user=sqream \ - $ --dashboard-password=sqream \ - $ --prometheus-url=http://127.0.0.1:9090/api/v1/query - -5. Debug the Data Collector: (**Comment** - *using the npm project manager*). - - .. code-block:: console - - $ npm start - - A json file is generated in the log, as shown below: - - .. code-block:: console - - $ { - $ "machines": [ - $ { - $ "machineId": "dd4af489615", - $ "name": "Server 0", - $ "location": "192.168.4.94", - $ "totalMemory": 31.19140625, - $ "gpus": [ - $ { - $ "gpuId": "GPU-b17575ec-eeba-3e0e-99cd-963967e5ee3f", - $ "machineId": "dd4af489615", - $ "name": "GPU 0", - $ "totalMemory": 3.9453125 - $ } - $ ], - $ "workers": [ - $ { - $ "workerId": "sqream_01", - $ "gpuId": "", - $ "name": "sqream_01" - $ } - $ ], - $ "storageWrite": 0, - $ "storageRead": 0, - $ "freeStorage": 0 - $ }, - $ { - $ "machineId": "704ec607174", - $ "name": "Server 1", - $ "location": "192.168.4.95", - $ "totalMemory": 31.19140625, - $ "gpus": [ - $ { - $ "gpuId": "GPU-8777c14f-7611-517a-e9c7-f42eeb21700b", - $ "machineId": "704ec607174", - $ "name": "GPU 0", - $ "totalMemory": 3.9453125 - $ } - $ ], - $ "workers": [ - $ { - $ "workerId": "sqream_02", - $ "gpuId": "", - $ "name": "sqream_02" - $ } - $ ], - $ "storageWrite": 0, - $ "storageRead": 0, - $ "freeStorage": 0 - $ } - $ ], - $ "clusterStatus": true, - $ "storageStatus": { - $ "dataStorage": 49.9755859375, - $ "totalDiskUsage": 52.49829018075231, - $ "storageDetails": { - $ "data": 0, - $ "freeData": 23.7392578125, - $ "tempData": 0, - $ "deletedData": 0, - $ "other": 26.236328125 - $ }, - $ "avgThroughput": { - $ "read": 0, - $ "write": 0 - $ }, - $ "location": "/" - $ }, - $ "queues": [ - $ { - $ "queueId": "sqream", - $ "name": "sqream", - $ "workerIds": [ - $ "sqream_01", - $ "sqream_02" - $ ] - $ } - $ ], - $ "queries": [], - $ "collected": true, - $ "lastCollect": "2021-11-17T12:46:31.601Z" - $ } - -.. note:: Verify that all machines and workers are correctly registered. - - -6. Press **CTRL + C** to stop ``npm start`` (**Comment** - *It may be better to refer to it as the npm project manager*). - - :: - - -7. Start the Data Collector with the ``pm2`` service: - - .. code-block:: console - - $ pm2 start ./index.js --name=dashboard-data-collector - -8. Add the following parameter to the SQream Studio setup defined in :ref:`Step 4<add_parameter>` in **Installing Studio** below. - - .. code-block:: console - - --data-collector-url=http://127.0.0.1:8100/api/dashboard/data - -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` diff --git a/installation_guides/installing_nginx_proxy_over_secure_connection.rst b/installation_guides/installing_nginx_proxy_over_secure_connection.rst index 5aef5eaff..b13c01427 100644 --- a/installation_guides/installing_nginx_proxy_over_secure_connection.rst +++ b/installation_guides/installing_nginx_proxy_over_secure_connection.rst @@ -1,18 +1,15 @@ .. _installing_nginx_proxy_over_secure_connection: -************************* +************************************************** Installing an NGINX Proxy Over a Secure Connection -************************* -Configuring your NGINX server to use a strong encryption for client connections provides you with secure servers requests, preventing outside parties from gaining access to your traffic. +************************************************** -The **Installing an NGINX Proxy Over a Secure Connection** page describes the following: +Configuring your NGINX server to use a strong encryption for client connections provides you with secure servers requests, preventing outside parties from gaining access to your traffic. .. contents:: :local: :depth: 1 -Overview -============== The Node.js platform that SQream uses with our Studio user interface is susceptible to web exposure. This page describes how to implement HTTPS access on your proxy server to establish a secure connection. **TLS (Transport Layer Security)**, and its predecessor **SSL (Secure Sockets Layer)**, are standard web protocols used for wrapping normal traffic in a protected, encrypted wrapper. This technology prevents the interception of server-client traffic. It also uses a certificate system for helping users verify the identity of sites they visit. The **Installing an NGINX Proxy Over a Secure Connection** guide describes how to set up a self-signed SSL certificate for use with an NGINX web server on a CentOS 7 server. @@ -24,7 +21,8 @@ A self-signed certificate may be appropriate if your domain name is not associat For more information on setting up a free trusted certificate, see `How To Secure Nginx with Let's Encrypt on CentOS 7 <https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-centos-7>`_. Prerequisites -============== +============= + The following prerequisites are required for installing an NGINX proxy over a secure connection: * Super user privileges @@ -34,7 +32,8 @@ The following prerequisites are required for installing an NGINX proxy over a se * A domain name to create a certificate for Installing NGINX and Adjusting the Firewall -============== +=========================================== + After verifying that you have the above preriquisites, you must verify that the NGINX web server has been installed on your machine. Though NGINX is not available in the default CentOS repositories, it is available from the **EPEL (Extra Packages for Enterprise Linux)** repository. @@ -45,25 +44,25 @@ Though NGINX is not available in the default CentOS repositories, it is availabl .. code-block:: console - $ sudo yum install epel-release + sudo yum install epel-release 2. Install NGINX: .. code-block:: console - $ sudo yum install nginx + sudo yum install nginx 3. Start the NGINX service: .. code-block:: console - $ sudo systemctl start nginx + sudo systemctl start nginx 4. Verify that the service is running: .. code-block:: console - $ systemctl status nginx + systemctl status nginx The following is an example of the correct output: @@ -81,7 +80,7 @@ Though NGINX is not available in the default CentOS repositories, it is availabl .. code-block:: console - $ sudo systemctl enable nginx + sudo systemctl enable nginx 6. Verify that access to **ports 80 and 443** are not blocked by a firewall. @@ -97,16 +96,16 @@ Though NGINX is not available in the default CentOS repositories, it is availabl .. code-block:: console - $ sudo firewall-cmd --add-service=http - $ sudo firewall-cmd --add-service=https - $ sudo firewall-cmd --runtime-to-permanent + sudo firewall-cmd --add-service=http + sudo firewall-cmd --add-service=https + sudo firewall-cmd --runtime-to-permanent 8. If you have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: .. code-block:: console - $ sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT - $ sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT + sudo iptables -I INPUT -p tcp -m tcp --dport 80 -j ACCEPT + sudo iptables -I INPUT -p tcp -m tcp --dport 443 -j ACCEPT .. note:: The commands in Step 8 above are highly dependent on your current rule set. @@ -115,7 +114,8 @@ Though NGINX is not available in the default CentOS repositories, it is availabl .. _creating_your_ssl_certificate: Creating Your SSL Certificate -============== +============================= + After installing NGINX and adjusting your firewall, you must create your SSL certificate. TLS/SSL combines public certificates with private keys. The SSL key, kept private on your server, is used to encrypt content sent to clients, while the SSL certificate is publicly shared with anyone requesting content. In addition, the SSL certificate can be used to decrypt the content signed by the associated SSL key. Your public certificate is located in the **/etc/ssl/certs** directory on your server. @@ -128,14 +128,14 @@ This section describes how to create your **/etc/ssl/private directory**, used f .. code-block:: console - $ sudo mkdir /etc/ssl/private - $ sudo chmod 700 /etc/ssl/private + sudo mkdir /etc/ssl/private + sudo chmod 700 /etc/ssl/private 2. Create a self-signed key and certificate pair with OpenSSL with the following command: .. code-block:: console - $ sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt + sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt The following list describes the elements in the command above: @@ -195,12 +195,13 @@ This section describes how to create your **/etc/ssl/private directory**, used f .. code-block:: console - $ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 + sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048 Creating a Diffie-Hellman group takes a few minutes, which is stored as the **dhparam.pem** file in the **/etc/ssl/certs** directory. This file can use in the configuration. Configuring NGINX to use SSL -============== +============================ + After creating your SSL certificate, you must configure NGINX to use SSL. The default CentOS NGINX configuration is fairly unstructured, with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. @@ -215,7 +216,7 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a .. code-block:: console - $ sudo vi /etc/nginx/conf.d/ssl.conf + sudo vi /etc/nginx/conf.d/ssl.conf 2. In the file you created in Step 1 above, open a server block: @@ -293,7 +294,7 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a .. code-block:: console - $ sudo vi /etc/nginx/conf.d/nginx.conf + sudo vi /etc/nginx/conf.d/nginx.conf .. code-block:: console @@ -316,7 +317,8 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a } Redirecting Studio Access from HTTP to HTTPS -================== +============================================ + After configuring NGINX to use SSL, you must redirect Studio access from HTTP to HTTPS. According to your current configuration, NGINX responds with encrypted content for requests on port 443, but with **unencrypted** content for requests on **port 80**. This means that our site offers encryption, but does not enforce its usage. This may be fine for some use cases, but it is usually better to require encryption. This is especially important when confidential data like passwords may be transferred between the browser and the server. @@ -329,16 +331,17 @@ The default NGINX configuration file allows us to easily add directives to the d .. code-block:: console - $ sudo vi /etc/nginx/default.d/ssl-redirect.conf + sudo vi /etc/nginx/default.d/ssl-redirect.conf 2. Copy and paste this line: .. code-block:: console - $ return 301 https://$host$request_uri:8080/; + return 301 https://$host$request_uri:8080/; Activating Your NGINX Configuration -============== +=================================== + After redirecting from HTTP to HTTPs, you must restart NGINX to activate your new configuration. **To activate your NGINX configuration:** @@ -347,7 +350,7 @@ After redirecting from HTTP to HTTPs, you must restart NGINX to activate your ne .. code-block:: console - $ sudo nginx -t + sudo nginx -t The following output is generated if your files contain no syntax errors: @@ -360,10 +363,11 @@ After redirecting from HTTP to HTTPs, you must restart NGINX to activate your ne .. code-block:: console - $ sudo systemctl restart nginx + sudo systemctl restart nginx Verifying that NGINX is Running -============== +=============================== + After activating your NGINX configuration, you must verify that NGINX is running correctly. **To verify that NGINX is running correctly:** @@ -372,7 +376,7 @@ After activating your NGINX configuration, you must verify that NGINX is running .. code-block:: console - $ systemctl status nginx + systemctl status nginx The following is an example of the correct output: @@ -390,7 +394,7 @@ After activating your NGINX configuration, you must verify that NGINX is running .. code-block:: console - $ sudo netstat -nltp |grep nginx + sudo netstat -nltp |grep nginx The following is an example of the correct output: diff --git a/installation_guides/installing_prometheus_exporters.rst b/installation_guides/installing_prometheus_exporters.rst deleted file mode 100644 index a1381fea3..000000000 --- a/installation_guides/installing_prometheus_exporters.rst +++ /dev/null @@ -1,196 +0,0 @@ -.. _installing_prometheus_exporters: - -********************************************* -Installing Prometheus Exporter -********************************************* - -The **Installing Prometheus Exporters** guide includes the following sections: - -.. contents:: - :local: - :depth: 1 - -Overview -============================== -The **Prometheus** exporter is an open-source systems monitoring and alerting toolkit. It is used for collecting metrics from an operating system and exporting them to a graphic user interface. - -The Installing Prometheus Exporters guide describes how to installing the following exporters: - -* The **Node_exporter** - the basic exporter used for displaying server metrics, such as CPU and memory. - -* The **Nvidia_exporter** - shows Nvidia GPU metrics. - -* The **process_exporter** - shows data belonging to the server's running processes. - -For information about more exporters, see `Exporters and Integration <https://prometheus.io/docs/instrumenting/exporters/>`_ - -Adding a User and Group -===================== -Adding a user and group determines who can run processes. - -You can add users with the following command: - -.. code-block:: console - - $ sudo groupadd --system prometheus - -You can add groups with the following command: - -.. code-block:: console - - $ sudo useradd -s /sbin/nologin --system -g prometheus prometheus - -Cloning the Prometheus GIT Project -===================== -After adding a user and group you must clone the Prometheus GIT project. - -You can clone the Prometheus GIT project with the following command: - -.. code-block:: console - - $ git clone http://gitlab.sq.l/IT/promethues.git prometheus - -.. note:: If you experience difficulties cloning the Prometheus GIT project or receive an error, contact your IT department. - -The following shows the result of cloning your Prometheus GIT project: - -.. code-block:: console - - $ prometheus/ - $ ├── node_exporter - $ │   └── node_exporter - $ ├── nvidia_exporter - $ │   └── nvidia_exporter - $ ├── process_exporter - $ │   └── process-exporter_0.5.0_linux_amd64.rpm - $ ├── README.md - $ └── services - $ ├── node_exporter.service - $ └── nvidia_exporter.service - -Installing the Node Exporter and NVIDIA Exporter -===================== -After cloning the Prometheus GIT project you must install the **node_exporter** and **NVIDIA_exporter**. - -**To install the node_exporter and NVIDIA_exporter:** - -1. Navigate to the cloned folder: - - .. code-block:: console - - $ cd prometheus - -2. Copy **node_exporter** and **nvidia_exporter** to **/usr/bin/**. - - .. code-block:: console - - $ sudo cp node_exporter/node_exporter /usr/bin/ - $ sudo cp nvidia_exporter/nvidia_exporter /usr/bin/ - -3. Copy the **services** files to the services folder: - - .. code-block:: console - - $ sudo cp services/node_exporter.service /etc/systemd/system/ - $ sudo cp services/nvidia_exporter.service /etc/systemd/system/ - -4. Reload the services so that they can be run: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -5. Set the permissions and group for both service files: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /usr/bin/node_exporter - $ sudo chmod u+x /usr/bin/node_exporter - $ sudo chown prometheus:prometheus /usr/bin/nvidia_exporter - $ sudo chmod u+x /usr/bin/nvidia_exporter - -6. Start both services: - - .. code-block:: console - - $ sudo systemctl start node_exporter && sudo systemctl enable node_exporter - -7. Set both services to start automatically when the server is booted up: - - .. code-block:: console - - $ sudo systemctl start nvidia_exporter && sudo systemctl enable nvidia_exporter - -8. Verify that the server's status is **active (running)**: - - .. code-block:: console - - $ sudo systemctl status node_exporter && sudo systemctl status nvidia_exporter - - The following is the correct output: - - .. code-block:: console - - $ ● node_exporter.service - Node Exporter - $ Loaded: loaded (/etc/systemd/system/node_exporter.service; enabled; vendor preset: disabled) - $ Active: active (running) since Wed 2019-12-11 12:28:31 IST; 1 months 5 days ago - $ Main PID: 28378 (node_exporter) - $ CGroup: /system.slice/node_exporter.service - $ - $ ● nvidia_exporter.service - Nvidia Exporter - $ Loaded: loaded (/etc/systemd/system/nvidia_exporter.service; enabled; vendor preset: disabled) - $ Active: active (running) since Wed 2020-01-22 13:40:11 IST; 31min ago - $ Main PID: 1886 (nvidia_exporter) - $ CGroup: /system.slice/nvidia_exporter.service - $ └─1886 /usr/bin/nvidia_exporter - -Installing the Process Exporter -===================== -After installing the **node_exporter** and **Nvidia_exporter** you must install the **process_exporter**. - -**To install the process_exporter:** - -1. Do one of the following: - - * For **CentOS**, run ``sudo rpm -i process_exporter/process-exporter_0.5.0_linux_amd64.rpm``. - * For **Ubuntu**, run ``sudo dpkg -i process_exporter/process-exporter_0.6.0_linux_amd64.deb``. - -2. Verify that the process_exporter is running: - - .. code-block:: console - - $ sudo systemctl status process-exporter - -3. Set the process_exporter to start automatically when the server is booted up: - - .. code-block:: console - - $ sudo systemctl enable process-exporter - -Opening the Firewall Ports -===================== -After installing the **process_exporter** you must open the firewall ports for the following services: - -* **node_exporter** - port: 9100 - -* **nvidia_exporter** - port: 9445 - -* **process-exporter** - port: 9256 - -.. note:: This procedure is only relevant if your firwall is running. - -**To open the firewall ports:** - -1. Run the following command: - - .. code-block:: console - - $ sudo firewall-cmd --zone=public --add-port=<PORT NUMBER>/tcp --permanent - -2. Reload the firewall: - - .. code-block:: console - - $ sudo firewall-cmd --reload - -3. Verify that the changes have taken effect. \ No newline at end of file diff --git a/installation_guides/installing_prometheus_using_binary_packages.rst b/installation_guides/installing_prometheus_using_binary_packages.rst deleted file mode 100644 index bd46d2fcc..000000000 --- a/installation_guides/installing_prometheus_using_binary_packages.rst +++ /dev/null @@ -1,230 +0,0 @@ -.. _installing_prometheus_using_binary_packages: - -.. _install_prometheus_binary_top: - -********************************************** -Installing Prometheus Using Binary Packages -********************************************** - -Prometheus is an application used for event monitoring and alerting. - -.. contents:: - :local: - :depth: 1 - -Installing Prometheus -^^^^^^^^^^^^^^^^^^^^^^ - -You must install Prometheus before installing the Dashboard Data Collector. - -**To install Prometheus:** - -1. Verify the following: - - 1. That you have **sudo** access to your Linux server. - 2. That your server has access to the internet (for downloading the Prometheus binary package). - 3. That your firewall rules are opened for accessing Prometheus Port 9090. - -2. Navigate to the Prometheus `Download <https://prometheus.io/download/>`_ page and download the **prometheus-2.32.0-rc.1.linux-amd64.tar.gz** package. - - :: - -3. Do the following: - - 1. Download the source using the ``curl`` command: - - .. code-block:: console - - $ curl -LO url -LO https://github.com/prometheus/prometheus/releases/download/v2.22.0/prometheus-2.22.0.linux-amd64.tar.gz - - 2. Extract the file contents: - - .. code-block:: console - - $ tar -xvf prometheus-2.22.0.linux-amd64.tar.gz - - 3. Rename the extracted folder **prometheus-files**: - - .. code-block:: console - - $ mv prometheus-2.22.0.linux-amd64 prometheus-files - -4. Create a Prometheus user: - - .. code-block:: console - - $ sudo useradd --no-create-home --shell /bin/false prometheus - -5. Create your required directories: - - .. code-block:: console - - $ sudo mkdir /etc/prometheus - $ sudo mkdir /var/lib/prometheus - -6. Set the Prometheus user as the owner of your required directories: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /etc/prometheus - $ sudo chown prometheus:prometheus /var/lib/prometheus - -7. Copy the Prometheus and Promtool binary packages from the **prometheus-files** folder to **/usr/local/bin**: - - .. code-block:: console - - $ sudo cp prometheus-files/prometheus /usr/local/bin/ - $ sudo cp prometheus-files/promtool /usr/local/bin/ - -8. Change the ownership to the prometheus user: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /usr/local/bin/prometheus - $ sudo chown prometheus:prometheus /usr/local/bin/promtool - -9. Move the **consoles** and **consoles_libraries** directories from **prometheus-files** folder to **/etc/prometheus** folder: - - .. code-block:: console - - $ sudo cp -r prometheus-files/consoles /etc/prometheus - $ sudo cp -r prometheus-files/console_libraries /etc/prometheus - -10. Change the ownership to the prometheus user: - - .. code-block:: console - - $ sudo chown -R prometheus:prometheus /etc/prometheus/consoles - $ sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries - -For more information on installing the Dashboard Data Collector, see :ref:`Installing the Dashboard Data Collector<installing_dashboard_data_collector>`. - -Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` - -Configuring Your Prometheus Settings -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After installing Prometheus you must configure your Prometheus settings. You must perform all Prometheus configurations in the **/etc/prometheus/prometheus.yml** file. - -**To configure your Prometheus settings:** - -1. Create your **prometheus.yml** file: - - .. code-block:: console - - $ sudo vi /etc/prometheus/prometheus.yml - -2. Copy the contents below into your prometheus.yml file: - - .. code-block:: console - - $ #node_exporter port : 9100 - $ #nvidia_exporter port: 9445 - $ #process-exporter port: 9256 - $ - $ global: - $ scrape_interval: 10s - $ - $ scrape_configs: - $ - job_name: 'prometheus' - $ scrape_interval: 5s - $ static_configs: - $ - targets: - $ - <prometheus server IP>:9090 - $ - job_name: 'processes' - $ scrape_interval: 5s - $ static_configs: - $ - targets: - $ - <process exporters iP>:9256 - $ - <another process exporters iP>:9256 - $ - job_name: 'nvidia' - $ scrape_interval: 5s - $ static_configs: - $ - targets: - $ - <nvidia exporter IP>:9445 - $ - <another nvidia exporter IP>:9445 - $ - job_name: 'nodes' - $ scrape_interval: 5s - $ static_configs: - $ - targets: - $ - <node exporter IP>:9100 - $ - <another node exporter IP>:9100 - -3. Change the ownership of the file to the prometheus user: - - .. code-block:: console - - $ sudo chown prometheus:prometheus /etc/prometheus/prometheus.yml - -Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` - -Configuring Your Prometheus Service File -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After configuring your Prometheus settings you must configure your Prometheus service file. - -**To configure your Prometheus service file**: - -1. Create your **prometheus.yml** file: - - .. code-block:: console - - $ sudo vi /etc/systemd/system/prometheus.service - -2. Copy the contents below into your prometheus service file: - - .. code-block:: console - - $ [Unit] - $ Description=Prometheus - $ Wants=network-online.target - $ After=network-online.target - $ - $ [Service] - $ User=prometheus - $ Group=prometheus - $ Type=simple - $ ExecStart=/usr/local/bin/prometheus \ - $ --config.file /etc/prometheus/prometheus.yml \ - $ --storage.tsdb.path /var/lib/prometheus/ \ - $ --web.console.templates=/etc/prometheus/consoles \ - $ --web.console.libraries=/etc/prometheus/console_libraries - $ - $ [Install] - $ WantedBy=multi-user.target - -3. Register the prometheus service by reloading the **systemd** service: - - .. code-block:: console - - $ sudo systemctl daemon-reload - -4. Start the prometheus service: - - .. code-block:: console - - $ sudo systemctl start prometheus - -5. Check the status of the prometheus service: - - .. code-block:: console - - $ sudo systemctl status prometheus - - If the status is ``active (running)``, you have configured your Prometheus service file correctly. - -Back to :ref:`Installing Prometheus Using Binary Packages<install_prometheus_binary_top>` - -Accessing the Prometheus User Interface -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -After configuring your Prometheus service file, you can access the Prometheus user interface. - -You can access the Prometheus user interface by running the following command: - -.. code-block:: console - - $ http://<prometheus-ip>:9090/graph - -Once the Prometheus user interface is displayed, go to the **Query** tab and query metrics. - diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index ad7802732..8c7cc6f46 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -2,26 +2,33 @@ .. _install_studio_top: -*********************** +***************************************** Installing Studio on a Stand-Alone Server -*********************** +***************************************** + A stand-alone server is a server that does not run SQreamDB based on binary files. .. contents:: :local: :depth: 1 -Installing NodeJS Version 12 on the Server -^^^^^^^^^^^^^^^ -Before installing Studio you must install NodeJS version 12 on the server. +Before You Begin +================ + +It is essential you have **NodeJS 16** installed. + +Installing NodeJS 16 on the Server +---------------------------------- + +Before installing Studio you must install NodeJS version 16 on the server. -**To install NodeJS version 12 on the server:** +**To install NodeJS version 16 on the server:** -1. Check if a version of NodeJS older than version *12.<x.x>* has been installed on the target server. +1. Check if a version of NodeJS older than version *16.<x.x>* has been installed on the target server. .. code-block:: console - $ node -v + node -v The following is the output if a version of NodeJS has already been installed on the target server: @@ -29,36 +36,36 @@ Before installing Studio you must install NodeJS version 12 on the server. bash: /usr/bin/node: No such file or directory -2. If a version of NodeJS older than *12.<x.x>* has been installed, remove it as follows: +2. If a version of NodeJS older than *16.<x.x>* has been installed, remove it as follows: * On CentOS: .. code-block:: console - $ sudo yum remove -y nodejs + sudo yum remove -y nodejs * On Ubuntu: .. code-block:: console - $ sudo apt remove -y nodejs + sudo apt remove -y nodejs -3. If you have not installed NodeJS version 12, run the following commands: +3. If you have not installed NodeJS version 16, run the following commands: * On CentOS: .. code-block:: console - $ curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - $ sudo yum clean all && sudo yum makecache fast - $ sudo yum install -y nodejs + curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - + sudo yum clean all && sudo yum makecache fast + sudo yum install -y nodejs * On Ubuntu: .. code-block:: console - $ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - - $ sudo apt-get install -y nodejs + curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - + sudo apt-get install -y nodejs The following output is displayed if your installation has completed successfully: @@ -97,25 +104,16 @@ Before installing Studio you must install NodeJS version 12 on the server. .. code-block:: console - $ node -v + node -v The following is an example of the correct output: .. code-block:: console - v12.22.1 - -5. Install Prometheus using binary packages. - - For more information on installing Prometheus using binary packages, see :ref:`installing_prometheus_using_binary_packages`. - -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` - - + v16.20.0 Installing Studio -^^^^^^^^^^^^^^^ -After installing the Dashboard Data Collector, you can install Studio. +================= **To install Studio:** @@ -127,7 +125,7 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ tar -xvf sqream-acceleration-studio-<version number>.x86_64.tar.gz + tar -xvf sqream-acceleration-studio-<version number>.x86_64.tar.gz :: @@ -135,7 +133,7 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ cd sqream-admin + cd sqream-admin .. _add_parameter: @@ -143,7 +141,7 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ npm run setup -- -y --host=<SQreamD IP> --port=3108 --data-collector-url=http://<data collector IP address>:8100/api/dashboard/data + npm run setup -- -y --host=<SQreamD IP> --port=3108 The above command creates the **sqream-admin-config.json** configuration file in the **sqream-admin** folder and shows the following output: @@ -165,7 +163,7 @@ After installing the Dashboard Data Collector, you can install Studio. The following is an example of the correctly modified configuration file: - .. code-block:: console + .. code-block:: json { "debugSqream": false, @@ -193,18 +191,19 @@ After installing the Dashboard Data Collector, you can install Studio. .. code-block:: console - $ mv sqream-admin-config.json /etc/sqream + mv sqream-admin-config.json /etc/sqream Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` Starting Studio Manually -^^^^^^^^^^^^^^^ +------------------------ + You can start Studio manually by running the following command: .. code-block:: console - $ cd /home/sqream/sqream-admin - $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start + cd /home/sqream/sqream-admin + NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start --config-location=/etc/sqream/sqream-admin-config.json The following output is displayed: @@ -219,7 +218,8 @@ The following output is displayed: └─────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ Starting Studio as a Service -^^^^^^^^^^^^^^^ +---------------------------- + Sqream uses the **Process Manager (PM2)** to maintain Studio. **To start Studio as a service:** @@ -228,7 +228,7 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ sudo npm install -g pm2 + sudo npm install -g pm2 :: @@ -236,7 +236,7 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ pm2 list + pm2 list The following is the output: @@ -256,15 +256,15 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ cd /home/sqream/sqream-admin - $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start --config-location=/etc/sqream/sqream-admin-config.json + cd /home/sqream/sqream-admin + NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start --config-location=/etc/sqream/sqream-admin-config.json * If the **sqream-admin-config.json** file is not located in **/etc/sqream/**, run the following command: .. code-block:: console - $ cd /home/sqream/sqream-admin - $ NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start + cd /home/sqream/sqream-admin + NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start :: @@ -272,7 +272,7 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ netstat -nltp + netstat -nltp 4. Verify that SQream_studio is listening on port 8080, as shown below: @@ -304,13 +304,13 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ pm2 startup + pm2 startup The following is an example of the output: .. code-block:: console - $ sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sqream --hp /home/sqream + sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u sqream --hp /home/sqream 7. Copy and paste the output above and run it. @@ -320,25 +320,27 @@ Sqream uses the **Process Manager (PM2)** to maintain Studio. .. code-block:: console - $ pm2 save + pm2 save Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` Accessing Studio -^^^^^^^^^^^^^^^ +---------------- + The Studio page is available on port 8080: ``http://<server ip>:8080``. If port 8080 is blocked by the server firewall, you can unblock it by running the following command: .. code-block:: console - $ firewall-cmd --zone=public --add-port=8080/tcp --permanent - $ firewall-cmd --reload + firewall-cmd --zone=public --add-port=8080/tcp --permanent + firewall-cmd --reload Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` Maintaining Studio with the Process Manager (PM2) -^^^^^^^^^^^^^^^ +------------------------------------------------- + Sqream uses the **Process Manager (PM2)** to maintain Studio. You can use PM2 to do one of the following: @@ -356,7 +358,8 @@ You can use PM2 to do one of the following: Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` Upgrading Studio -^^^^^^^^^^^^^^^ +---------------- + To upgrade Studio you need to stop the version that you currently have. **To stop the current version of Studio:** @@ -365,7 +368,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ pm2 list + pm2 list The process name is displayed. @@ -379,7 +382,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ pm2 stop <process name> + pm2 stop <process name> :: @@ -387,7 +390,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ pm2 stop all + pm2 stop all :: @@ -395,7 +398,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ mv sqream-admin sqream-admin-<old_version> + mv sqream-admin sqream-admin-<old_version> :: @@ -403,7 +406,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ tar -xf sqream-acceleration-studio-<version>tar.gz + tar -xf sqream-acceleration-studio-<version>tar.gz :: @@ -411,7 +414,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ npm run setup -- -y --host=<SQreamD IP> --port=3108 + npm run setup -- -y --host=<SQreamD IP> --port=3108 The above command creates the **sqream-admin-config.json** configuration file in the **sqream_admin** folder. @@ -425,7 +428,7 @@ To upgrade Studio you need to stop the version that you currently have. .. code-block:: console - $ pm2 start all + pm2 start all Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` diff --git a/installation_guides/sqream_studio_installation.rst b/installation_guides/sqream_studio_installation.rst index 53c89772d..8891dfcde 100644 --- a/installation_guides/sqream_studio_installation.rst +++ b/installation_guides/sqream_studio_installation.rst @@ -9,8 +9,5 @@ The **Installing SQream Studio** page incudes the following installation guides: :maxdepth: 1 :glob: - installing_prometheus_exporters - installing_prometheus_using_binary_packages - installing_dashboard_data_collector installing_studio_on_stand_alone_server installing_nginx_proxy_over_secure_connection \ No newline at end of file diff --git a/troubleshooting/log_related_issues.rst b/troubleshooting/log_related_issues.rst index a259bff35..2f37f0962 100644 --- a/troubleshooting/log_related_issues.rst +++ b/troubleshooting/log_related_issues.rst @@ -3,6 +3,7 @@ *********************** Log Related Issues *********************** + The **Log Related Issues** page describes how to resolve the following common issues: .. toctree:: @@ -12,7 +13,8 @@ The **Log Related Issues** page describes how to resolve the following common is Loading Logs with Foreign Tables --------------------------------------- -Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. + +Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`foreign_tables` concept through SQream DB. .. code-block:: postgres From 6f8dfa6d04591966ea1de934a2f9d6bcb4e85077 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:47:19 +0300 Subject: [PATCH 1258/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 56 ++++++++++++++++--- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index ab4dc42f3..fab954ee1 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -4,7 +4,7 @@ Casts and Conversions ********************* -SQream supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQream DB. +SQreamDB supports explicit and implicit casting and type conversion. The system may automatically add implicit casts when combining different data types in the same expression. In many cases, while the details related to this are not important, they can affect the results of a query. When necessary, an explicit cast can be used to override the automatic cast added by SQreamDB. For example, the ANSI standard defines a ``SUM()`` aggregation over an ``INT`` column as an ``INT``. However, when dealing with large amounts of data this could cause an overflow. @@ -14,21 +14,36 @@ You can rectify this by casting the value to a larger data type, as shown below: SUM(some_int_column :: BIGINT) -SQream supports the following three data conversion types: +Conversion Methods +================== -* ``CAST(<value> AS <data type>)``, to convert a value from one type to another. For example, ``CAST('1997-01-01' AS DATE)``, ``CAST(3.45 AS SMALLINT)``, ``CAST(some_column AS TEXT)``. +SQreamDB supports the following data conversion methods: - :: +* ``CAST(<value> AS <data type>)``, to convert a value from one type to another. + + For example: + + .. code-block:: postgres + + CAST('1997-01-01' AS DATE) + CAST(3.45 AS SMALLINT) + CAST(some_column AS TEXT) -* ``<value> :: <data type>``, a shorthand for the ``CAST`` syntax. For example, ``'1997-01-01' :: DATE``, ``3.45 :: SMALLINT``, ``(3+5) :: BIGINT``. +* ``<value> :: <data type>``, a shorthand for the ``CAST`` syntax. - :: + For example: + + .. code-block:: postgres + + '1997-01-01' :: DATE + 3.45 :: SMALLINT + (3+5) :: BIGINT * See the :ref:`SQL functions reference <sql_functions>` for additional functions that convert from a specific value which is not an SQL type, such as :ref:`from_unixts`, etc. Supported Casts ---------------- +=============== The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. @@ -47,3 +62,30 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ + +Value Dependent Conversions +--------------------------- + +Conversions between certain data types may be value-dependent, as the outcome can vary based on the specific values being converted and their compatibility with the target data type's range or precision. + +For example: + +.. code-block:: postgres + + CREATE OR REPLACE TABLE t(xint INT, xtext TEXT); + INSERT INTO t VALUES(1234567, 'abc'); + + -- yields cast overflow: + SELECT xint::TINYINT FROM t; + + -- yields Unsupported conversion attempt from string to number - not all strings are numbers: + SELECT xtext::INT FROM t; + + + CREATE OR REPLACE TABLE t(xint INT, xtext TEXT); + INSERT INTO t VALUES(12, '12'); + + -- yields 12 in both cases: + SELECT xint::TINYINT FROM t; + + SELECT xtext::INT FROM t; \ No newline at end of file From 189aee406a12c19e3df12ed31655afe6a71a9503 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:50:47 +0300 Subject: [PATCH 1259/1892] Update create_foreign_table.rst --- .../sql/sql_statements/ddl_commands/create_foreign_table.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index c21b5e925..37781b1c3 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -24,7 +24,7 @@ Syntax ) [ FOREIGN DATA ] WRAPPER fdw_name [ OPTIONS ( option_def [, ... ] ) ] - ; + schema_name ::= identifier @@ -83,7 +83,7 @@ Parameters * - ``column_def`` - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally * - ``WRAPPER ...`` - - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, or ``csv_fdw`` + - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, ``json_fdw``, or ``csv_fdw`` * - ``LOCATION = ...`` - Specifies a path or URI of the source files, such as ``/path/to/*.parquet`` * - ``DELIMITER = ...`` From a7f45a601bd8a1626ada5f3271964cf1b4582f94 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Apr 2024 11:21:03 +0300 Subject: [PATCH 1260/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 013721e4b..4830f109c 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -216,7 +216,7 @@ The following table shows the Access Control commands: - Returns a list of permissions required to run a statement or query * - :ref:`grant` - Grant permissions to a role - * - :ref:`GRANT USAGE ON SERVICE TO ALL ROLES` + * - :ref:`grant_usage_on_service_to_all_roles` - Grant service usage permissions * - :ref:`revoke` - Revoke permissions from a role From b47b30b1dbc3ea6c9468966b23cdc6a71008be59 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Apr 2024 14:25:31 +0300 Subject: [PATCH 1261/1892] Update ldap.rst --- configuration_guides/ldap.rst | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index e7f631354..76d1932be 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -152,8 +152,6 @@ Flags - Root DN to begin the search for the user in, when doing advanced authentication * - ``ldapBindDn`` - DN of user with which to bind to the directory to perform the search when doing search + bind authentication - * - ``ldapBindDnPassword`` - - Password for user with which to bind to the directory to perform the search when doing search + bind authentication * - ``ldapSearchAttribute`` - Attribute to match against the user name in the search when doing search + bind authentication. If no attribute is specified, ``the uid`` attribute will be used * - ``ldapSearchFilter`` @@ -203,35 +201,41 @@ Advanced Method Configuration Only roles with admin privileges and higher may enable LDAP Authentication. -1. Set the ``authenticationMethod`` flag: +1. Set your LDAP password + +Configure an LDAP admin password (a kind of out-of-the-box LDAP admin user, no REVOKE or GRANT, etc'..) : + + .. code-block:: postgres + + GRANT PASSWORD <'binding_user_password'> TO ldap_bind_dn_admin_password; + + This password is your LDAP server password. + + This password is encrypted in your SQreamDB metadata. + +2. Set the ``authenticationMethod`` flag: .. code-block:: postgres ALTER SYSTEM SET authenticationMethod = 'ldap'; -2. Set the ``ldapAdvancedMode`` flag: +3. Set the ``ldapAdvancedMode`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapAdvancedMode = true; -3. Set the ``ldapIpAddress`` flag: +4. Set the ``ldapIpAddress`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapIpAddress = '<ldaps://<IpAddress>'; -4. Set the ``ldapBindDn`` flag: +5. Set the ``ldapBindDn`` flag: .. code-block:: postgres ALTER SYSTEM SET ldapBindDn = <binding_user_DN>; - -5. Set the ``ldapBindDnPassword`` flag: - - .. code-block:: postgres - - ALTER SYSTEM SET ldapBindDnPassword = '<binding_user_password>'; 6. Set the ``ldapBaseDn`` flag: @@ -289,6 +293,8 @@ User has value of elonm for attribute ``sAMAccountName``. .. code-block:: postgres + GRANT PASSWORD 'LdapPassword12#4%' TO ldap_bind_dn_admin_password; + ALTER SYSTEM SET authenticationMethod = 'ldap'; ALTER SYSTEM SET ldapAdvancedMode = true; @@ -299,8 +305,6 @@ User has value of elonm for attribute ``sAMAccountName``. ALTER SYSTEM SET ldapBindDn = 'CN=LDAP admin,OU=network admin,DC=sqream,DC=loc'; - ALTER SYSTEM SET ldapBindDnPassword = 'sqream123'; - ALTER SYSTEM SET ldapBaseDn = 'OU=Sqream Users,DC=sqream,DC=loc'; ALTER SYSTEM SET ldapSearchAttribute = 'sAMAccountName'; From f023f8aabaf215222dd45e4e1802abf889057468 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Apr 2024 15:04:37 +0300 Subject: [PATCH 1262/1892] Update ldap.rst --- configuration_guides/ldap.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/configuration_guides/ldap.rst b/configuration_guides/ldap.rst index 76d1932be..6e5b5f3e7 100644 --- a/configuration_guides/ldap.rst +++ b/configuration_guides/ldap.rst @@ -201,17 +201,13 @@ Advanced Method Configuration Only roles with admin privileges and higher may enable LDAP Authentication. -1. Set your LDAP password - -Configure an LDAP admin password (a kind of out-of-the-box LDAP admin user, no REVOKE or GRANT, etc'..) : +1. Configure your LDAP server bind password to be stored in SQreamDB metadata: .. code-block:: postgres GRANT PASSWORD <'binding_user_password'> TO ldap_bind_dn_admin_password; - This password is your LDAP server password. - - This password is encrypted in your SQreamDB metadata. + This action emulates the execution of a ``GRANT`` command, but it's solely necessary for configuring the password. Note that ``ldap_bind_dn_admin_password`` is not an actual SQreamDB role. This password is encrypted within your SQreamDB metadata. 2. Set the ``authenticationMethod`` flag: From d196c0200e97c08026fd305902fdc13d1ff9401b Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 7 Apr 2024 14:57:42 +0300 Subject: [PATCH 1263/1892] Dataiku --- .../client_drivers/dataiku/index.rst | 50 +++++++++++++++++++ connecting_to_sqream/client_drivers/index.rst | 9 +++- 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 connecting_to_sqream/client_drivers/dataiku/index.rst diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst new file mode 100644 index 000000000..d79d8b903 --- /dev/null +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -0,0 +1,50 @@ +.. _dataiku: + +******* +Dataiku +******* + +This Plugin accelerates data transfer from Amazon S3 to SqreamDB within Dataiku DSS. It enables direct loading of data from S3 to SqreamDB, ensuring rapid transfers without external steps. + +The Plugin includes a code environment that automatically installs the SqreamDB Python Connector (pysqream) alongside the Plugin. + +Use your existing AWS S3 buckets and folder paths for bulk loading into SqreamDB the following supported file formats: + +* Avro +* JSON +* CSV + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================= + +It is essential you have the follwoing: + +* Sqreamdb :ref:`java_jdbc` connection set up in DSS + +* Amazon S3 connection set up in DSS + +* Python 3.9 + +Establishing a Dataiku Connection +================================= + +In your Dataiku web interface: + +#. Define a DSS S3 Dataset + +#. Add the Plugin to your Flow. + +#. Set the S3 Dataset as Input of the Plugin (mandatory). + +#. Assign a name for the output Dataset stored in your Sqreamd connection. + +#. Provide AWS Access Key and Secret Key by either: + a. Filling in the values in the Plugin form + + b. Set the Project Variables or set the Global Variables when DSS Variables are used + + diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 21a4db9b6..9b4e96692 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -23,6 +23,11 @@ Client Driver Downloads - :ref:`spark` - - All + * - **Dataiku** + - `Dataiku plugin <>`_ + - :ref:`dataiku` + - + - All * - **JDBC** - `sqream-jdbc 5.2.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.2.0.jar>`_ - :ref:`java_jdbc` @@ -68,12 +73,14 @@ Client Driver Downloads + .. toctree:: :maxdepth: 4 :titlesonly: :hidden: - dotnet/index + dotnet/index + dataiku/index jdbc/index nodejs/index odbc/index From ccbb471a65689a08683d3c7dc0bec02687c0419a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 09:37:29 +0300 Subject: [PATCH 1264/1892] Dataiku --- connecting_to_sqream/client_drivers/dataiku/index.rst | 6 +++++- connecting_to_sqream/client_drivers/index.rst | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index d79d8b903..50973f449 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -36,7 +36,11 @@ In your Dataiku web interface: #. Define a DSS S3 Dataset -#. Add the Plugin to your Flow. +#. Add the Plugin to your Flow using Git repository: + + .. code-block:: console + + git@github.com:SQream/dataiku_plugin.git #. Set the S3 Dataset as Input of the Plugin (mandatory). diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 9b4e96692..1b0119926 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -24,7 +24,7 @@ Client Driver Downloads - - All * - **Dataiku** - - `Dataiku plugin <>`_ + - Plugin Git repository: ``git@github.com:SQream/dataiku_plugin.git`` - :ref:`dataiku` - - All From 1c36304f187058ceb6128e12e73be22e1572c727 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 13:32:11 +0300 Subject: [PATCH 1265/1892] Update index.rst --- connecting_to_sqream/client_drivers/dataiku/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index 50973f449..b15bc12f6 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -8,11 +8,11 @@ This Plugin accelerates data transfer from Amazon S3 to SqreamDB within Dataiku The Plugin includes a code environment that automatically installs the SqreamDB Python Connector (pysqream) alongside the Plugin. -Use your existing AWS S3 buckets and folder paths for bulk loading into SqreamDB the following supported file formats: +The following file formats are supported: * Avro * JSON -* CSV +* CSV (requires manual data type mapping as the default for all columns is ``TEXT``) .. contents:: :local: From b5e4f4813d4445ffb81f624e927433212d1a8a1d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 14:02:10 +0300 Subject: [PATCH 1266/1892] Update values.rst --- .../sql_statements/dml_commands/values.rst | 116 +++++++++++------- 1 file changed, 69 insertions(+), 47 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/values.rst b/reference/sql/sql_statements/dml_commands/values.rst index 4e8e1f28b..aa8d367e1 100644 --- a/reference/sql/sql_statements/dml_commands/values.rst +++ b/reference/sql/sql_statements/dml_commands/values.rst @@ -1,83 +1,105 @@ .. _values: -********************** +****** VALUES -********************** +****** -``VALUES`` is a table constructor - a clause that can be used to define tabular data. - -.. tip:: - * Use VALUES in conjunction with :ref:`INSERT<insert>` statements to insert a set of one or more rows. - - -Permissions -============= - -This clause requires no special permissions. +``VALUES`` is a table constructor used to define tabular data. It’s utilized with :ref:`INSERT<insert>` statements to insert one or more rows. Syntax -========== +====== .. code-block:: postgres - values_expr ::= VALUES ( value_expr [, ... ] ) [, ... ] - ; -Notes +Usage Notes =========== -Each set of comma-separated ``value_expr`` in parentheses represents a single row in the result set. +.. glossary:: + + ``value_expr`` + Each set of comma-separated ``value_expr`` in parentheses represents a single row in the result set. -Column names of the result table are auto-generated. To rename the column names, add an ``AS`` clause. + **Column Names** + Column names of the result table are auto-generated. To rename the column names, add an ``AS`` clause. + + **Aggregations** + Aggregations (e.g., ``SUM``, ``COUNT``) cannot be directly used in the ``VALUES`` clause. Examples -=========== +======== -Tabular data with VALUES --------------------------- +Tabular data with ``VALUES`` +---------------------------- .. code-block:: psql - master=> VALUES (1,2,3,4), (5,6,7,8), (9,10,11,12); - 1,2,3,4 - 5,6,7,8 - 9,10,11,12 - 3 rows + VALUES (1,2,3,4), (5,6,7,8), (9,10,11,12); -Using VALUES with a SELECT query ----------------------------------- + clmn1 |clmn2 |clmn3 |clmn4 + ------+------+------+----- + 1 | 2 | 3 | 4 + 5 | 6 | 7 | 8 + 9 | 10 | 11 | 12 -To use VALUES in a select query, assign a :ref:`name<identifiers>` to the ``VALUES`` clause with ``AS`` +Using ``VALUES`` in a ``SELECT`` Query +-------------------------------------- .. code-block:: postgres - master=> SELECT t.* FROM (VALUES (1,2,3,'a'), (5,6,7,'b'), (9,10,11,'c')) AS t; - 1,2,3,a - 5,6,7,b - 9,10,11,c - - 3 rows + SELECT + t.* + FROM + ( + VALUES + (1, 2, 3, 'a'), + (5, 6, 7, 'b'), + (9, 10, 11, 'c') + ) AS t; + + clmn1 |clmn2 |clmn3 |clmn4 + ------+------+------+----- + 1 | 2 | 3 | a + 5 | 6 | 7 | b + 9 | 10 | 11 | c You can also use this to rename the columns .. code-block:: postgres - SELECT t.* FROM (VALUES (1,2,3,'a'), (5,6,7,'b'), (9,10,11,'c')) AS t(a,b,c,d); - - -Creating a table with ``VALUES`` + SELECT + t.* + FROM + ( + VALUES + (1, 2, 3, 'a'), + (5, 6, 7, 'b'), + (9, 10, 11, 'c') + ) AS t(a, b, c, d); + +Creating a Table Using ``VALUES`` --------------------------------- Use ``AS`` to assign names to columns .. code-block:: postgres - CREATE TABLE cool_animals AS - (SELECT t.* - FROM (VALUES (1, 'dog'), - (2, 'cat'), - (3, 'horse'), - (4, 'hippopotamus') - ) AS t(id, name) - ); + CREATE TABLE + cool_animals AS ( + SELECTt.* + FROM + ( + VALUES + (1, 'dog'), + (2, 'cat'), + (3, 'horse'), + (4, 'hippopotamus') + ) + AS t(id, name) + ); + +Permissions +=========== + +This clause requires no special permissions. \ No newline at end of file From b64be27aac977394fa9f9b5a012697c907124d30 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:40:10 +0300 Subject: [PATCH 1267/1892] dataiku --- .../client_drivers/dataiku/index.rst | 14 +- .../monitoring_query_performance.rst | 394 ++++++++++-------- 2 files changed, 219 insertions(+), 189 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index b15bc12f6..41fe09bc1 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -34,17 +34,23 @@ Establishing a Dataiku Connection In your Dataiku web interface: -#. Define a DSS S3 Dataset - -#. Add the Plugin to your Flow using Git repository: +#. Upload the plugin from the following SQreamDB Git repository: .. code-block:: console + -- Repository URL: git@github.com:SQream/dataiku_plugin.git + + -- Path in repository: + s3_bulk_load + +#. Define a DSS S3 dataset. + +#. Add the plugin to your flow. #. Set the S3 Dataset as Input of the Plugin (mandatory). -#. Assign a name for the output Dataset stored in your Sqreamd connection. +#. Assign a name for the output dataset stored in your SQreamDB connection. #. Provide AWS Access Key and Secret Key by either: a. Filling in the values in the Plugin form diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 25e3f3b8c..a17a66dad 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -29,7 +29,6 @@ To adjust the frequency of logging for statements, you may want to reduce the in say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggingSec`` parameter as you see fit: .. code-block:: console - :emphasize-lines: 7 { @@ -53,61 +52,65 @@ First, create a foreign table for the logs .. code-block:: postgres - CREATE FOREIGN TABLE logs - ( - start_marker TEXT(4), - row_id BIGINT, - timestamp DATETIME, - message_level TEXT, - thread_id TEXT, - worker_hostname TEXT, - worker_port INT, - connection_id INT, - database_name TEXT, - user_name TEXT, - statement_id INT, - service_name TEXT, - message_type_id INT, - message TEXT, - end_message TEXT(5) - ) - WRAPPER csv_fdw - OPTIONS - ( - LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', - DELIMITER = '|' - ) - ; + CREATE FOREIGN TABLE logs ( + start_marker TEXT(4), + row_id BIGINT, + timestamp DATETIME, + message_level TEXT, + thread_id TEXT, + worker_hostname TEXT, + worker_port INT, + connection_id INT, + database_name TEXT, + user_name TEXT, + statement_id INT, + service_name TEXT, + message_type_id INT, + message TEXT, + end_message TEXT(5) + ) + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = '/home/rhendricks/sqream_storage/logs/**/sqream*.log', + DELIMITER = '|' + ); + Once you've defined the foreign table, you can run queries to observe the previously logged execution plans. This is recommended over looking at the raw logs. .. code-block:: postgres - t=> SELECT message - . FROM logs - . WHERE message_type_id = 200 - . AND timestamp BETWEEN '2020-06-11' AND '2020-06-13'; - message - --------------------------------------------------------------------------------------------------------------------------------- - SELECT *,coalesce((depdelay > 15),false) AS isdepdelayed FROM ontime WHERE year IN (2005, 2006, 2007, 2008, 2009, 2010) - : - : 1,PushToNetworkQueue ,10354468,10,1035446,2020-06-12 20:41:42,-1,,,,13.55 - : 2,Rechunk ,10354468,10,1035446,2020-06-12 20:41:42,1,,,,0.10 - : 3,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:42,2,,,,0.00 - : 4,DeferredGather ,10354468,10,1035446,2020-06-12 20:41:42,3,,,,1.23 - : 5,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:41,4,,,,0.01 - : 6,GpuToCpu ,10354468,10,1035446,2020-06-12 20:41:41,5,,,,0.07 - : 7,GpuTransform ,10354468,10,1035446,2020-06-12 20:41:41,6,,,,0.02 - : 8,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:41,7,,,,0.00 - : 9,Filter ,10354468,10,1035446,2020-06-12 20:41:41,8,,,,0.07 - : 10,GpuTransform ,10485760,10,1048576,2020-06-12 20:41:41,9,,,,0.07 - : 11,GpuDecompress ,10485760,10,1048576,2020-06-12 20:41:41,10,,,,0.03 - : 12,GpuTransform ,10485760,10,1048576,2020-06-12 20:41:41,11,,,,0.22 - : 13,CpuToGpu ,10485760,10,1048576,2020-06-12 20:41:41,12,,,,0.76 - : 14,ReorderInput ,10485760,10,1048576,2020-06-12 20:41:40,13,,,,0.11 - : 15,Rechunk ,10485760,10,1048576,2020-06-12 20:41:40,14,,,,5.58 - : 16,CpuDecompress ,10485760,10,1048576,2020-06-12 20:41:34,15,,,,0.04 - : 17,ReadTable ,10485760,10,1048576,2020-06-12 20:41:34,16,832MB,,public.ontime,0.55 + SELECT + message + FROM + logs + WHERE + message_type_id = 200 + AND timestamp BETWEEN '2020-06-11' AND '2020-06-13'; + + message + --------------------------------------------------------------------------------------------------------------------------------- + SELECT *,coalesce((depdelay > 15),false) AS isdepdelayed FROM ontime WHERE year IN (2005, 2006, 2007, 2008, 2009, 2010) + + 1,PushToNetworkQueue ,10354468,10,1035446,2020-06-12 20:41:42,-1,,,,13.55 + 2,Rechunk ,10354468,10,1035446,2020-06-12 20:41:42,1,,,,0.10 + 3,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:42,2,,,,0.00 + 4,DeferredGather ,10354468,10,1035446,2020-06-12 20:41:42,3,,,,1.23 + 5,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:41,4,,,,0.01 + 6,GpuToCpu ,10354468,10,1035446,2020-06-12 20:41:41,5,,,,0.07 + 7,GpuTransform ,10354468,10,1035446,2020-06-12 20:41:41,6,,,,0.02 + 8,ReorderInput ,10354468,10,1035446,2020-06-12 20:41:41,7,,,,0.00 + 9,Filter ,10354468,10,1035446,2020-06-12 20:41:41,8,,,,0.07 + 10,GpuTransform ,10485760,10,1048576,2020-06-12 20:41:41,9,,,,0.07 + 11,GpuDecompress ,10485760,10,1048576,2020-06-12 20:41:41,10,,,,0.03 + 12,GpuTransform ,10485760,10,1048576,2020-06-12 20:41:41,11,,,,0.22 + 13,CpuToGpu ,10485760,10,1048576,2020-06-12 20:41:41,12,,,,0.76 + 14,ReorderInput ,10485760,10,1048576,2020-06-12 20:41:40,13,,,,0.11 + 15,Rechunk ,10485760,10,1048576,2020-06-12 20:41:40,14,,,,5.58 + 16,CpuDecompress ,10485760,10,1048576,2020-06-12 20:41:34,15,,,,0.04 + 17,ReadTable ,10485760,10,1048576,2020-06-12 20:41:34,16,832MB,,public.ontime,0.55 .. _using_show_node_info: @@ -123,20 +126,22 @@ In this example, we inspect a statement with statement ID of 176. The command lo .. code-block:: postgres - t=> SELECT SHOW_NODE_INFO(176); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- - 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 - 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 - 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 - 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 - 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 - 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 - 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 - 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 - 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 - 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 - 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 + SELECT + SHOW_NODE_INFO(176); + + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+--------------------+------+--------+-------------------+---------------------+----------------+------+-------+------------+-------- + 176 | 1 | PushToNetworkQueue | 1 | 1 | 1 | 2019-12-25 23:53:13 | -1 | | | | 0.0025 + 176 | 2 | Rechunk | 1 | 1 | 1 | 2019-12-25 23:53:13 | 1 | | | | 0 + 176 | 3 | GpuToCpu | 1 | 1 | 1 | 2019-12-25 23:53:13 | 2 | | | | 0 + 176 | 4 | ReorderInput | 1 | 1 | 1 | 2019-12-25 23:53:13 | 3 | | | | 0 + 176 | 5 | Filter | 1 | 1 | 1 | 2019-12-25 23:53:13 | 4 | | | | 0.0002 + 176 | 6 | GpuTransform | 457 | 1 | 457 | 2019-12-25 23:53:13 | 5 | | | | 0.0002 + 176 | 7 | GpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 6 | | | | 0 + 176 | 8 | CpuToGpu | 457 | 1 | 457 | 2019-12-25 23:53:13 | 7 | | | | 0.0003 + 176 | 9 | Rechunk | 457 | 1 | 457 | 2019-12-25 23:53:13 | 8 | | | | 0 + 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 + 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 Alternatively, you may also :ref:`retrieve the query execution plan output<retrieving_execution_plan_output_using_studio>` using SQreamDB Studio, and contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. @@ -341,22 +346,36 @@ Identifying the Offending Nodes .. code-block:: postgres - SELECT o_year, - SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share - FROM (SELECT datepart(YEAR,o_orderdate) AS o_year, - l_extendedprice*(1 - l_discount / 100.0) AS volume, - n2.n_name AS nation - FROM lineitem - JOIN part ON p_partkey = CAST (l_partkey AS INT) - JOIN orders ON l_orderkey = o_orderkey - JOIN customer ON o_custkey = c_custkey - JOIN nation n1 ON c_nationkey = n1.n_nationkey - JOIN region ON n1.n_regionkey = r_regionkey - JOIN supplier ON s_suppkey = l_suppkey - JOIN nation n2 ON s_nationkey = n2.n_nationkey - WHERE o_orderdate BETWEEN '1995-01-01' AND '1996-12-31') AS all_nations - GROUP BY o_year - ORDER BY o_year; + SELECT + o_year, + SUM( + CASE + WHEN nation = 'BRAZIL' THEN volume + ELSE 0 + END + ) / SUM(volume) AS mkt_share + FROM + ( + SELECT + datepart(YEAR, o_orderdate) AS o_year, + l_extendedprice * (1 - l_discount / 100.0) AS volume, + n2.n_name AS nation + FROM + lineitem + JOIN part ON p_partkey = CAST (l_partkey AS INT) + JOIN orders ON l_orderkey = o_orderkey + JOIN customer ON o_custkey = c_custkey + JOIN nation n1 ON c_nationkey = n1.n_nationkey + JOIN region ON n1.n_regionkey = r_regionkey + JOIN supplier ON s_suppkey = l_suppkey + JOIN nation n2 ON s_nationkey = n2.n_nationkey + WHERE + o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' + ) AS all_nations + GROUP BY + o_year + ORDER BY + o_year; #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -366,10 +385,9 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``LoopJoin``: .. code-block:: postgres + :emphasize-lines: 33,35,37,39 - :emphasize-lines: 33,35,37,39 - - t=> SELECT message FROM logs WHERE message_type_id = 200 LIMIT 1; + SELECT message FROM logs WHERE message_type_id = 200 LIMIT 1; message ----------------------------------------------------------------------------------------- SELECT o_year, @@ -442,25 +460,28 @@ Identifying the Offending Nodes .. code-block:: postgres - SELECT s.*, - l.*, - r.*, - n1.*, - n2.*, - p.*, - o.*, - c.* - FROM lineitem l - JOIN part p ON p_partkey = CAST (l_partkey AS INT) - JOIN orders o ON l_orderkey = o_orderkey - JOIN customer c ON o_custkey = c_custkey - JOIN nation n1 ON c_nationkey = n1.n_nationkey - JOIN region r ON n1.n_regionkey = r_regionkey - JOIN supplier s ON s_suppkey = l_suppkey - JOIN nation n2 ON s_nationkey = n2.n_nationkey - WHERE r_name = 'AMERICA' - AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' - AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL'); + SELECT + s.*, + l.*, + r.*, + n1.*, + n2.*, + p.*, + o.*, + c.* + FROM + lineitem l + JOIN part p ON p_partkey = CAST (l_partkey AS INT) + JOIN orders o ON l_orderkey = o_orderkey + JOIN customer c ON o_custkey = c_custkey + JOIN nation n1 ON c_nationkey = n1.n_nationkey + JOIN region r ON n1.n_regionkey = r_regionkey + JOIN supplier s ON s_suppkey = l_suppkey + JOIN nation n2 ON s_nationkey = n2.n_nationkey + WHERE + r_name = 'AMERICA' + AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' + AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL'); #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -470,22 +491,21 @@ Identifying the Offending Nodes The execution below has been shortened, but note the highlighted rows for ``DeferredGather``: .. code-block:: postgres - :emphasize-lines: 7,9,11 - t=> SELECT show_node_info(494); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+---------+-------+-----------------+-------- - 494 | 1 | PushToNetworkQueue | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | -1 | | | | 0.36 - 494 | 2 | Rechunk | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 1 | | | | 0 - 494 | 3 | ReorderInput | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 2 | | | | 0 - 494 | 4 | DeferredGather | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 3 | | | | 0.16 - [...] - 494 | 166 | DeferredGather | 3998730 | 39 | 102531 | 2020-09-04 19:07:47 | 165 | | | | 21.75 - [...] - 494 | 194 | DeferredGather | 133241 | 20 | 6662 | 2020-09-04 19:07:03 | 193 | | | | 0.41 - [...] - 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 + SELECT show_node_info(494); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+---------+-------+-----------------+-------- + 494 | 1 | PushToNetworkQueue | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | -1 | | | | 0.36 + 494 | 2 | Rechunk | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 1 | | | | 0 + 494 | 3 | ReorderInput | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 2 | | | | 0 + 494 | 4 | DeferredGather | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | 3 | | | | 0.16 + [...] + 494 | 166 | DeferredGather | 3998730 | 39 | 102531 | 2020-09-04 19:07:47 | 165 | | | | 21.75 + [...] + 494 | 194 | DeferredGather | 133241 | 20 | 6662 | 2020-09-04 19:07:03 | 193 | | | | 0.41 + [...] + 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 When you see ``DeferredGather`` operations taking more than a few seconds, that's a sign that you're selecting too much data. In this case, the DeferredGather with node ID 166 took over 21 seconds. @@ -495,10 +515,11 @@ Identifying the Offending Nodes .. code-block:: postgres - SELECT DATEPART(year, o_orderdate) AS o_year, - l_extendedprice * (1 - l_discount / 100.0) as volume, - n2.n_name as nation - FROM ... + SELECT + DATEPART(year, o_orderdate) AS o_year, + l_extendedprice * (1 - l_discount / 100.0) as volume, + n2.n_name as nation + FROM ... Common Solutions for Reducing Gather Time ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -528,25 +549,39 @@ For example: .. code-block:: postgres - SELECT o_year, - SUM(CASE WHEN nation = 'BRAZIL' THEN volume ELSE 0 END) / SUM(volume) AS mkt_share - FROM (SELECT datepart(YEAR,o_orderdate) AS o_year, - l_extendedprice*(1 - l_discount / 100.0) AS volume, - n2.n_name AS nation - FROM lineitem - JOIN part ON p_partkey = CAST (l_partkey AS INT) - JOIN orders ON l_orderkey = o_orderkey - JOIN customer ON o_custkey = c_custkey - JOIN nation n1 ON c_nationkey = n1.n_nationkey - JOIN region ON n1.n_regionkey = r_regionkey - JOIN supplier ON s_suppkey = l_suppkey - JOIN nation n2 ON s_nationkey = n2.n_nationkey - WHERE r_name = 'AMERICA' - AND lineitem.l_quantity = 3 - AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' - AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL')) AS all_nations - GROUP BY o_year - ORDER BY o_year; + SELECT + o_year, + SUM( + CASE + WHEN nation = 'BRAZIL' THEN volume + ELSE 0 + END + ) / SUM(volume) AS mkt_share + FROM + ( + SELECT + datepart(YEAR, o_orderdate) AS o_year, + l_extendedprice * (1 - l_discount / 100.0) AS volume, + n2.n_name AS nation + FROM + lineitem + JOIN part ON p_partkey = CAST (l_partkey AS INT) + JOIN orders ON l_orderkey = o_orderkey + JOIN customer ON o_custkey = c_custkey + JOIN nation n1 ON c_nationkey = n1.n_nationkey + JOIN region ON n1.n_regionkey = r_regionkey + JOIN supplier ON s_suppkey = l_suppkey + JOIN nation n2 ON s_nationkey = n2.n_nationkey + WHERE + r_name = 'AMERICA' + AND lineitem.l_quantity = 3 + AND o_orderdate BETWEEN '1995-01-01' AND '1996-12-31' + AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL') + ) AS all_nations + GROUP BY + o_year + ORDER BY + o_year; #. Observe the execution information by using the foreign table, or use ``show_node_info`` @@ -554,11 +589,10 @@ For example: The execution below has been shortened, but note the highlighted rows for ``ReadTable`` and ``Filter``: .. code-block:: postgres - :linenos: :emphasize-lines: 9,17,19,27 - t=> SELECT show_node_info(559); + SELECT show_node_info(559); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+--------+-------+-----------------+-------- 559 | 1 | PushToNetworkQueue | 2 | 1 | 2 | 2020-09-07 11:12:01 | -1 | | | | 0.28 @@ -600,7 +634,6 @@ For example: Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQreamDB skip reading the data. .. code-block:: postgres - :emphasize-lines: 15 SELECT o_year, @@ -624,11 +657,10 @@ For example: ORDER BY o_year; .. code-block:: postgres - :linenos: :emphasize-lines: 5,13 - t=> SELECT show_node_info(586); + SELECT show_node_info(586); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+--------+-------+-----------------+-------- [...] @@ -703,11 +735,10 @@ For example, consider these two table structures: joining 1.5 billion records. .. code-block:: postgres - :linenos: :emphasize-lines: 8 - t=> SELECT show_node_info(5); + SELECT show_node_info(5); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -744,11 +775,10 @@ Improving Query Performance The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. .. code-block:: postgres - :linenos: :emphasize-lines: 8 - t=> SELECT show_node_info(6); + SELECT show_node_info(6); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -784,7 +814,6 @@ For example: Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: .. code-block:: postgres - :emphasize-lines: 5 CREATE TABLE t_inefficient ( @@ -800,12 +829,12 @@ For example: .. code-block:: postgres - t=> SELECT country_code, - . SUM(amt) - . FROM t_inefficient - . GROUP BY country_code; - executed - time: 47.55s + SELECT + country_code, + SUM(amt) + FROM t_inefficient + GROUP BY country_code; + country_code | sum -------------+----------- @@ -816,10 +845,9 @@ For example: .. code-block:: postgres - :emphasize-lines: 8,9 - t=> select show_node_info(30); + SELECT SHOW_NODE_INFO(30); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+--------------------+----------+--------+-------------------+---------------------+----------------+-------+-------+----------------------+-------- 30 | 1 | PushToNetworkQueue | 249 | 1 | 249 | 2020-09-10 16:17:10 | -1 | | | | 0.25 @@ -839,7 +867,7 @@ For example: .. code-block:: postgres - t=> SELECT MAX(LEN(country_code)) FROM t_inefficient; + SELECT MAX(LEN(country_code)) FROM t_inefficient; max --- 3 @@ -849,22 +877,20 @@ For example: .. code-block:: postgres - t=> CREATE TABLE t_efficient - . AS SELECT i, - . amt, - . ts, - . country_code::TEXT(3) AS country_code, - . flag - . FROM t_inefficient; - executed - time: 16.03s + CREATE TABLE t_efficient + AS SELECT i, + amt, + ts, + country_code::TEXT(3) AS country_code, + flag + FROM t_inefficient; - t=> SELECT country_code, - . SUM(amt::bigint) - . FROM t_efficient - . GROUP BY country_code; - executed - time: 4.75s + SELECT + country_code, + SUM(amt::bigint) + FROM t_efficient + GROUP BY country_code; + country_code | sum -------------+----------- VUT | 1195416012 @@ -903,7 +929,7 @@ Consider this execution plan: .. code-block:: postgres - t=> select show_node_info(30); + SELECT SHOW_NODE_INFO(30); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+-------------------+-----------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -936,10 +962,9 @@ In this case, we're also interested in the number of chunks produced by these no Consider this execution plan: .. code-block:: postgres - :emphasize-lines: 6,11 - t=> select show_node_info(30); + SELECT SHOW_NODE_INFO(30); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+-------------------+-----------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -954,6 +979,7 @@ Consider this execution plan: 30 | 38 | Filter | 18160 | 74 | 245 | 2020-09-10 12:17:09 | 37 | | | | 0.012 [...] 30 | 44 | ReadTable | 77000000 | 74 | 1040540 | 2020-09-10 12:17:09 | 43 | 277MB | | public.dim | 0.058 + * ``Join`` is the node that matches rows from both table relations. * ``DeferredGather`` gathers the required column chunks to decompress Pay special attention to the volume of data removed by the ``Filter`` node. @@ -970,24 +996,23 @@ This forces the compiler to rechunk the data into fewer chunks. To tell SQreamDB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: .. code-block:: postgres - :emphasize-lines: 13 -- Without the hint SELECT * FROM cdrs WHERE - RequestReceiveTime BETWEEN '2018-01-01 00:00:00.000' AND '2018-08-31 23:59:59.999' - AND EnterpriseID=1150 - AND MSISDN='9724871140341'; + RequestReceiveTime BETWEEN '2018-01-01 00:00:00.000' AND '2018-08-31 23:59:59.999' + AND EnterpriseID=1150 + AND MSISDN='9724871140341'; -- With the hint SELECT * FROM cdrs WHERE - HIGH_SELECTIVITY(RequestReceiveTime BETWEEN '2018-01-01 00:00:00.000' AND '2018-08-31 23:59:59.999') - AND EnterpriseID=1150 - AND MSISDN='9724871140341'; + HIGH_SELECTIVITY(RequestReceiveTime BETWEEN '2018-01-01 00:00:00.000' AND '2018-08-31 23:59:59.999') + AND EnterpriseID=1150 + AND MSISDN='9724871140341'; Manual Join Reordering ---------------------- @@ -1010,7 +1035,6 @@ Changing the join order can reduce the query runtime significantly. In the examp from 27.3 seconds to just 6.4 seconds. .. code-block:: postgres - :caption: Original query -- This variant runs in 27.3 seconds From 7471e706d220d00e595fbff3bd0c5c47223392dc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 16:17:58 +0300 Subject: [PATCH 1268/1892] Update index.rst --- connecting_to_sqream/client_drivers/dataiku/index.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index 41fe09bc1..ff5787bcb 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -14,10 +14,6 @@ The following file formats are supported: * JSON * CSV (requires manual data type mapping as the default for all columns is ``TEXT``) -.. contents:: - :local: - :depth: 1 - Before You Begin ================= From 335144053087644858eb573f3e9f9f97224197b8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Apr 2024 17:06:41 +0300 Subject: [PATCH 1269/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index a17a66dad..3289751ce 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -4,31 +4,25 @@ Monitoring Query Performance **************************** -When analyzing options for query tuning, the first step is to analyze the query plan and execution. -The query plan and execution details explain how SQreamDB processes a query and where time is spent. -This document details how to analyze query performance with execution plans. -This guide focuses specifically on identifying bottlenecks and possible optimization techniques to improve query performance. -Performance tuning options for each query are different. You should adapt the recommendations and tips for your own workloads. -See also our :ref:`sql_best_practices` guide for more information about data loading considerations and other best practices. +The initial step in query tuning involves a thorough analysis of the query plan and its execution. The query plan and execution details illuminate how SQreamDB handles a query and pinpoint where time resources are consumed. This document offers a comprehensive guide on analyzing query performance through execution plans, with a specific emphasis on recognizing bottlenecks and exploring potential optimization strategies to enhance query efficiency. + +It's important to note that performance tuning approaches can vary for each query, necessitating adaptation of recommendations and tips to suit specific workloads. Additionally, for further insights into data loading considerations and other best practices, refer to our :ref:`sql_best_practices` guide. .. contents:: :local: :depth: 1 - Setting Up the System for Monitoring ==================================== -By default, SQreamDB logs execution details for every statement that runs for more than 60 seconds. -If you want to see the execution details for a currently running statement, see :ref:`using_show_node_info` below. +By default, SQreamDB automatically logs execution details for any statement that runs longer than 60 seconds. Adjusting the Logging Frequency ------------------------------- -To adjust the frequency of logging for statements, you may want to reduce the interval from 60 seconds down to, -say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggingSec`` parameter as you see fit: +To customize statement logging frequency to be more frequent, consider reducing the interval from the default 60 seconds to a shorter duration like 5 or 10 seconds. This adjustment can be made by modifying the :ref:`configuration files<current_method_modification_methods>` and setting the ``nodeInfoLoggingSec`` parameter to your preferred value. -.. code-block:: console +.. code-block:: json :emphasize-lines: 7 { @@ -42,8 +36,10 @@ say, 5 or 10 seconds. Modify the configuration files and set the ``nodeInfoLoggi "server":{ } } -After restarting the SQreamDB cluster, the execution plan details will be logged to the :ref:`standard SQreamDB logs directory<logging>`, as a message of type ``200``. -You can see these messages with a text viewer or with queries on the log :ref:`foreign_tables`. + +After customizing the frequency, restart your SQreamDB cluster to have the execution plan details logged to the default SQreamDB :ref:`log directory<logging>`, as a :ref:`message type<message_type>` ``200``. + +You can view all log message details either using a text viewer or by creating dedicated :ref:`foreign table<foreign_tables>` to store and access the logs. Reading Execution Plans with a Foreign Table -------------------------------------------- From 3c00f11b2b7f9edeb3b481755de699f17c7173da Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 09:11:56 +0300 Subject: [PATCH 1270/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 3289751ce..94a1a5421 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -12,15 +12,15 @@ It's important to note that performance tuning approaches can vary for each quer :local: :depth: 1 -Setting Up the System for Monitoring -==================================== +Setting Up System Monitoring Preferences +======================================== -By default, SQreamDB automatically logs execution details for any statement that runs longer than 60 seconds. +By default, SQreamDB automatically logs execution details for any query that runs longer than 60 seconds. This means that by default, queries shorter than 60 seconds are not logged. You can adjust this parameter to your own preference. Adjusting the Logging Frequency ------------------------------- -To customize statement logging frequency to be more frequent, consider reducing the interval from the default 60 seconds to a shorter duration like 5 or 10 seconds. This adjustment can be made by modifying the :ref:`configuration files<current_method_modification_methods>` and setting the ``nodeInfoLoggingSec`` parameter to your preferred value. +To customize statement logging frequency to be more frequent, consider reducing the interval from the default 60 seconds to a shorter duration like 5 or 10 seconds. This adjustment can be made by modifying the ``nodeInfoLoggingSec`` in your SQreamDB :ref:`configuration files<current_method_modification_methods>` and setting the parameter to your preferred value. .. code-block:: json :emphasize-lines: 7 @@ -37,9 +37,9 @@ To customize statement logging frequency to be more frequent, consider reducing } } -After customizing the frequency, restart your SQreamDB cluster to have the execution plan details logged to the default SQreamDB :ref:`log directory<logging>`, as a :ref:`message type<message_type>` ``200``. +After customizing the frequency, please restart your SQreamDB cluster. Execution plan details are logged to the default SQreamDB :ref:`log directory<logging>` as :ref:`message type<message_type>` ``200``. -You can view all log message details either using a text viewer or by creating dedicated :ref:`foreign table<foreign_tables>` to store and access the logs. +You can access these log details by using a text viewer or by creating a dedicated :ref:`foreign table<foreign_tables>` to store the logs in a SQreamDB table. Reading Execution Plans with a Foreign Table -------------------------------------------- From af56ca21039c0df32b554f439e45ec96e03426da Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 09:28:56 +0300 Subject: [PATCH 1271/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 94a1a5421..77d772d9c 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -41,15 +41,17 @@ After customizing the frequency, please restart your SQreamDB cluster. Execution You can access these log details by using a text viewer or by creating a dedicated :ref:`foreign table<foreign_tables>` to store the logs in a SQreamDB table. -Reading Execution Plans with a Foreign Table --------------------------------------------- +Creating a Dedicated Foreign Table to Store Log Details +------------------------------------------------------- -First, create a foreign table for the logs +Utilizing a SQreamDB table for storing and accessing log details helps simplify log management by avoiding direct handling of raw logs. + +To create a foreign table for storing your log details, use the following table DDL: .. code-block:: postgres CREATE FOREIGN TABLE logs ( - start_marker TEXT(4), + start_marker TEXT, row_id BIGINT, timestamp DATETIME, message_level TEXT, @@ -63,7 +65,7 @@ First, create a foreign table for the logs service_name TEXT, message_type_id INT, message TEXT, - end_message TEXT(5) + end_message TEXT ) WRAPPER csv_fdw @@ -73,8 +75,7 @@ First, create a foreign table for the logs DELIMITER = '|' ); -Once you've defined the foreign table, you can run queries to observe the previously logged execution plans. -This is recommended over looking at the raw logs. +Use the following query structure as an example to view previously logged execution plans: .. code-block:: postgres From 3757dcc71ed6fb4ff26f144577e52d03f554c1d7 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 09:55:33 +0300 Subject: [PATCH 1272/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 77d772d9c..47b263804 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -114,12 +114,11 @@ Use the following query structure as an example to view previously logged execut Using the ``SHOW_NODE_INFO`` Command ==================================== -The :ref:`show_node_info` command returns a snapshot of the current query plan, similar to ``EXPLAIN ANALYZE`` from other databases. -The :ref:`show_node_info` result, just like the periodically-logged execution plans described above, are an at-the-moment -view of the compiler's execution plan and runtime statistics for the specified statement. -To inspect a currently running statement, execute the ``show_node_info`` utility function in a SQL client like :ref:`sqream sql<sqream_sql_cli_reference>`, the :ref:`SQream Studio Editor<studio_editor>`, or any other :ref:`third party SQL terminal<third_party_tools>`. +The :ref:`show_node_info` command provides a snapshot of the current query plan. Similar to periodically-logged execution plans, ``SHOW_NODE_INFO`` displays the compiler's execution plan and runtime statistics for a specified statement at the moment of execution. -In this example, we inspect a statement with statement ID of 176. The command looks like this: +You can execute the ``SHOW_NODE_INFO`` utility function using :ref:`sqream sql<sqream_sql_cli_reference>`, :ref:`SQream Studio Editor<sqream_studio_>`, or other :ref:`third party tool<client_platforms>`. + +In this example, we inspect a statement with statement ID of 176: .. code-block:: postgres @@ -140,7 +139,7 @@ In this example, we inspect a statement with statement ID of 176. The command lo 176 | 10 | CpuDecompress | 457 | 1 | 457 | 2019-12-25 23:53:13 | 9 | | | | 0 176 | 11 | ReadTable | 457 | 1 | 457 | 2019-12-25 23:53:13 | 10 | 4MB | | public.nba | 0.0004 -Alternatively, you may also :ref:`retrieve the query execution plan output<retrieving_execution_plan_output_using_studio>` using SQreamDB Studio, and contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. +You may also :ref:`download the query execution plan<retrieving_execution_plan_output_using_studio>` to a CSV file using the **Execution Details View** feature. Understanding the Query Execution Plan Output ============================================= From fa097a6ebed969457c8e8d49071a0b575969d0f7 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 10:50:34 +0300 Subject: [PATCH 1273/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 47b263804..85e0dbed1 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -314,8 +314,7 @@ Commonly Seen Nodes Examples ======== -In general, looking at the top three longest running nodes (as is detailed in the ``timeSum`` column) can indicate the biggest bottlenecks. -In the following examples you will learn how to identify and solve some common issues. +Typically, examining the top three longest running nodes (detailed in the ``timeSum`` column) can highlight major bottlenecks. The following examples will demonstrate how to identify and address common issues. .. contents:: In this section: :local: From 3e3ce89bab4cc63ba3e3e4a48b19ad99e17359e3 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 10:52:03 +0300 Subject: [PATCH 1274/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 85e0dbed1..5b5c0c4c3 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -316,9 +316,9 @@ Examples Typically, examining the top three longest running nodes (detailed in the ``timeSum`` column) can highlight major bottlenecks. The following examples will demonstrate how to identify and address common issues. -.. contents:: In this section: +.. contents:: :local: - :depths: 1 + :depth: 1 Spooling to Disk ---------------- From 337773458ba7b5430a6393cbc7f7fbaf7a870cc6 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 10:58:03 +0300 Subject: [PATCH 1275/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 5b5c0c4c3..776501d7a 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -323,13 +323,9 @@ Typically, examining the top three longest running nodes (detailed in the ``time Spooling to Disk ---------------- -When there is not enough RAM to process a statement, SQreamDB will spill over data to the ``temp`` folder in the storage disk. -While this ensures that a statement can always finish processing, it can slow down the processing significantly. -It's worth identifying these statements, to figure out if the cluster is configured correctly, as well as potentially reduce -the statement size. -You can identify a statement that spools to disk by looking at the ``write`` column in the execution details. -A node that spools will have a value, shown in megabytes in the ``write`` column. -Common nodes that write spools include ``Join`` or ``LoopJoin``. +When SQreamDB doesn't have enough RAM to process a statement, it will temporarily store overflow data in the ``temp`` folder on the storage disk. While this ensures that statements complete processing, it can significantly slow down performance. It's important to identify these statements to assess cluster configuration and potentially optimize statement size. + +To identify statements that spill data to disk, check the ``write`` column in the execution details. Nodes that write to disk will display a value (in megabytes) in this column. Common nodes that may write spillover data include ``Join`` and ``LoopJoin``. Identifying the Offending Nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 7bc1d863d264e9bbce444cb41bea8594f86557d4 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 11:13:28 +0300 Subject: [PATCH 1276/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 776501d7a..54ef14d76 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -333,7 +333,7 @@ Identifying the Offending Nodes #. Run a query. - For example, a query from the TPC-H benchmark: + This example is from the TPC-H benchmark: .. code-block:: postgres @@ -369,7 +369,7 @@ Identifying the Offending Nodes o_year; #. - Observe the execution information by using the foreign table, or use ``show_node_info`` + Use a foreign table or ``show_node_info`` to view the execution information. This statement is made up of 199 nodes, starting from a ``ReadTable``, and finishes by returning only 2 results to the client. @@ -419,9 +419,10 @@ Identifying the Offending Nodes : 150,LoopJoin ,182369485,10,18236948,2020-09-04 18:31:47,149,12860MB,12860MB,inner,23.62 [...] : 199,ReadTable ,20000000,1,20000000,2020-09-04 18:30:33,198,0MB,,public.part,0.83 - Because of the relatively low amount of RAM in the machine and because the data set is rather large at around 10TB, SQreamDB needs to spool. - The total spool used by this query is around 20GB (1915MB + 2191MB + 3064MB + 12860MB). + Due to the machine's limited RAM and the large dataset of approximately 10TB, SQreamDB requires spooling. + + The total spool used by this query amounts to approximately 20GB (1915MB + 2191MB + 3064MB + 12860MB). Common Solutions for Reducing Spool ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 3b57b9c83d228cbd9a09058c888fed43bc56d32e Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 14:07:18 +0300 Subject: [PATCH 1277/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 54ef14d76..ec5d2805d 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -427,14 +427,24 @@ Identifying the Offending Nodes Common Solutions for Reducing Spool ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* - Increase the amount of spool memory available for the workers, as a proportion of the maximum statement memory. - When the amount of spool memory is increased, SQreamDB may not need to write to disk. +.. list-table:: + :widths: auto + :header-rows: 1 - This setting is called ``spoolMemoryGB``. Refer to the :ref:`configuration` guide. -* - Reduce the amount of **workers** per host, and increase the amount of spool available to the (now reduced amount of) active workers. - This may reduce the amount of concurrent statements, but will improve performance for heavy statements. + * - Solution + - Description + * - Increasing Spool Memory Amount + - Increase the amount of spool memory available for the Workers relative to the maximum statement memory. By increasing spool memory, SQreamDB may avoid the need to write to disk. This setting is known as ``spoolMemoryGB``. Refer to the :ref:`concurrency_and_scaling_in_sqream` guide for details. + * - Reducing Workers Per Host + - Reduce the number of Workers per host and allocate more spool memory to the reduced number of active Workers. This approach may decrease concurrent statements but can enhance performance for resource-intensive queries. + + + + + + + + Queries with Large Result Sets ------------------------------ From d2fe3fd35f37ac8e69a2a0d7cfa7c3d009d5d382 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 14:24:35 +0300 Subject: [PATCH 1278/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index ec5d2805d..72cfd71fc 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -437,20 +437,11 @@ Common Solutions for Reducing Spool - Increase the amount of spool memory available for the Workers relative to the maximum statement memory. By increasing spool memory, SQreamDB may avoid the need to write to disk. This setting is known as ``spoolMemoryGB``. Refer to the :ref:`concurrency_and_scaling_in_sqream` guide for details. * - Reducing Workers Per Host - Reduce the number of Workers per host and allocate more spool memory to the reduced number of active Workers. This approach may decrease concurrent statements but can enhance performance for resource-intensive queries. - - - - - - - - Queries with Large Result Sets ------------------------------ -When queries have large result sets, you may see a node called ``DeferredGather``. -This gathering occurs when the result set is assembled, in preparation for sending it to the client. +When queries produce large result sets, you may encounter a node called ``DeferredGather``. This node is responsible for assembling the result set in preparation for sending it to the client. Identifying the Offending Nodes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 07b3f575f7c89fdd092515d2e74ff4f64e700847 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 9 Apr 2024 15:05:07 +0300 Subject: [PATCH 1279/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 72cfd71fc..a38b3f758 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -449,7 +449,7 @@ Identifying the Offending Nodes #. Run a query. - For example, a modified query from the TPC-H benchmark: + This example is from the TPC-H benchmark: .. code-block:: postgres @@ -477,7 +477,7 @@ Identifying the Offending Nodes AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL'); #. - Observe the execution information by using the foreign table, or use ``show_node_info`` + Use a foreign table or ``show_node_info`` to view the execution information. This statement is made up of 221 nodes, containing 8 ``ReadTable`` nodes, and finishes by returning billions of results to the client. @@ -500,11 +500,13 @@ Identifying the Offending Nodes [...] 494 | 221 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-04 19:07:01 | 220 | 20MB | | public.part | 0.1 - When you see ``DeferredGather`` operations taking more than a few seconds, that's a sign that you're selecting too much data. - In this case, the DeferredGather with node ID 166 took over 21 seconds. + If you notice that ``DeferredGather`` operations are taking more than a few seconds, it could indicate that you're selecting a large amount of data. For example, in this case, the ``DeferredGather`` with node ID 166 took over 21 seconds. -#. Modify the statement to see the difference - Altering the select clause to be more restrictive will reduce the deferred gather time back to a few milliseconds. +#. + + Modify the statement by making the ``SELECT`` clause more restrictive. + + This adjustment will reduce the DeferredGather time from several seconds to just a few milliseconds. .. code-block:: postgres @@ -517,8 +519,14 @@ Identifying the Offending Nodes Common Solutions for Reducing Gather Time ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* Reduce the effect of the preparation time. Avoid selecting unnecessary columns (``SELECT * FROM...``), or reduce the result set size by using more filters. -.. `` +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Solution + - Description + * - minimizing preparation time + - To minimize preparation time, avoid selecting unnecessary columns (e.g., ``SELECT * FROM`` ...) or reduce the result set size by applying more filters. Inefficient Filtering --------------------- From 285263e8256c9d1b91e596ce7e625feebfad5929 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Apr 2024 11:21:22 +0300 Subject: [PATCH 1280/1892] Monitoring query performance edit --- architecture/internals_architecture.rst | 14 +++-- .../monitoring_query_performance.rst | 63 +++++++++++-------- 2 files changed, 44 insertions(+), 33 deletions(-) diff --git a/architecture/internals_architecture.rst b/architecture/internals_architecture.rst index a47092fb6..af4e21f73 100644 --- a/architecture/internals_architecture.rst +++ b/architecture/internals_architecture.rst @@ -21,27 +21,29 @@ The SQreamDB execution engine employs thread workers and message passing for its Learn more about :ref:`concurrency_and_scaling_in_sqream`. Statement Compiler -============================ +================== The Statement Compiler, developed using Haskell, accepts SQL text and generates optimized statement execution plans. Building Blocks (GPU Workers) -============================== +============================= In SQreamDB, the main workload is carried out by specialized C++/CUDA building blocks, also known as Workers, which intentionally lack inherent intelligence and require precise instructions for operation. Effectively assembling these components relies largely on the capabilities of the statement compiler. Storage Layer -================ +============= The storage is split into the metadata layer and an append-only data layer. Metadata Layer ------------------- +-------------- Utilizing RocksDB key/value data store, the metadata layer incorporates features such as snapshots and atomic writes within the transaction system, while working in conjunction with the append-only bulk data layer to maintain overall data consistency. +.. _bulk_data_layer_optimization: + Bulk Data Layer Optimization ------------------------------------- +---------------------------- SQreamDB harnesses the power of its columnar storage architecture within the bulk data layer for performance optimization. This layer employs IO-optimized extents containing compression-enabled CPU and GPU-efficient chunks. Even during small insert operations, SQreamDB maintains efficiency by generating less optimized chunks and extents as needed. This is achieved through background transactional reorganization, such as ``DeferredGather``, that doesn't disrupt Data Manipulation Language (DML) operations. Deferred Gather optimizes GPU processing by selectively gathering only the necessary columns after GPU execution, effectively conserving memory and enhancing query performance. @@ -49,7 +51,7 @@ The system initially writes small chunks via small inserts and subsequently reor Transactions -============================ +============ SQreamDB has serializable (auto commit) transactions, with these features: diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index a38b3f758..b52db95e2 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -506,7 +506,7 @@ Identifying the Offending Nodes Modify the statement by making the ``SELECT`` clause more restrictive. - This adjustment will reduce the DeferredGather time from several seconds to just a few milliseconds. + This adjustment will reduce the ``DeferredGather`` time from several seconds to just a few milliseconds. .. code-block:: postgres @@ -531,21 +531,18 @@ Common Solutions for Reducing Gather Time Inefficient Filtering --------------------- -When running statements, SQreamDB tries to avoid reading data that is not needed for the statement by :ref:`skipping chunks<chunks_and_extents>`. -If statements do not include efficient filtering, SQreamDB will read a lot of data off disk. -In some cases, you need the data and there's nothing to do about it. However, if most of it gets pruned further down the line, -it may be efficient to skip reading the data altogether by using the :ref:`metadata<metadata_system>`. +When executing statements, SQreamDB optimizes data retrieval by :ref:`skipping unnecessary chunks<bulk_data_layer_optimization>`. However, if statements lack efficient filtering, SQreamDB may end up reading excessive data from disk. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -We consider the filtering to be inefficient when the ``Filter`` node shows that the number of rows processed is less -than a third of the rows passed into it by the ``ReadTable`` node. -For example: +Filtering is considered inefficient when the ``Filter`` node processes less than one-third of the rows passed into it by the ``ReadTable`` node. + #. Run a query. In this example, we execute a modified query from the TPC-H benchmark. + Our ``lineitem`` table contains 600,037,902 rows. .. code-block:: postgres @@ -585,7 +582,7 @@ For example: o_year; #. - Observe the execution information by using the foreign table, or use ``show_node_info`` + Use a foreign table or ``show_node_info`` to view the execution information. The execution below has been shortened, but note the highlighted rows for ``ReadTable`` and ``Filter``: @@ -620,19 +617,20 @@ For example: 559 | 214 | Rechunk | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 213 | | | | 0 559 | 215 | CpuDecompress | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 214 | | | | 0 559 | 216 | ReadTable | 20000000 | 20 | 1000000 | 2020-09-07 11:11:57 | 215 | 20MB | | public.part | 0 + + Note the following: + + * The ``Filter`` on line 9 has processed 12,007,447 rows, but the output of ``ReadTable`` on ``public.lineitem`` on line 17 was 600,037,902 rows. + + This means that it has filtered out 98% (:math:`1 - \dfrac{600037902}{12007447} = 98\%`) of the data, but the entire table was read. - * - The ``Filter`` on line 9 has processed 12,007,447 rows, but the output of ``ReadTable`` on ``public.lineitem`` - on line 17 was 600,037,902 rows. This means that it has filtered out 98% (:math:`1 - \dfrac{600037902}{12007447} = 98\%`) - of the data, but the entire table was read. - - * - The ``Filter`` on line 19 has processed 133,000 rows, but the output of ``ReadTable`` on ``public.part`` - on line 27 was 20,000,000 rows. This means that it has filtered out >99% (:math:`1 - \dfrac{133241}{20000000} = 99.4\%`) - of the data, but the entire table was read. However, this table is small enough that we can ignore it. + * The ``Filter`` on line 19 has processed 133,000 rows, but the output of ``ReadTable`` on ``public.part`` on line 27 was 20,000,000 rows. + + This means that it has filtered out >99% (:math:`1 - \dfrac{133241}{20000000} = 99.4\%`) of the data, but the entire table was read. However, this table is small enough that we can ignore it. -#. Modify the statement to see the difference - Altering the statement to have a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table will help SQreamDB skip reading the data. +#. modify the statement by adding a ``WHERE`` condition on the clustered ``l_orderkey`` column of the ``lineitem`` table. + + This adjustment will enable SQreamDB to skip reading unnecessary data. .. code-block:: postgres :emphasize-lines: 15 @@ -675,17 +673,28 @@ For example: 586 | 197 | CpuDecompress | 494927872 | 8 | 61865984 | 2020-09-07 13:20:44 | 196 | | | | 0 586 | 198 | ReadTable | 494927872 | 8 | 61865984 | 2020-09-07 13:20:44 | 197 | 6595MB | | public.lineitem | 0.09 [...] - In this example, the filter processed 494,621,593 rows, while the output of ``ReadTable`` on ``public.lineitem`` - was 494,927,872 rows. This means that it has filtered out all but 0.01% (:math:`1 - \dfrac{494621593}{494927872} = 0.01\%`) - of the data that was read. - The metadata skipping has performed very well, and has pre-filtered the data for us by pruning unnecessary chunks. + Note the following: + + * The filter processed 494,621,593 rows, while the output of ``ReadTable`` on ``public.lineitem`` was 494,927,872 rows. + + This means that it has filtered out all but 0.01% (:math:`1 - \dfrac{494621593}{494927872} = 0.01\%`) of the data that was read. + + * The metadata skipping has performed very well, and has pre-filtered the data for us by pruning unnecessary chunks. Common Solutions for Improving Filtering ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* Use :ref:`clustering keys and naturally ordered data<data_clustering>` in your filters. -* Avoid full table scans when possible +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Solution + - Description + * - :ref:`Clustering keys<cluster_by>` and ordering data + - Utilize clustering keys and naturally ordered data to enhance filtering efficiency. + * - Avoiding full table scans + - Minimize full table scans by applying targeted filtering conditions. Joins with ``text`` Keys ------------------------ @@ -944,7 +953,7 @@ All of these rows could fit in one single chunk, instead of spanning 74 rather s Improving Performance with High Selectivity Hints ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * - Use when there's a ``WHERE`` condition on an :ref:`unclustered column<data_clustering>`, and when you expect the filter + Use when there's a ``WHERE`` condition on an :ref:`unclustered column<cluster_by>`, and when you expect the filter to cut out more than 60% of the result set. * Use when the data is uniformly distributed or random From 605639d744f0586ad913548ef0515285f89bcb34 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Apr 2024 13:57:18 +0300 Subject: [PATCH 1281/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 143 ++++++++++-------- 1 file changed, 80 insertions(+), 63 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index b52db95e2..0f96a1800 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -696,53 +696,57 @@ Common Solutions for Improving Filtering * - Avoiding full table scans - Minimize full table scans by applying targeted filtering conditions. -Joins with ``text`` Keys +Joins with ``TEXT`` Keys ------------------------ -Joins on long text keys do not perform as well as numeric data types or very short text keys. +Joins on long ``TEXT`` keys may result in reduced performance compared to joins on ``NUMERIC`` data types or very short ``TEXT`` keys. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -When a join is inefficient, you may note that a query spends a lot of time on the ``Join`` node. -For example, consider these two table structures: +When a join is inefficient, you may observe that a query spends a significant amount of time on the ``Join`` node. + +Consider these two table structures: .. code-block:: postgres - CREATE TABLE t_a - ( - amt FLOAT NOT NULL, - i INT NOT NULL, - ts DATETIME NOT NULL, - country_code TEXT(3) NOT NULL, - flag TEXT(10) NOT NULL, - fk TEXT(50) NOT NULL - ); - CREATE TABLE t_b - ( - id TEXT(50) NOT NULL - prob FLOAT NOT NULL, - j INT NOT NULL, - ); + CREATE TABLE + t_a ( + amt FLOAT NOT NULL, + i INT NOT NULL, + ts DATETIME NOT NULL, + country_code TEXT NOT NULL, + flag TEXT NOT NULL, + fk TEXT NOT NULL + ); + + CREATE TABLE + t_b ( + id TEXT NOT NULL, + prob FLOAT NOT NULL, + j INT NOT NULL + ); #. Run a query. - In this example, we will join ``t_a.fk`` with ``t_b.id``, both of which are ``TEXT(50)``. + In this example, we join ``t_a.fk`` with ``t_b.id``, both of which are ``TEXT``. .. code-block:: postgres - SELECT AVG(t_b.j :: BIGINT), - t_a.country_code - FROM t_a - JOIN t_b ON (t_a.fk = t_b.id) - GROUP BY t_a.country_code + SELECT + AVG(t_b.j :: BIGINT), + t_a.country_code + FROM + t_a + JOIN t_b ON (t_a.fk = t_b.id) + GROUP BY + t_a.country_code; + #. - Observe the execution information by using the foreign table, or use ``show_node_info`` + Use a foreign table or ``show_node_info`` to view the execution information. The execution below has been shortened, but note the highlighted rows for ``Join``. - The ``Join`` node is by far the most time-consuming part of this statement - clocking in at 69.7 seconds - joining 1.5 billion records. .. code-block:: postgres :linenos: @@ -764,52 +768,65 @@ For example, consider these two table structures: 5 | 41 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 40 | | | | 0 5 | 42 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:26:09 | 41 | 14MB | | public.t_a | 0 -Improving Query Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^ + Note the following: + + * The ``Join`` node is the most time-consuming part of this statement, taking 69.7 seconds to join 1.5 billion records. + +Common Solutions for Improving Query Performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. -* - Convert text values on-the-fly before running the query. For example, the :ref:`crc64` function takes a text - input and returns a ``BIGINT`` hash. +In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` works best as a join key. + +.. list-table:: + :widths: auto + :header-rows: 1 - For example: + * - Solution + - Description + * - Mapping + - Use a dimension table to map ``TEXT`` values to ``NUMERIC`` types, and then reconcile these values as needed by joining the dimension table. + * - Converting + - Use functions like :ref:`crc64` to convert ``TEXT`` values into BIGINT hashes directly before running the query. + + For example: - .. code-block:: postgres + .. code-block:: postgres - SELECT AVG(t_b.j::BIGINT), t_a.country_code - FROM "public"."t_a" - JOIN "public"."t_b" ON (CRC64(t_a.fk::TEXT) = CRC64(t_b.id::TEXT)) - GROUP BY t_a.country_code; + SELECT AVG(t_b.j::BIGINT), t_a.country_code + FROM "public"."t_a" + JOIN "public"."t_b" ON (CRC64(t_a.fk::TEXT) = CRC64(t_b.id::TEXT)) + GROUP BY t_a.country_code; - The execution below has been shortened, but note the highlighted rows for ``Join``. - The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. + The execution below has been shortened, but note the highlighted rows for ``Join``. + The ``Join`` node went from taking nearly 70 seconds, to just 6.67 seconds for joining 1.5 billion records. - .. code-block:: postgres - :linenos: - :emphasize-lines: 8 + .. code-block:: postgres + :linenos: + :emphasize-lines: 8 - SELECT show_node_info(6); - stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum - --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- - [...] - 6 | 19 | GpuTransform | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 18 | | | | 1.48 - 6 | 20 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 19 | | | | 0 - 6 | 21 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 20 | | | | 0 - 6 | 22 | Join | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 21 | | | inner | 6.67 - 6 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 22 | | | | 0 - [...] - 6 | 32 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 31 | 235MB | | public.t_b | 0.02 - [...] - 6 | 43 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 42 | | | | 0 - 6 | 44 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 43 | 14MB | | public.t_a | 0 - -* You can map some text values to numeric types by using a dimension table. Then, reconcile the values when you need them by joining the dimension table. + SELECT show_node_info(6); + stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum + --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- + [...] + 6 | 19 | GpuTransform | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 18 | | | | 1.48 + 6 | 20 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 19 | | | | 0 + 6 | 21 | ReorderInput | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 20 | | | | 0 + 6 | 22 | Join | 1497366528 | 85 | 17825792 | 2020-09-08 18:57:04 | 21 | | | inner | 6.67 + 6 | 24 | AddSortedMinMaxMet.. | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 22 | | | | 0 + [...] + 6 | 32 | ReadTable | 6291456 | 1 | 6291456 | 2020-09-08 18:55:12 | 31 | 235MB | | public.t_b | 0.02 + [...] + 6 | 43 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 42 | | | | 0 + 6 | 44 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 43 | 14MB | | public.t_a | 0 + + + + Sorting on big ``TEXT`` fields ------------------------------ -In general, SQreamDB automatically inserts a ``Sort`` node which arranges the data prior to reductions and aggregations. -When running a ``GROUP BY`` on large ``TEXT`` fields, you may see nodes for ``Sort`` and ``Reduce`` taking a long time. +In SQreamDB, a ``Sort`` node is automatically inserted to arrange data before reductions and aggregations. When performing a ``GROUP BY`` on large ``TEXT`` fields, you may notice that ``Sort`` and ``Reduce`` nodes take a significant amount of time to complete. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ From b1694dedae7c632eed348c46517b966dab1bcce0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Apr 2024 14:17:25 +0300 Subject: [PATCH 1282/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 0f96a1800..bb56b5b25 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -847,9 +847,9 @@ For example: i INT NOT NULL, amt DOUBLE NOT NULL, ts DATETIME NOT NULL, - country_code TEXT(100) NOT NULL, - flag TEXT(10) NOT NULL, - string_fk TEXT(50) NOT NULL + country_code TEXT NOT NULL, + flag TEXT NOT NULL, + string_fk TEXTNOT NULL ); We will run a query, and inspect it's execution details: From 5dc5a870550c40956e97065c1c0da68bd91ee438 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:48:38 +0300 Subject: [PATCH 1283/1892] Remove old COPY TO Syntax --- .../utility_commands/get_ddl.rst | 96 ++++++++++--------- .../utility_commands/get_function_ddl.rst | 87 +++++++++-------- .../get_role_database_ddl.rst | 46 ++++----- .../utility_commands/get_view_ddl.rst | 95 +++++++++--------- 4 files changed, 156 insertions(+), 168 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_ddl.rst b/reference/sql/sql_statements/utility_commands/get_ddl.rst index bc3b9ef54..07a25951a 100644 --- a/reference/sql/sql_statements/utility_commands/get_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_ddl.rst @@ -1,36 +1,23 @@ .. _get_ddl: -***************** -GET_DDL -***************** +******* +GET DDL +******* -``GET_DDL(<table name>)`` is a function that shows the :ref:`CREATE TABLE<create_table>` statement for a table. +The ``GET DDL`` function retrieves the Data Definition Language (DDL) statement used to create a table. It may include additional information that was added by SQreamDB (e.g., explicit ``NULL`` constraints). -.. tip:: - * For views, see :ref:`GET_VIEW_DDL<get_view_ddl>`. - * For the entire database, see :ref:`DUMP_DATABASE_DDL<dump_database_ddl>`. - * For UDFs, see :ref:`GET_FUNCTION_DDL<get_function_ddl>`. - -Permissions -============= - -The role must have the ``CONNECT`` permission at the database level. +See also: :ref:`GET_VIEW_DDL<get_view_ddl>`, :ref:`DUMP_DATABASE_DDL<dump_database_ddl>`, :ref:`GET_FUNCTION_DDL<get_function_ddl>` Syntax -========== +====== .. code-block:: postgres - get_ddl_statement ::= - SELECT GET_DDL('[schema_name.]table_name') - ; - - schema_name ::= identifier - - table_name ::= identifier + SELECT + GET_DDL(['<schema_name>'.]'<table_name>') Parameters -============ +========== .. list-table:: :widths: auto @@ -39,39 +26,54 @@ Parameters * - Parameter - Description * - ``schema_name`` - - The name of the schema. + - The name of the schema * - ``table_name`` - - The name of the table. + - The name of the table Examples -=========== +======== -Getting the DDL for a table ------------------------------ -The result of the ``GET_DDL`` function is a verbose version of the :ref:`create_table` syntax, which may include additional information that was added by SQream DB. For example, a ``NULL`` constraint may be specified explicitly. - -.. code-block:: psql +.. code-block:: postgres - farm=> CREATE TABLE cool_animals ( - id INT NOT NULL, - name text(30) NOT NULL, - weight FLOAT, - is_agressive BOOL DEFAULT false NOT NULL - ); - executed - - farm=> SELECT GET_DDL('cool_animals'); - create table "public"."cool_animals" ( - "id" int not null, - "name" text(30) not null, - "weight" double null, - "is_agressive" bool default false not null ) - ; + -- Create a table: + CREATE TABLE + cool_animals ( + id INT NOT NULL, + name TEXT NOT NULL, + weight FLOAT, + is_agressive BOOL DEFAULT false NOT NULL + ); + + -- Get table ddl: + SELECT + GET_DDL('cool_animals'); + + -- Result: + CREATE TABLE + 'public'.'cool_animals' ( + 'id' INT NOT NULL, + 'name' TEXT NOT NULL, + 'weight' DOUBLE NULL, + 'is_agressive' BOOL DEFAULT FALSE NOT NULL + ); Exporting table DDL to a file -------------------------------- +----------------------------- .. code-block:: postgres - COPY (SELECT GET_DDL('cool_animals')) TO '/home/rhendricks/animals.ddl'; + COPY + ( + SELECT + GET_DDL('cool_animals') + ) TO + WRAPPER + csv_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/cool_animals_ddl.csv'); + +Permissions +============= + +The role must have the ``CONNECT`` permission at the database level. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_function_ddl.rst b/reference/sql/sql_statements/utility_commands/get_function_ddl.rst index e456073ae..4327ba33f 100644 --- a/reference/sql/sql_statements/utility_commands/get_function_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_function_ddl.rst @@ -1,31 +1,18 @@ .. _get_function_ddl: ***************** -GET_FUNCTION_DDL +GET FUNCTION DDL ***************** -``GET_FUNCTION_DDL(<function name>)`` is a function that shows the :ref:`CREATE FUNCTION<create_function>` statement for a function. - -.. tip:: - * For tables, see :ref:`GET_DDL<get_ddl>`. - * For views, see :ref:`GET_VIEW_DDL<get_view_ddl>`. - * For the entire database, see :ref:`DUMP_DATABASE_DDL<dump_database_ddl>`. - -Permissions -============= - -The role must have the ``CONNECT`` permission at the database level. +``GET_FUNCTION_DDL`` is a function that shows the :ref:`create_function` statement for a function. Syntax -========== +====== .. code-block:: postgres - get_function_ddl_statement ::= - SELECT GET_FUNCTION_DDL('function_name') - ; - function_name ::= identifier + SELECT GET_FUNCTION_DDL('<function_name>') Parameters ============ @@ -37,46 +24,58 @@ Parameters * - Parameter - Description * - ``function_name`` - - The name of the function. + - The name of the function Examples -=========== - -Getting the DDL for a function ---------------------------------- +======== -The result of the ``GET_FUNCTION_DDL`` function is a verbose version of the CREATE FUNCTION statement, which may include additional information that was added by SQream DB. For example, some type names and identifiers may be quoted or altered. +.. code-block:: postgres -.. code-block:: psql + CREATE OR REPLACE FUNCTION my_distance (x1 float, + y1 float, + x2 float, + y2 float) returns float as + $$ import mathIF y1 < X1:RETURN 0.0 + else: + return math.Sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) + $$ + language python; - master=> CREATE OR REPLACE FUNCTION my_distance (x1 float, y1 float, x2 float, y2 float) RETURNS float as $$ - import math - if y1 < x1: - return 0.0 - else: - return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) - $$ LANGUAGE PYTHON; - executed - master=> SELECT GET_FUNCTION_DDL('my_distance'); - create function "my_distance" (x1 float, + SELECT + GET_FUNCTION_DDL('my_distance'); + + CREATE FUNCTION 'my_distance' (x1 float, y1 float, x2 float, y2 float) returns float as - $$ - import math - if y1 < x1: - return 0.0 - else: - return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) - $$ - language python volatile; + $$ + import math + if y1 < x1: + return 0.0 + else: + return math.sqrt((y2 - y1) ** 2 + (x2 - x1) ** 2) + $$ + language python volatile; Exporting function DDL to a file ------------------------------------- +-------------------------------- .. code-block:: postgres - COPY (SELECT GET_FUNCTION_DDL('my_distance')) TO '/home/rhendricks/my_distance.sql'; + COPY + ( + SELECT + GET_FUNCTION_DDL('my_distance') + ) TO + WRAPPER + csv_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/cool_animals_ddl.csv'); + +Permissions +============= + +The role must have the ``CONNECT`` permission at the database level. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index ed7adfcf5..13dd0d98b 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -1,23 +1,20 @@ .. _get_role_database_ddl: -******************** +********************* GET_ROLE_DATABASE_DDL -******************** -The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a role's database in DDL format. +********************* -The ``GET_ROLE_DATABASE_DDL`` page describes the following: +The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a role's database in DDL format. Syntax -========== -The following is the correct syntax for using the ``GET_ROLE_DATABASE_DDL`` statement: +====== .. code-block:: postgres - select get_role_database_ddl(<'role_name'>) + SELECT GET_ROLE_DATABASE_DDL('<role_name>') Parameters -============ -The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: +========== .. list-table:: :widths: auto @@ -26,33 +23,24 @@ The following table shows the ``GET_ROLE_DATABASE_DDL`` parameters: * - Parameter - Description * - ``role_name`` - - The definition of the database role in DDL format. + - The role for which to get database definition Example -=========== -The following is an example of using the ``GET_ROLE_DATABASE_DDL`` statement: +======= -.. code-block:: psql +.. code-block:: postgres - select get_role_database_ddl('public'); + SELECT GET_ROLE_DATABASE_DDL('public'); - -Output -========== -The following is an example of the output of the ``GET_ROLE_DATABASE_DDL`` statement: +Output: -.. code-block:: postgres +.. code-block:: console - grant create, usage on schema "public" to "public" ; alter default schema for "public" to "public"; alter default permissions for "public" for schemas grant superuser to creator_role ; alter default permissions for "public" for tables grant select, insert, delete, ddl to creator_role ; + Name|Value | + ----+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ddl |grant create, usage on schema 'master'.'public' to 'public' ;alter default schema for 'public' to 'master'.'public';alter default permissions for 'public' for schemas grant superuser to creator_role ;alter default permissions for 'public' for tables grant select, insert, delete, update, ddl to creator_role ;alter default permissions for 'public' for external tables grant select, ddl to creator_role ;alter default permissions for 'public' for views grant select, ddl to creator_role ;| Permissions -============= -Using the ``GET_ROLE_DATABASE_DDL`` statement requires no special permissions. - -For more information, see the following: - -* :ref:`get_role_global_ddl` +=========== - :: - -* :ref:`get_role_permissions` \ No newline at end of file +Using the ``GET_ROLE_DATABASE_DDL`` statement requires no special permissions. diff --git a/reference/sql/sql_statements/utility_commands/get_view_ddl.rst b/reference/sql/sql_statements/utility_commands/get_view_ddl.rst index 5ce56d7af..6ae5d4328 100644 --- a/reference/sql/sql_statements/utility_commands/get_view_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_view_ddl.rst @@ -1,36 +1,20 @@ .. _get_view_ddl: -***************** -GET_VIEW_DDL -***************** +************ +GET VIEW DDL +************ -``GET_VIEW_DDL(<view name>)`` is a function that shows the :ref:`CREATE VIEW<create_view>` statement for a view. - -.. tip:: - * For tables, see :ref:`GET_DDL<get_ddl>`. - * For the entire database, see :ref:`DUMP_DATABASE_DDL<dump_database_ddl>`. - * For UDFs, see :ref:`GET_FUNCTION_DDL<get_function_ddl>`. - -Permissions -============= - -The role must have the ``CONNECT`` permission at the database level. +``GET_VIEW_DDL`` is a function that shows the :ref:`CREATE VIEW<create_view>` statement for a view. Syntax -========== +====== .. code-block:: postgres - get_view_ddl_statement ::= - SELECT GET_VIEW_DDL('[schema_name.]view_name') - ; - - schema_name ::= identifier - - view_name ::= identifier + SELECT GET_VIEW_DDL(['<schema_name>'.]'<view_name>') Parameters -============ +========== .. list-table:: :widths: auto @@ -39,40 +23,55 @@ Parameters * - Parameter - Description * - ``schema_name`` - - The name of the schema. + - The name of the schema * - ``view_name`` - - The name of the view. + - The name of the view Examples -=========== +======== -Getting the DDL for a view ------------------------------ - -The result of the ``GET_VIEW_DDL`` function is a verbose version of the CREATE VIEW statement, which may include additional information that was added by SQream DB. For example, schemas and column names will be be specified explicitly. +.. code-block:: postgres -.. code-block:: psql + CREATE VIEW + angry_animals AS + SELECT + * + FROM + cool_animals + WHERE + is_agressive = false; - farm=> CREATE VIEW angry_animals AS SELECT * FROM cool_animals WHERE is_agressive = false; - executed - farm=> SELECT GET_VIEW_DDL('angry_animals'); - create view "public".angry_animals as - select - "cool_animals"."id" as "id", - "cool_animals"."name" as "name", - "cool_animals"."weight" as "weight", - "cool_animals"."is_agressive" as "is_agressive" - from - "public".cool_animals as cool_animals - where - "cool_animals"."is_agressive" = false; - - + SELECT + GET_VIEW_DDL('angry_animals'); + + CREATE VIEW 'public'.angry_animals AS + SELECT + 'cool_animals'.'id' as 'id', + 'cool_animals'.'name' as 'name', + 'cool_animals'.'weight' as 'weight', + 'cool_animals'.'is_agressive' as 'is_agressive' + FROM + 'public'.cool_animals as cool_animals + WHERE + 'cool_animals'.'is_agressive' = false; Exporting view DDL to a file -------------------------------- +---------------------------- .. code-block:: postgres - COPY (SELECT GET_VIEW_DDL('angry_animals')) TO '/home/rhendricks/angry_animals.sql'; + COPY + ( + SELECT + GET_VIEW_DDL('angry_animals') + ) TO + WRAPPER + csv_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/cool_animals_ddl.csv'); + +Permissions +=========== + +The role must have the ``CONNECT`` permission at the database level. \ No newline at end of file From a116df7535e56e6898925b7262e8ee7eb9b8f439 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 11 Apr 2024 16:11:03 +0300 Subject: [PATCH 1284/1892] Update dump_database_ddl.rst --- .../utility_commands/dump_database_ddl.rst | 101 ++++++++---------- 1 file changed, 46 insertions(+), 55 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst index fc9ca1282..2be276ef7 100644 --- a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst @@ -4,75 +4,66 @@ DUMP_DATABASE_DDL ***************** -``DUMP_DATABASE_DDL()`` is a function that shows the ``CREATE`` statements for database objects including views and tables. Begining with 2020.3.1, DUMP_DATABASE_DDL includes foreign tables in the output. - -.. warning:: - This function does not currently show UDFs. To list available UDFs, use the catalog: - - .. code-block:: psql - - farm=> SELECT * FROM sqream_catalog.user_defined_functions; - farm,1,my_distance - - Then, export UDFs one-by-one using :ref:`GET_FUNCTION_DDL<get_function_ddl>`. - -.. tip:: - * For just tables, see :ref:`GET_DDL<get_ddl>`. - * For just views, see :ref:`GET_VIEW_DDL<get_view_ddl>`. - * For UDFs, see :ref:`GET_FUNCTION_DDL<get_function_ddl>`. - -Permissions -============= - -The role must have the ``CONNECT`` permission at the database level. +``DUMP_DATABASE_DDL()`` is a function that shows the ``CREATE`` statements for database objects including views and tables. Syntax -========== +====== .. code-block:: postgres - dump_database_ddl_statement ::= - SELECT DUMP_DATABASE_DDL() - ; + SELECT DUMP_DATABASE_DDL() -Parameters -============ +Examples +======== -This function accepts no parameters. +.. code-block:: postgres -Examples -=========== + SELECT + DUMP_DATABASE_DDL(); -Getting the DDL for a database ---------------------------------- +Exporting database DDL to a file +-------------------------------- -.. code-block:: psql +.. code-block:: postgres - farm=> SELECT DUMP_DATABASE_DDL(); - create table "public"."cool_animals" ( - "id" int not null, - "name" text(30) not null, - "weight" double null, - "is_agressive" bool default false not null - ) - ; + COPY + ( + SELECT + DUMP_DATABASE_DDL() + ) TO + WRAPPER + csv_fdw + OPTIONS + (LOCATION = 's3://sqream-docs/database.ddl'); + +Showing the ``CREATE`` Statements for UDFs +------------------------------------------ + +``DUMP_DATABASE_DDL`` does not show UDFs. + +To list available UDFs: + +#. Retrieve UDFs from catalog: + + .. code-block:: postgres - create view "public".angry_animals as - select - "cool_animals"."id" as "id", - "cool_animals"."name" as "name", - "cool_animals"."weight" as "weight", - "cool_animals"."is_agressive" as "is_agressive" - from - "public".cool_animals as cool_animals - where - "cool_animals"."is_agressive" = false; + SELECT + * + FROM + sqream_catalog.user_defined_functions; + Output: + .. code-block:: console -Exporting database DDL to a file ------------------------------------- + database_name|function_id|function_name| + -------------+-----------+-------------+ + master | 0|add_months | + master | 2|my_distance | + +#. Export UDFs one-by-one using :ref:`GET_FUNCTION_DDL<get_function_ddl>`. -.. code-block:: postgres +Permissions +=========== - COPY (SELECT DUMP_DATABASE_DDL()) TO '/home/rhendricks/database.ddl'; +The role must have the ``CONNECT`` permission at the database level. \ No newline at end of file From b1033543717077a7b6a6074c119d613954390135 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Sun, 14 Apr 2024 17:01:31 +0300 Subject: [PATCH 1285/1892] Update access_control_permissions.rst --- .../access_control_permissions.rst | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index e172ce27f..7272cd8d2 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -69,6 +69,12 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``ALL`` | All function permissions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| **Column** | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``SELECT`` | Select from catalog | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``DDL`` | Column DDL operations | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **View** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from view | @@ -183,6 +189,22 @@ GRANT ON FUNCTION <function_name> TO <role> + -- Grant permissions at the column level: + GRANT + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS] + } + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] + | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + } + TO <role> [, ...] + -- Grant permissions on the view level GRANT { {SELECT @@ -288,6 +310,20 @@ REVOKE ON FUNCTION <function_name> FROM <role> + -- Revoke permissions at the column level: + REVOKE + { + { SELECT + | DDL } [, ...] + | ALL [PERMISSIONS]} + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] + | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] + | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] + } + FROM <role> [, ...] + -- Revoke permissions on the view level REVOKE { {SELECT @@ -343,7 +379,8 @@ schema statement is run. SCHEMAS | TABLES | FOREIGN TABLES - | VIEWS + | VIEWS + | COLUMNS | CATALOGS | SERVICES | SAVED_QUERIES @@ -405,6 +442,12 @@ Grant execute function permission to a role: GRANT EXECUTE ON FUNCTION function_name TO role_name; +Grant column-level permissions to a role: + +.. code-block:: postgres + + GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; + Grant usage permissions on a service to a role: .. code-block:: postgres @@ -451,6 +494,12 @@ Revoke permissions on specific objects (table, view, foreign table, or catalog) REVOKE SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE schema_name.table_name FROM role_name; +Revoke column-level permissions from a role: + +.. code-block:: postgres + + REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE schema_name.table_name FROM role_name; + Revoke usage permissions on a service from a role: .. code-block:: postgres From f4c0fe96fe1b908167a1bfbb4c4344bc17a0cc8c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Apr 2024 08:25:12 +0300 Subject: [PATCH 1286/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 75767ef26..b74ae2e76 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -1,8 +1,8 @@ .. _recommended_pre-installation_configurations: -********************************************* +****************************** Pre-Installation Configuration -********************************************* +****************************** Before installing SQreamDB, it is recommended that you to tune your system for better performance and stability. @@ -11,7 +11,7 @@ Before installing SQreamDB, it is recommended that you to tune your system for b :depth: 1 Recommended Basic Input/Output System Settings -=============================================== +============================================== The first step when setting your pre-installation configurations is to use the recommended basic input/output system (BIOS) settings. @@ -809,7 +809,7 @@ Installing the CUDA Driver :local: :depth: 1 -The current recommendation is for CUDA 12.2.1. +The current recommendation is for CUDA 12.3.2. For A100 GPU and other A series GPUs, you must install CUDA driver **11.4.3** or a later version. From aa480a24cfc401d55861955fc74a2dc02c356ff3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Apr 2024 09:38:32 +0300 Subject: [PATCH 1287/1892] Update monitoring_query_performance.rst --- operational_guides/monitoring_query_performance.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index bb56b5b25..662b960db 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -785,7 +785,7 @@ In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` - Description * - Mapping - Use a dimension table to map ``TEXT`` values to ``NUMERIC`` types, and then reconcile these values as needed by joining the dimension table. - * - Converting + * - Conversion - Use functions like :ref:`crc64` to convert ``TEXT`` values into BIGINT hashes directly before running the query. For example: From 1071294f3c4beb805ec87230ca6c12bcdfe9d48c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:33:52 +0300 Subject: [PATCH 1288/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 112 +++++++++--------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 662b960db..336913475 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -147,7 +147,7 @@ Understanding the Query Execution Plan Output Both :ref:`show_node_info` and the logged execution plans represents the query plan as a graph hierarchy, with data separated into different columns. Each row represents a single logical database operation, which is also called a **node** or **chunk producer**. A node reports several metrics during query execution, such as how much data it has read and written, how many chunks and rows, and how much time has elapsed. -Consider the example show_node_info presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 +Consider the example SHOW_NODE_INFO presented above. The source node with ID #11 (``ReadTable``), has a parent node ID #10 (``CpuDecompress``). If we were to draw this out in a graph, it'd look like this: .. figure:: /_static/images/show_node_info_graph.png @@ -369,7 +369,7 @@ Identifying the Offending Nodes o_year; #. - Use a foreign table or ``show_node_info`` to view the execution information. + Use a foreign table or ``SHOW_NODE_INFO`` to view the execution information. This statement is made up of 199 nodes, starting from a ``ReadTable``, and finishes by returning only 2 results to the client. @@ -477,7 +477,7 @@ Identifying the Offending Nodes AND high_selectivity(p_type = 'ECONOMY BURNISHED NICKEL'); #. - Use a foreign table or ``show_node_info`` to view the execution information. + Use a foreign table or ``SHOW_NODE_INFO`` to view the execution information. This statement is made up of 221 nodes, containing 8 ``ReadTable`` nodes, and finishes by returning billions of results to the client. @@ -486,7 +486,7 @@ Identifying the Offending Nodes .. code-block:: postgres :emphasize-lines: 7,9,11 - SELECT show_node_info(494); + SELECT SHOW_NODE_INFO(494); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+---------+-------+-----------------+-------- 494 | 1 | PushToNetworkQueue | 242615 | 1 | 242615 | 2020-09-04 19:07:55 | -1 | | | | 0.36 @@ -582,7 +582,7 @@ Filtering is considered inefficient when the ``Filter`` node processes less than o_year; #. - Use a foreign table or ``show_node_info`` to view the execution information. + Use a foreign table or ``SHOW_NODE_INFO`` to view the execution information. The execution below has been shortened, but note the highlighted rows for ``ReadTable`` and ``Filter``: @@ -590,7 +590,7 @@ Filtering is considered inefficient when the ``Filter`` node processes less than :linenos: :emphasize-lines: 9,17,19,27 - SELECT show_node_info(559); + SELECT SHOW_NODE_INFO(559); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+--------+-------+-----------------+-------- 559 | 1 | PushToNetworkQueue | 2 | 1 | 2 | 2020-09-07 11:12:01 | -1 | | | | 0.28 @@ -659,7 +659,7 @@ Filtering is considered inefficient when the ``Filter`` node processes less than :linenos: :emphasize-lines: 5,13 - SELECT show_node_info(586); + SELECT SHOW_NODE_INFO(586); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+-----------+--------+-------------------+---------------------+----------------+--------+-------+-----------------+-------- [...] @@ -744,7 +744,7 @@ Consider these two table structures: #. - Use a foreign table or ``show_node_info`` to view the execution information. + Use a foreign table or ``SHOW_NODE_INFO`` to view the execution information. The execution below has been shortened, but note the highlighted rows for ``Join``. @@ -752,7 +752,7 @@ Consider these two table structures: :linenos: :emphasize-lines: 8 - SELECT show_node_info(5); + SELECT SHOW_NODE_INFO(5); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -804,7 +804,7 @@ In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` :linenos: :emphasize-lines: 8 - SELECT show_node_info(6); + SELECT SHOW_NODE_INFO(6); stmt_id | node_id | node_type | rows | chunks | avg_rows_in_chunk | time | parent_node_id | read | write | comment | timeSum --------+---------+----------------------+------------+--------+-------------------+---------------------+----------------+-------+-------+------------+-------- [...] @@ -819,27 +819,19 @@ In general, try to avoid ``TEXT`` as a join key. As a rule of thumb, ``BIGINT`` 6 | 43 | CpuDecompress | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 42 | | | | 0 6 | 44 | ReadTable | 10000000 | 2 | 5000000 | 2020-09-08 18:55:13 | 43 | 14MB | | public.t_a | 0 - - - - -Sorting on big ``TEXT`` fields +Sorting on Big ``TEXT`` Fields ------------------------------ -In SQreamDB, a ``Sort`` node is automatically inserted to arrange data before reductions and aggregations. When performing a ``GROUP BY`` on large ``TEXT`` fields, you may notice that ``Sort`` and ``Reduce`` nodes take a significant amount of time to complete. +In SQreamDB, a ``Sort`` node is automatically added to organize data prior to reductions and aggregations. When executing a ``GROUP BY`` operation on extensive ``TEXT`` fields, you might observe that the ``Sort`` and subsequent ``Reduce`` nodes require a considerable amount of time to finish. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -When running a statement, inspect it with :ref:`show_node_info`. If you see ``Sort`` and ``Reduce`` among +If you see ``Sort`` and ``Reduce`` among your top five longest running nodes, there is a potential issue. -For example: -#. - Run a query to test it out. - - - Our ``t_inefficient`` table contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: - + +Consider this ``t_inefficient`` table which contains 60,000,000 rows, and the structure is simple, but with an oversized ``country_code`` column: + .. code-block:: postgres :emphasize-lines: 5 @@ -851,8 +843,9 @@ For example: flag TEXT NOT NULL, string_fk TEXTNOT NULL ); - - We will run a query, and inspect it's execution details: + +#. + Run a query. .. code-block:: postgres @@ -870,6 +863,8 @@ For example: TUR | 1195946178 [...] +#. + Use a foreign table or ``SHOW_NODE_INFO`` to view the execution information. .. code-block:: postgres :emphasize-lines: 8,9 @@ -890,7 +885,7 @@ For example: 30 | 11 | CpuDecompress | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 10 | | | | 0 30 | 12 | ReadTable | 60000000 | 15 | 4000000 | 2020-09-10 16:17:10 | 11 | 520MB | | public.t_inefficient | 0.05 -#. We can look to see if there's any shrinking we can do on the ``GROUP BY`` key +#. Look to see if there's any shrinking that can be done on the ``GROUP BY`` key: .. code-block:: postgres @@ -900,40 +895,51 @@ For example: 3 With a maximum string length of just 3 characters, our ``TEXT(100)`` is way oversized. #. - We can recreate the table with a more restrictive ``TEXT(3)``, and can examine the difference in performance: + Recreate the table with a more restrictive ``TEXT(3)``, and examine the difference in performance: .. code-block:: postgres - CREATE TABLE t_efficient - AS SELECT i, - amt, - ts, - country_code::TEXT(3) AS country_code, - flag - FROM t_inefficient; - - SELECT - country_code, - SUM(amt::bigint) - FROM t_efficient - GROUP BY country_code; + CREATE TABLE + t_efficient AS + SELECT + i, + amt, + ts, + country_code :: TEXT(3) AS country_code, + flag + FROM + t_inefficient; + + SELECT + country_code, + SUM(amt :: bigint) + FROM + t_efficient + GROUP BY + country_code; - country_code | sum - -------------+----------- - VUT | 1195416012 - GIB | 1195710372 - TUR | 1195946178 - [...] + country_code | sum + -------------+----------- + VUT | 1195416012 + GIB | 1195710372 + TUR | 1195946178 + [...] - This time, the entire query took just 4.75 seconds, or just about 91% faster. + This time, the query should be about 91% faster. -Improving Sort Performance on Text Keys -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Common Solutions for Improving Sort Performance on ``TEXT`` Keys +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -When using TEXT, ensure that the maximum length defined in the table structure is as small as necessary. -For example, if you're storing phone numbers, don't define the field as ``TEXT(255)``, as that affects sort performance. +.. list-table:: + :widths: auto + :header-rows: 1 -You can run a query to get the maximum column length (e.g. ``MAX(LEN(a_column))``), and potentially modify the table structure. + * - Solution + - Description + * - Using Appropriate Text Length + - Define the maximum length of ``TEXT`` fields in your table structure as small as necessary. For example, if you're storing phone numbers, avoid defining the field as ``TEXT(255)`` to optimize sort performance. + * - Optimize Column Length + - Execute a query to determine the maximum length of data in the column (e.g., ``MAX(LEN(a_column))``) and consider modifying the table structure based on this analysis. .. _high_selectivity_data_opt: From 08bb45ba48a01efbaa75d762b30691c960ff744c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:48:02 +0300 Subject: [PATCH 1289/1892] favicon --- _static/images/favicon-dark.png | Bin 0 -> 11518 bytes _static/images/favicon-light.png | Bin 0 -> 12378 bytes conf.py | 6 ++++++ 3 files changed, 6 insertions(+) create mode 100644 _static/images/favicon-dark.png create mode 100644 _static/images/favicon-light.png diff --git a/_static/images/favicon-dark.png b/_static/images/favicon-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..241e68580a35b3e3d890fa5713220fa82ffd7b6e GIT binary patch literal 11518 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 QylV!?%P31%Ng4<JAE`g3V*mgE literal 0 HcmV?d00001 diff --git a/_static/images/favicon-light.png b/_static/images/favicon-light.png new file mode 100644 index 0000000000000000000000000000000000000000..dc73ebff4fd9fe63d1bffea73e7209acf047d80a GIT binary patch literal 12378 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%0D@@ zq1(|7`1|_OM=0T+vnSdwSI>Cj#z21c=(w<)C^szrG;B&T2DIDn=$?}LFbC0q3}McO zdGq5@$Q-FB;}F(=0q&a|-kJE&w8axWbrcxZWeODZI||53r{>B?1#9m`%uqP|5@SXR zSK!uQl@VDD2BuiP#7*?+!345qH9I?x@ba;WCkE#ZIJXAp&7mc<Zc|SJnh^rAeg6LP z5?gi5e%4YM5HHfX+8v@+9ww*1aqC73!%6xg)aN53%|?{D%>1{*U;1P4g)$_t&2+SW z(^CCJ_Y?wVfAcG!iPlSicg`Djjrg<9&?bdp<S&b%b!w0i?HB0rn;;-q4_bQ%$;rl_ z^vgJ*yuobQMCV8{?zyCn3j!YIXPrC4vI8VEt1?t=#O$#=oeu5ua43zzbz9^4kv-Z! zuE#wPke89I>w&=~^)%mP*lwh*DH+L^RLB}}_|imM+?!S~Is`i+$l%JDq=mBcp|f+2 z9uDvM3FK5t_#>eR>u~Q)#z^cXYrQ~cPEDhhEG}Ug8u)3c`pO|I#+kn{_xH0-OuvJd zPS8f@9^Nk35rst&d}%pgIupT8jz=~<+`wSA14<ckdwoadV~@C+c4shYmf|+3J5P{> z2+LS%tah6m4n96yAM9{|h}TTq7drfEIgWFF!d}=A$2N93a#B8_SNxtCOA6wE8-`xV zcPf$0dbxX)L$?xU;QA(<U^MsDWI89$z!zbm6uxDQ3!AinNKc1h>?y*zv^x5YY5d^5 zeEJ^;O(D&j7!_d0<Y%>d+2Jpr=*(;$%%nqoey1DlE|P&A>B<sNV2^>klMsj)GJV40 z&a;m4dpDmYrf9$@As{M}o!5$MICyoC{MofJP2eliq}gBZ#3Drp*oEm`)7fIq3;ZXk z&s}F^HlW&5q%u@*TD6Kc+u#*aOtG3QvafI!?vZQxH|o+dUVbi5ry@dWq!6%vL?^d{ zFAoqKS*r;x@GM|M>gk%(blo)?P~D$ny4TSSYz3^BH>TeaZ41su@;c?4$dbh-&Dv5M zm0Z`Mjfr5iN6uV$&$C^FN1t6T={Gx*ap3E-k!#&FIllzNq^65%ra%q|oWv_rbN7_j z`V*GTRQmI9PbrdJEEA-;2z@szW0VfD?gj1Z`^%=A+&i9lLC+gi40Pk3QODG(yWx+r zK~BQGWp8A>65JC@j<*ZTdZWJ<48RK}al|B!t0Dh8emS)h=wY=)9*5Ro>M2r0Wc~iR z^@k~<na}HFZLF?F9i69*qGQ3flZ@=&h?iRdG;xB*)0zZP`K6%nKd2`5k%52X5IEG| zWvZ7WT~=qwcL`~6jfhrZY+XS{1h+Fi!uZ~z0i^kNyqW40Q+>#s-n<o{uO<eBMh~lj z;Ch;U!qdO#)wKX}0&r~h{?@`tmY83ZPi6t&k-Ce<ZKze1@!Mc(Z{3wS<$tFC_$F=Y z(~yOBV*@dH%*^6yA{BI!$zpFG+;g{vSsAHlptspko0nvbjY={@rU8}{UTf6iImZCY zdJ*fE0u<_OfnDpD9npcCpxp}-;1@PuTx_LeM*gn3Bv5eJ&a%hV*Xf+xCXsx~)t5~- zJnxS?OtTabcZ9>ec?%5zI29IZt{UuK#vna9k5$*-W(&Q2gg=SNL0}6rB@W;R?Rf{m zG|gdzOF%|4TT@fT<j6);1S29EPHLU6cZeYg+sF;<8i3=yId0(iL4GXAS0ou=O4rPn z7!BbtW!w(%1BxjE&X~rkKfku3logq0r5ml%)meHyDmvCZ?A)2Cp>G49L-g_&3dUQ| z$y9UvwRMz#rNS|>|Kh-IlK@2zY9xC8u?_3el&(hf0W9md%(%M4o0d%8ZcP-`l7?_A zRH6c|nEZ%uHLL<cprZ<%<N2o)#W>Hpj43ff%>O5A*k}x5efQgE9TGW6k%Tu`fJIOH zQXLsN-AVucVh{OGV*Ho6N~v(*^Q=*1H&Y%m5_4}>)jZ<y#CHlpc`v4MZnPIYv+gYO zqQnC@eozFg)t{Bq<$v-k&1oeeItBwp#wW=~9cdH#Tyh9rWe;kWpkj`f?}tnb<KkhM zo1}hy*@#}$E5Ht=G3`Oyr+p%ru>X@2EYdHrHxoB>%;<Iv`p;~DrP8-_oJY%aSjKLx z04M5j#8-x@^mNp)*>H&TPC)~N0^+MbSBS~r$g_2`1?gFf)_dRetp_@e0W`&O{HRx3 zCBG2wv*6=Nw}(?=OFmkL9kv8pRG`xd^94x;0hW9-wJw&OKgo8kF*9OIUYEOD^wUW1 z6n;IR+X}yawK%{nr&#qpup7Kd2DfI&`ngP<HZ$Yvul^H$Zs`$GQ2T;HQ|WY@y}{?C z=ilQWe9b6s9Po0s61HeVb6<>uG$^*3;V&`T|HPK<GU%Y^0z%H2BFZP&sM0S_`?xm; zk*)A;B=K;;%b~I|Axt|a5y|~)fw>_g@gu>jRzHb2B!3+lCSU}e8UnfIW_ODF<^Oy& zRAh?#(DI|D0)<cnff+Io`w2k=)RWX04iRo+B%kw|)SPmbDEcgd(=xRcJ3`2BO+wTN zD4AazJSHFAbGKO(7v-=8U8<UV!1A=`xpzPAlrV-LT>yj7t(me+%vu70Eu63ED$LPy z3lpI=yy{)1&-bC=pLFiguc8olnP-j2;UKjZ!eI669oa^>nuzKiVwG$?9X8G%EXyf~ odC1JvOs}4N+(_&gAD>|JsS>RUX^t&l{|o>mMdd^)h4lUZ4|#jtR{#J2 literal 0 HcmV?d00001 diff --git a/conf.py b/conf.py index 99cd8288e..122608702 100644 --- a/conf.py +++ b/conf.py @@ -38,6 +38,7 @@ extensions = [ 'sphinx_rtd_theme' ,'notfound.extension' # 404 handling + ,"sphinx_favicon" ] # Mark 'index' as the main page @@ -58,12 +59,17 @@ # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' +html_favicon = "_static/images/favicon-light.png" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +favicons = [ + "_static/images/favicon-light.png" +] + html_css_files = [ 'css/custom.css', # Relative to the _static path From d7f316fb3fbcfe0fb66ab64261f90142bccea528 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:05:51 +0300 Subject: [PATCH 1290/1892] Update monitoring_query_performance.rst --- .../monitoring_query_performance.rst | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 336913475..820a4b3c3 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -946,19 +946,17 @@ Common Solutions for Improving Sort Performance on ``TEXT`` Keys High Selectivity Data --------------------- -Selectivity is the ratio of cardinality to the number of records of a chunk. We define selectivity as :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` -SQreamDB has a hint called ``HIGH_SELECTIVITY``, which is a function you can wrap a condition in. -The hint signals to SQreamDB that the result of the condition will be very sparse, and that it should attempt to rechunk -the results into fewer, fuller chunks. +In SQreamDB, selectivity refers to the ratio of distinct values to the total number of records within a chunk. It is defined by the formula: :math:`\frac{\text{Distinct values}}{\text{Total number of records in a chunk}}` + +SQreamDB provides a hint called ``HIGH_SELECTIVITY`` that can be used to optimize queries. When you wrap a condition with this hint, it signals to SQreamDB that the result of the condition will yield a sparse output. As a result, SQreamDB attempts to rechunk the results into fewer, fuller chunks for improved performance. + .. note:: - SQreamDB doesn't do this automatically because it adds a significant overhead on naturally ordered and - well-clustered data, which is the more common scenario. + SQreamDB does not apply this optimization automatically because it introduces significant overhead for naturally ordered and well-clustered data, which is the more common scenario. Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -This is easily identifiable - when the amount of average of rows in a chunk is small, following a ``Filter`` operation. -Consider this execution plan: +This condition is easily identifiable when the average number of rows in a chunk is small, particularly after a Filter operation. Consider the following execution plan: .. code-block:: postgres @@ -969,18 +967,27 @@ Consider this execution plan: 30 | 38 | Filter | 18160 | 74 | 245 | 2020-09-10 12:17:09 | 37 | | | | 0.012 [...] 30 | 44 | ReadTable | 77000000 | 74 | 1040540 | 2020-09-10 12:17:09 | 43 | 277MB | | public.dim | 0.058 -The table was read entirely - 77 million rows into 74 chunks. -The filter node reduced the output to just 18,160 relevant rows, but they're distributed across the original 74 chunks. -All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. -Improving Performance with High Selectivity Hints -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* - Use when there's a ``WHERE`` condition on an :ref:`unclustered column<cluster_by>`, and when you expect the filter - to cut out more than 60% of the result set. -* Use when the data is uniformly distributed or random +The table was initially read entirely, containing 77 million rows divided into 74 chunks. After applying a filter node, the output was reduced to just 18,160 relevant rows, which are still distributed across the original 74 chunks. However, all these rows could fit into a single chunk instead of spanning across 74 sparsely populated chunks. + +Common Solutions for Improving Performance with High Selectivity Hints +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Solution + - Description + * - Using ``HIGH_SELECTIVITY`` hint + - + * When a ``WHERE`` condition is used on an :ref:`unclustered column<cluster_by>`, especially if you anticipate the filter to reduce more than 60% of the result set + + * When the data is uniformly distributed or random + + -Performance of unsorted data in joins +Performance of Unsorted Data in Joins ------------------------------------- When data is not well-clustered or naturally ordered, a join operation can take a long time. From dcca01b4c68017eab7a5729730b0a4d86196c997 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 Apr 2024 10:12:58 +0300 Subject: [PATCH 1291/1892] Update keywords_and_identifiers.rst --- .../sql_syntax/keywords_and_identifiers.rst | 76 ++++++++++++++++++- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index aa27daf51..002ddf173 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -30,7 +30,7 @@ Examples Creating quoted and unquoted identifiers: -.. code-block:: sql +.. code-block:: postgres CREATE ROLE "developer"; --quoted identifiers preserves case - will create "developer" CREATE ROLE "Developer"; --quoted identifiers preserves case - will create "Developer" @@ -38,7 +38,7 @@ Creating quoted and unquoted identifiers: Valid and invalid use of identifiers: -.. code-block:: sql +.. code-block:: postgres -- these are all valid examples when quoted: @@ -69,8 +69,78 @@ Identifiers are different than **keywords**, which are predefined words reserved SQreamDB reserved keywords: +.. glossary:: + + A + ``ABORT``, ``ADD``, ``ALL``, ``ALTER``, ``ANALYSE``, ``ANALYZE``, ``AND``, ``ANY``, ``ARRAY``, ``AS``, ``ASC``, ``AUDITLOG``, ``AUTHORIZATION`` + + B + ``BACKUP``, ``BEGIN``, ``BETWEEN``, ``BIGINT``, ``BINARY``<, ``BOTH``, ``BREAK``, ``BROWSE``, ``BULK``, ``BY`` + + C + ``CASE``, ``CAST``, ``CASCADE``, ``CHECK``, ``CHECKPOINT``, ``CLOSE``, ``CLUSTERED``, ``COLLATE``, ``COLUMN``, ``COMMENT``<, ``COMPUTE``, ``CONCURRENTLY``, ``CONSTRAINT``, ``CONTAINSTABLE``, ``CONTINUE``, ``CONVERT``, ``CREATE``, ``CROSS``, ``CURRENT``, ``CURRENT_CATALOG``, ``CURRENT_ROLE``, ``CURRENT_TIME``, ``CURRENT_USER``, ``CURSOR`` + + D + ``DATABASE``, ``DBCC``, ``DEALLOCATE``, ``DECLARE``, ``DEFAULT``, ``DEFERRABLE``, ``DELETE``, ``DENY``, ``DESC``, ``DISTINCT``, ``DISTRIBUTED``, ``DO``<, ``DROP``, ``DUMP`` + + E + ``ELSE``, ``END``, ``ERRLVL``, ``ESCAPE``, ``EXEC``, ``EXECUTE``, ``EXCEPT``, ``EXISTS``, ``EXIT``, ``EXTERNAL`` + + F + ``FALSE``, ``FETCH``, ``FILLFACTOR``, ``FILE``, ``FOR``, ``FOREIGN``, ``FREEZE``, ``FREETEXT``, ``FREETEXTTABLE``, ``FROM``, ``FULL``, ``FUNCTION`` + + G + ``GOTO``, ``GRANT``, ``GROUP``, ``HASH``, ``HAVING``, ``HOLDLOCK`` + + H + ``HASH``, ``HAVING``, ``HOLDLOCK`` + + I + ``IDENTITY``, ``IDENTITYCOL``, ``IDENTITY_INSERT``, ``IF``, ``ILIKE``, ``IN``, ``INITIALLY``, ``INNER``, ``INDEX``, ``INSERT``, ``IS``, ``ISCASTABLE``, ``ISNULL``< + + J + ``JOIN`` + + K + ``KEY``, ``KILL`` + + L + ``LEFT``, ``LEADING``, ``LIKE``, ``LIMIT``, ``LINENO``, ``LOAD``, ``LOCALTIME``, ``LOCALTIMESTAMP``, ``LOOP`` + + M + ``MERGE`` + + N + ``NATIONAL``, ``NATURAL``, ``NOCHECK``, ``NONCLUSTERED``, ``NOT``, ``NOTNULL``<, ``NULL``, ``NULLIF`` + + O + ``OFF``, ``OFFSET``, ``OFFSETS``, ``OF``, ``ON``, ``ONLY``, ``OPEN``, ``OPENDATASOURCE``, ``OPENQUERY``, ``OPENROWSET``, ``OPENXML``, ``OPTION``, ``OR``, ``ORDER``, ``OUTER``, ``OVER``, ``OVERLAPS`` + + P + ``PERCENT``, ``PLACING``, ``PLAIN``, ``PLAINS``, ``PLAINTEXT``, ``PLB``, ``PLI``, ``PLM``, ``PLP``, ``PLSQL``, ``PRECISION``<<, ``PRIMARY``, ``PRINT``, ``PROC``, ``PROCEDURE``, ``PUBLICATION``, ``PUBLISH``, ``PUBLICIZE`` + + R + ``RAISEERROR``, ``READ``, ``READTEXT``, ``REFERENCES``, ``RECONFIGURE``, ``REPLICATION``, ``RESTORE``, ``RESTRICT``, ``RETURN``, ``RETURNING``, ``REVERT``, ``REVOKE``, ``RIGHT``, ``RLIKE``, ``ROLLBACK``, ``ROWCOUNT``, ``ROWGUIDCOL``, ``RULE`` + + S + ``SAVE``, ``SCHEMA``, ``SECURITYAUDIT``, ``SELECT``, ``SESSION_USER``, ``SET``, ``SETUSER``, ``SHUTDOWN``, ``SIMILAR``, ``SOME``, ``STATISTICS``, ``SYMMETRIC`` + + T + ``TABLE``, ``TABLESAMPLE``, ``TEXTSIZE``, ``THEN``, ``TO``, ``TOP``, ``TRANSACTION``, ``TRAN``, ``TRIGGER``, ``TRUNCATE``, ``TRUE`` + + U + ``UNION``, ``UNIQUE``, ``UNPIVOT``, ``UPDATE``, ``UPDATETEXT``, ``USE``, ``USER``, ``USING`` + + V + ``VARIADIC``, ``VERBOSE``, ``VIEW``, ``VALUES``, ``VARYING`` + + W + ``WAITFOR``, ``WHEN``, ``WHERE``, ``WHILE``, ``WINDOW``, ``WITH``, ``WRITETEXT`` + + + + -``ALL`` | ``ANALYSE`` | ``ANALYZE`` | ``AND`` | ``ANY`` | ``ARRAY`` | ``AS`` | ``ASC`` | ``AUTHORIZATION`` | ``BINARY`` | ``BIGINT`` | ``BOTH`` | ``CASE`` | ``CAST`` | ``CHECK`` | ``COLLATE`` | ``COLUMN`` | ``COMMENT`` | ``CONCURRENTLY`` | ``CONSTRAINT`` | ``CREATE`` | ``CROSS`` | ``CURRENT_CATALOG`` | ``CURRENT_ROLE`` | ``CURRENT_TIME`` | ``CURRENT_USER`` | ``DEFAULT`` | ``DEFERRABLE`` | ``DESC`` | ``DISTINCT`` | ``DO`` | ``ELSE`` | ``END`` | ``EXCEPT`` | ``FALSE`` | ``FETCH`` | ``FOR`` | ``FREEZE`` | ``FROM`` | ``FULL`` | ``FUNCTION`` | ``GRANT`` | ``GROUP`` | ``HASH`` | ``HAVING`` | ``ILIKE`` | ``IN`` | ``INITIALLY`` | ``INNER`` | ``INTERSECT`` | ``INTO`` | ``IS`` | ``ISNULL`` | ``JOIN`` | ``KEY`` | ``LEADING`` | ``LEFT`` | ``LIKE`` | ``LIMIT`` | ``LOCALTIME`` | ``LOCALTIMESTAMP`` | ``LOOP`` | ``MERGE`` | ``NATURAL`` | ``NOT`` | ``NOTNULL`` | ``NULL`` | ``OFF`` | ``OFFSET`` | ``OFFSETS`` | ``ON`` | ``ONLY`` | ``OPTION`` | ``OR`` | ``ORDER`` | ``OUTER`` | ``OVER`` | ``OVERLAPS`` | ``PERCENT`` | ``PLACING`` | ``PRIMARY`` | ``PRECISION`` | ``PROC`` | ``PROCEDURE`` | ``REFERENCES`` | ``RETURNING`` | ``RIGHT`` | ``RLIKE`` | ``RULE`` | ``SCHEMA`` | ``SELECT`` | ``SESSION_USER`` | ``SET`` | ``SIMILAR`` | ``SOME`` | ``STATISTICS`` | ``SYMMETRIC`` | ``TABLE`` | ``THEN`` | ``TO`` | ``TOP`` | ``TRAILING`` | ``TRAN`` | ``TRUE`` | ``UNION`` | ``UNIQUE`` | ``USER`` | ``USING`` | ``VARIADIC`` | ``VERBOSE`` | ``WHEN`` | ``WHERE`` | ``WINDOW`` | ``WITH`` | From 6c2467e4d2bddc7fbc0d9df041a4e1e09d76793a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 Apr 2024 14:07:23 +0300 Subject: [PATCH 1292/1892] Update select_data_read_metrics.rst --- .../utility_commands/select_data_read_metrics.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst index e2fb55acb..3d55b88cb 100644 --- a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst @@ -59,7 +59,7 @@ Daily data reads are cumulative. For a comprehensive view of your data read usag .. code-block:: postgres - SELECT data_read_metrics('daily','2023-05-01', '2023-05-05); + SELECT data_read_metrics('daily','2023-05-01', '2023-05-05'); Output: @@ -78,7 +78,7 @@ Monthly data reads: .. code-block:: postgres - SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05); + SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05'); Output: From 86357aa1c916b01adf57f122b1fc706ac7eba66a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 16 Apr 2024 16:02:59 +0300 Subject: [PATCH 1293/1892] Maintenance --- .../monitoring_query_performance.rst | 36 +++++++------------ .../sql_syntax/keywords_and_identifiers.rst | 20 ++++++----- 2 files changed, 25 insertions(+), 31 deletions(-) diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 820a4b3c3..d80453e78 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -956,7 +956,9 @@ SQreamDB provides a hint called ``HIGH_SELECTIVITY`` that can be used to optimiz Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -This condition is easily identifiable when the average number of rows in a chunk is small, particularly after a Filter operation. Consider the following execution plan: +This condition is easily identifiable when the average number of rows in a chunk is small, particularly after a Filter operation. + +Consider the following execution plan: .. code-block:: postgres @@ -995,9 +997,7 @@ When data is not well-clustered or naturally ordered, a join operation can take Identifying the Situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -When running a statement, inspect it with :ref:`show_node_info`. If you see ``Join`` and ``DeferredGather`` among your -top five longest running nodes, there is a potential issue. -In this case, we're also interested in the number of chunks produced by these nodes. +If you identify ``Join`` and ``DeferredGather`` as two of the top five longest running nodes, this could indicate a potential issue. Additionally, it's important to consider the number of chunks generated by these nodes in such cases. Consider this execution plan: @@ -1020,20 +1020,16 @@ Consider this execution plan: [...] 30 | 44 | ReadTable | 77000000 | 74 | 1040540 | 2020-09-10 12:17:09 | 43 | 277MB | | public.dim | 0.058 -* ``Join`` is the node that matches rows from both table relations. -* ``DeferredGather`` gathers the required column chunks to decompress -Pay special attention to the volume of data removed by the ``Filter`` node. -The table was read entirely - 77 million rows into 74 chunks. -The filter node reduced the output to just 18,160 relevant rows, but they're distributed across the original 74 chunks. -All of these rows could fit in one single chunk, instead of spanning 74 rather sparse chunks. +The ``Join`` node performs row matching between table relations, while ``DeferredGather`` is responsible for gathering necessary column chunks for decompression. Notably, closely monitor the data volume filtered out by the ``Filter`` node. + +The table of 77 million rows was read into 74 chunks. After applying a filter, only 18,160 relevant rows remained, dispersed across these 74 chunks. Ideally, these rows could be consolidated into a single chunk rather than spanning multiple sparse chunks. Improving Join Performance when Data is Sparse ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -You can tell SQreamDB to reduce the amount of chunks involved, if you know that the filter is going to be quite -agressive by using the :ref:`HIGH_SELECTIVITY<high_selectivity>` hint described :ref:`above<high_selectivity_data_opt>`. -This forces the compiler to rechunk the data into fewer chunks. -To tell SQreamDB to rechunk the data, wrap a condition (or several) in the ``HIGH_SELECTIVITY`` hint: +To optimize performance in SQreamDB, especially when dealing with aggressive filtering, you can use the :ref:`HIGH_SELECTIVITY<high_selectivity>` hint as described :ref:`above<high_selectivity_data_opt>`. This hint instructs the compiler to rechunk the data into fewer chunks. + +To apply this optimization, wrap your filtering condition (or conditions) with the ``HIGH_SELECTIVITY`` hint like this: .. code-block:: postgres :emphasize-lines: 13 @@ -1057,22 +1053,17 @@ To tell SQreamDB to rechunk the data, wrap a condition (or several) in the ``HIG Manual Join Reordering ---------------------- -When joining multiple tables, you may wish to change the join order to join the smallest tables first. +When performing joins involving multiple tables, consider changing the join order to start with the smallest tables first. Identifying the situation ^^^^^^^^^^^^^^^^^^^^^^^^^ -When joining more than two tables, the ``Join`` nodes will be the most time-consuming nodes. +When joining more than two tables, the ``Join`` nodes typically represent the most time-consuming operations. Changing the Join Order ^^^^^^^^^^^^^^^^^^^^^^^ -Always prefer to join the smallest tables first. -.. note:: - We consider small tables to be tables that only retain a small amount of rows after conditions - are applied. This bears no direct relation to the amount of total rows in the table. -Changing the join order can reduce the query runtime significantly. In the examples below, we reduce the time -from 27.3 seconds to just 6.4 seconds. +It's advisable to prioritize joining the smallest tables first. By small tables, we mean tables that retain a relatively low number of rows after applying filtering conditions, regardless of the total row count in the table. Changing the join order in this way can lead to a significant reduction in query runtime. For instance, in specific examples, this approach has resulted in a remarkable 76.64% reduction in query time. .. code-block:: postgres :caption: Original query @@ -1094,7 +1085,6 @@ from 27.3 seconds to just 6.4 seconds. GROUP BY c_nationkey .. code-block:: postgres - :caption: Modified query with improved join order -- This variant runs in 6.4 seconds diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 002ddf173..24611d8cf 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -36,24 +36,28 @@ Creating quoted and unquoted identifiers: CREATE ROLE "Developer"; --quoted identifiers preserves case - will create "Developer" CREATE ROLE Developer; --unquoted identifiers ignores case - will create "developer" -Valid and invalid use of identifiers: +These are all valid examples when quoted, but are invalid when unquoted: .. code-block:: postgres - -- these are all valid examples when quoted: - CREATE SCHEMA "my schema"; - CREATE SCHEMA "123schema"; - -- but are invalid when unquoted: + CREATE SCHEMA "123schema"; + + CREATE SCHEMA my schema; --invalid - CREATE SCHEMA my schema; --invalid - CREATE SCHEMA 123schema; --invalid + CREATE SCHEMA 123schema; --invalid - -- Use of invalid characters: +Use of invalid characters, such as ``@``: + +.. code-block:: postgres CREATE SCHEMA "my schema@master"; +Provides the following error message: + +.. code-block:: console + Status: Ended with errorError preparing statement: Unsupported character '@' in identifier: "my schema@master" Quoted identifiers cannot contain the character '@'. Quoted identifiers may contain any ASCII character with code between 32 and 126 except for: From 7e93ffa3c551de1a58e21b052cf3dbd768cfa877 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 17 Apr 2024 15:00:23 +0300 Subject: [PATCH 1294/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 796695f4c..5ff6a0582 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -19,6 +19,8 @@ Data Integration Tools :ref:`Talend<talend>` +:ref:`Semarchy<semarchy>` + :ref:`SQL Workbench<connect_to_sql_workbench>` Business Intelligence (BI) Tools @@ -60,11 +62,12 @@ Data Analysis and Programming Languages r sap_businessobjects sas_viya + semarchy sql_workbench tableau talend tibco_spotfire - + trino @@ -73,4 +76,3 @@ Data Analysis and Programming Languages - From 6d577bd85a116a5f53bf6b2a1f0daeda552dab9b Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Wed, 17 Apr 2024 15:01:23 +0300 Subject: [PATCH 1295/1892] Create semarchy.rst --- .../client_platforms/semarchy.rst | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 connecting_to_sqream/client_platforms/semarchy.rst diff --git a/connecting_to_sqream/client_platforms/semarchy.rst b/connecting_to_sqream/client_platforms/semarchy.rst new file mode 100644 index 000000000..05aee35cd --- /dev/null +++ b/connecting_to_sqream/client_platforms/semarchy.rst @@ -0,0 +1,89 @@ +.. _semarchy: + +*************** +Semarchy +*************** + +Semarchy's Intelligent Data eXchange (IDX) facilitates seamless data integration and interoperability across systems. IDX ensures reliable data exchange between different applications, enhancing overall data quality, governance, and adaptability for critical business operations. + +Before You Begin +================ + +It is essential that you use Semarchy version 2023.01 or later. + +Setting Up a Connection to SQreamDB +=================================== + +#. Install the Semarchy SQreamDB component as described in `Semarchy documentation <https://www.semarchy.com/doc/semarchy-xdi/xdi/latest/Components/sqreamdb/overview.html>`_. + +#. Install SQreamDB :ref:`java_jdbc`. + +JDBC Connection String +====================== + +The following is a SQreamDB JDBC connection string template: + +.. code-block:: text + + jdbc:Sqream://<host and port>/<database name>;user=<username>;password=<password>;[<optional parameters>; ...] + +Connection Parameters +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Item + - State + - Default + - Description + * - ``<host and port>`` + - Mandatory + - None + - Hostname and port of the SQream DB worker. For example, ``127.0.0.1:5000``, ``sqream.mynetwork.co:3108`` + * - ``<database name>`` + - Mandatory + - None + - Database name to connect to. For example, ``master`` + * - ``username=<username>`` + - Optional + - None + - Username of a role to use for connection. For example, ``username=SqreamRole`` + * - ``password=<password>`` + - Optional + - None + - Specifies the password of the selected role. For example, ``password=SqreamRolePassword2023`` + * - ``service=<service>`` + - Optional + - ``sqream`` + - Specifices service queue to use. For example, ``service=etl`` + * - ``<ssl>`` + - Optional + - ``false`` + - Specifies SSL for this connection. For example, ``ssl=true`` + * - ``<cluster>`` + - Optional + - ``true`` + - Connect via load balancer (use only if exists, and check port). + * - ``<fetchSize>`` + - Optional + - ``true`` + - Enables on-demand loading, and defines double buffer size for the result. The ``fetchSize`` parameter is rounded according to chunk size. For example, ``fetchSize=1`` loads one row and is rounded to one chunk. If the ``fetchSize`` is 100,600, a chunk size of 100,000 loads, and is rounded to, two chunks. + * - ``<insertBuffer>`` + - Optional + - ``true`` + - Defines the bytes size for inserting a buffer before flushing data to the server. Clients running a parameterized insert (network insert) can define the amount of data to collect before flushing the buffer. + * - ``<loggerLevel>`` + - Optional + - ``true`` + - Defines the logger level as either ``debug`` or ``trace``. + * - ``<logFile>`` + - Optional + - ``true`` + - Enables the file appender and defines the file name. The file name can be set as either the file name or the file path. + * - ``<idleconnectiontimeout>`` + - Optional + - 0 + - Sets the duration, in seconds, for which a database connection can remain idle before it is terminated. If the parameter is set to its default value, idle connections will not be terminated. The idle connection timer begins counting after the completion of query execution. + From 209ed3c9b665373ffa497e5deb24badf912c24e7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:57:23 +0300 Subject: [PATCH 1296/1892] Update pentaho.rst --- connecting_to_sqream/client_platforms/pentaho.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst index 26ea788cb..64cd8f81b 100644 --- a/connecting_to_sqream/client_platforms/pentaho.rst +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -23,7 +23,7 @@ The Connecting to SQream Using Pentaho page describes the following: Installing Pentaho ~~~~~~~~~~~~~~~~~~ -To install PDI, see the `Pentaho Community Edition (CE) Installation Guide <https://www.hitachivantara.com/en-us/pdf/white-paper/pentaho-community-edition-installation-guide-for-windows-whitepaper.pdf>`_. +To install PDI, see the `Pentaho Community Edition (CE) Installation Guide <https://www.hitachivantara.com/en-us/pdf/implementation-guide/three-steps-to-install-pentaho-data-integration-ce.pdf>`_. The **Pentaho Community Edition (CE) Installation Guide** describes how to do the following: From ac316b856f69a3f4b5701449f215bac5315c7e10 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 14:58:46 +0300 Subject: [PATCH 1297/1892] Update talend.rst --- connecting_to_sqream/client_platforms/talend.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index e2db1d278..cdfeed1ea 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -123,6 +123,4 @@ Talend Cloud connectors let you create reusable connections with a wide variety Known Issues ------------ -As of 6/1/2021 schemas were not displayed for tables with identical names. - -If you experience issues using Talend, see the `SQream support portal <https://support.sqream.com>`_. \ No newline at end of file +As of 6/1/2021 schemas were not displayed for tables with identical names. \ No newline at end of file From 9f8769c0ff4313974c9226eb36c73389e04e1584 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:03:44 +0300 Subject: [PATCH 1298/1892] Update 2021.2.1.24.rst --- releases/2021.2.1.24.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst index b43594976..90fc9eab0 100644 --- a/releases/2021.2.1.24.rst +++ b/releases/2021.2.1.24.rst @@ -28,7 +28,7 @@ Query Healer ************ The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. -For more information, see `Query Healer <https://docs.sqream.com/en/v2021.2.1.24/feature_guides/query_healer.html>`_. +For more information, see :ref:`query_healer`. Resolved Issues --------------- From a344d1f88fe4ab0327979e2ce2c5fb62316437e3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:24:24 +0300 Subject: [PATCH 1299/1892] Update filesystem_and_filesystem_usage.rst --- architecture/filesystem_and_filesystem_usage.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/architecture/filesystem_and_filesystem_usage.rst b/architecture/filesystem_and_filesystem_usage.rst index 1bd670efb..90b1c0a40 100644 --- a/architecture/filesystem_and_filesystem_usage.rst +++ b/architecture/filesystem_and_filesystem_usage.rst @@ -77,7 +77,7 @@ The ``temp`` directory is where SQreamDB writes temporary data. The directory to which SQreamDB writes temporary data can be changed to any other directory on the filesystem. SQreamDB recommends remapping this directory to a fast local storage to get better performance when executing intensive larger-than-RAM operations like sorting. SQreamDB recommends an SSD or NVMe drive, in mirrored RAID 1 configuration. -If desired, the ``temp`` folder can be redirected to a local disk for improved performance, by setting the ``tempPath`` setting in the :ref:`configuration<configuration>` file. +If desired, the ``temp`` folder can be redirected to a local disk for improved performance, by setting the ``tempPath`` setting in the :ref:`legacy configuration<current_method_modification_methods>` file. ``logs`` From 0d1c67694e6f2a2662e546862fd24e7f4db9dde8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 15:33:11 +0300 Subject: [PATCH 1300/1892] Remove 2021 --- releases/2021.2.1.24.rst | 94 ------------------- releases/2021.2.1.rst | 91 ------------------- releases/2021.2.rst | 184 -------------------------------------- releases/2021.2_index.rst | 18 ---- releases/index.rst | 2 +- 5 files changed, 1 insertion(+), 388 deletions(-) delete mode 100644 releases/2021.2.1.24.rst delete mode 100644 releases/2021.2.1.rst delete mode 100644 releases/2021.2.rst delete mode 100644 releases/2021.2_index.rst diff --git a/releases/2021.2.1.24.rst b/releases/2021.2.1.24.rst deleted file mode 100644 index 90fc9eab0..000000000 --- a/releases/2021.2.1.24.rst +++ /dev/null @@ -1,94 +0,0 @@ -.. _2021.2.1.24: - -************************* -Release Notes 2021.2.1.24 -************************* - -The 2021.2.1.24 release notes were released on 7/28/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ---------------- - -The 2021.2.1.24 Release Notes includes a query maintenance feature. - -New Features ------------- - -The 2021.2.1.24 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Query Healer -************ -The new **Query Healer** feature periodically examines the progress of running statements, and is used for query maintenance. - -For more information, see :ref:`query_healer`. - -Resolved Issues ---------------- - -The following table lists the resolved issues for Version 2021.2.1.24: - -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+====================================================================================================================================+ -| SQ-10606 | Queries were getting stuck in the queue for a prolonged time. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10691 | The DB schema identifier was causing an error when running queries from joins suite. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10918 | The Workload Manager was only assigning jobs sequentially, delaying user SQLs assigned to workers running very large jobs. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10955 | Metadata filters were not being applied when users filtered by nullable dates using ``dateadd`` | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ - -Known Issues ------------- - -The following table lists the known issues for Version 2021.2.1.24: - -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+====================================================================================================================================+ -| SQ-10071 | An error occurred on existing subqueries with ``TEXT`` and ``VARCHAR`` equality conditions. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-10902 | Inserting a null value into non-null column was causing SQream to crash. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11088 | Specific workers caused low performance during compilation. | -+-------------+------------------------------------------------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes ------------------------------------- - -The following worker level configuration flags were added: - - * :ref:`is_healer_on` - - :: - - * :ref:`healer_max_statement_inactivity_seconds` - - :: - - * :ref:`healer_detection_frequency_seconds` - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -Version 2021.2.1.24 includes no deprecated features. - -End of Support --------------- - -The End of Support section is not relevant to Version 2021.2.1.24. - diff --git a/releases/2021.2.1.rst b/releases/2021.2.1.rst deleted file mode 100644 index 1f427df49..000000000 --- a/releases/2021.2.1.rst +++ /dev/null @@ -1,91 +0,0 @@ -.. _2021.2.1: - -********************** -Release Notes 2021.2.1 -********************** - -The 2021.2.1 release notes were released on 15/12/2021 and describes the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - -The 2021.2.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -CREATE TABLE -************ - -SQream now supports duplicating the column structure of an existing table using the ``LIKE`` clause. - -For more information, see `Duplicating the Column Structure of an Existing Table <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_statements/ddl_commands/create_table.html#duplicating-the-column-structure-of-an-existing-table>`_. - -PERCENTILE FUNCTIONS -************ -SQream now supports the following aggregation functions: - -* `PERCENTILE_CONT <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/aggregate_functions/percentile_cont.html>`_ -* `PERCENTILE_DISC <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/aggregate_functions/percentile_disc.html>`_ -* `MODE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/aggregate_functions/mode.html>`_ - -REGEX REPLACE -************* - -SQream now supports the ``REGEXP_REPLACE`` function for finding and replacing text column substrings. - -For more information, see `REGEX_REPLACE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/scalar_functions/string/regexp_replace.html>`_. - -Delete Optimization -******************* - -The ``DELETE`` statement can now delete values that contain multi-table conditions. - -For more information, see `Deleting Values that Contain Multi-Table Conditions <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_statements/dml_commands/delete.html#deleting-values-that-contain-multi-table-conditions>`_. - -For more information, see `REGEX_REPLACE <https://docs.sqream.com/en/v2021.2.1/reference/sql/sql_functions/scalar_functions/string/regexp_replace.html>`_. - -Performance Enhancements ------------------------- - -The **Performance Enhancements** section is not relevant to Version 2021.2.1. - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2021.2.1: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-8267 - - A method has been provided for including the ``GROUP BY`` and ``DISTINCT COUNT`` statements. - -Known Issues ------------- - -The **Known Issues** section is not relevant to 2021.2.1. - -Naming Convention Modifications -------------------------------- - -The **Naming Convention Modifications** section is not relevant to Version 2021.2.1. - -End of Support --------------- - -The **End of Support** section is not relevant to Version 2021.2.1. - -Deprecated Features -------------------- - -The **Deprecated Components** section is not relevant to Version 2021.2.1. - diff --git a/releases/2021.2.rst b/releases/2021.2.rst deleted file mode 100644 index 790c33956..000000000 --- a/releases/2021.2.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. _2021.2: - -******************** -Release Notes 2021.2 -******************** - -The 2021.2 release notes were released on 13/9/2021. - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - -The 2021.2 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -New Driver Compatibility -************************ - -The 2021.2 release supports the following drivers: - -* **JDBC** - new driver version (JDBC 4.5) with important bug fixes. -* **ODBC** - ODBC 4.1.1. available on request. -* **NodeJS** - all versions starting with NodeJS 4.0. SQream recommends the latest version (NodeJS 4.2.4). -* **Dot Net** - SQream recommends version version 3.02 (compatible with DotNet version 48). -* **Pysqream** - pysqream 3.1.2 - -Centralized Configuration System -******************************** - -SQream now uses a new configuration system based on centralized configuration accessible from SQream Studio. - -For more information, see the following: - -* `Configuration <https://docs.sqream.com/en/v2021.2/guides/operations/configuration.html>` - describes how to configure your instance of SQream from a centralized location. -* `SQream Studio 5.4.3 <https://docs.sqream.com/en/v2021.2/sqream_studio_5.4.3/index.html>`_ - configure your instance of SQream from Studio. - -Qualifying Schemas Without Providing an Alias -********************************************* - -When running queries, SQream now supports qualifying schemas without providing an alias. - -For more information, see `SQream Studio 5.4.3 <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/ddl_commands/create_schema.html>`_. - -Double-Quotations Supported When Importing and Exporting CSVs -************************************************************* - -When importing and exporting CSVs, SQream now supports using quotation characters other than double quotation marks (``"``). - -For more information, see the following: - -* `COPY_FROM <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/dml_commands/copy_from.html#copy-from>`_ - -* `COPY_TO <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/dml_commands/copy_to.html#copy-to>`_ - - - -Note the following: - -* Leaving *<x>* unspecified uses the default value of standard double quotations ``”``. - - :: - -* The quotation character must be a single, 1-byte printable ASCII character. The same octal syntax of the copy command can be used. - - :: - -* The quote character cannot be contained in the field delimiter, record delimiter, or null marker. - - :: - -* Double-quotations can be customized when the ``csv_fdw`` value is used with the ``COPY FROM`` and ``CREATE FOREIGN TABLE`` statements. - - :: - -* The default escape character always matches the quote character, and can be overridden by using the ``ESCAPE = {'\\' | E'\XXX')`` syntax as shown in the following examples: - - .. code-block:: postgres - - copy t from wrapper csv_fdw options (location = '/tmp/file.csv', escape='\\'); - - .. code-block:: postgres - - copy t from wrapper csv_fdw options (location = '/tmp/file.csv', escape=E'\017'); - - .. code-block:: postgres - - copy t to wrapper csv_fdw options (location = '/tmp/file.csv', escape='\\'); - -For more information, see the following statements: - - -* `COPY_FROM <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/dml_commands/copy_from.html#copy-from>`_ - -* `CREATE_FOREIGN_TABLE <https://docs.sqream.com/en/v2021.2/reference/sql/sql_statements/ddl_commands/create_foreign_table.html>`_ - -Performance Enhancements ------------------------- - -In Version 2021.2, an advanced smart spooling mechanism splits spool memory based on required CP usage. - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2021.2: - -.. list-table:: - :widths: 17 200 - :header-rows: 1 - - * - SQ No. - - Description - * - SQ-8294 - - Quote qualifiers were not present in exported file, preventing it from being reloaded. - * - SQ-8288 - - Saved ``TEXT`` query parameters were not supported. - * - SQ-8266 - - A data loading issue occurred related to column order. - - -Known Issues ------------- - -The **Known Issues** section is not relevant to Version 2021.2. - - -Naming Convention Modifications -------------------------------- - -The **Naming Convention Modifications** describes SQream features, such as data types or statements, that have been renamed. - -NVARCHAR Data Type Renamed TEXT -************ -The ``NVARCHAR`` data type has been renamed ``TEXT``. - - -For more information on the ``TEXT`` data type, see `String (TEXT) <https://docs.sqream.com/en/v2021.2/data_type_guides/sql_data_types_string.html>`_ - -End of Support --------------- - -The **End of Support** section is not relevant to Version 2021.2. - -Deprecated Features -------------------- - -The **Deprecated Components** section is not relevant to Version 2021.2. - -Upgrading Your SQream Version ------------------------------ - -The **Upgrading Your SQream Version** section describes the following: - -.. contents:: - :local: - :depth: 1 - -Upgrading Your Storage Version -****************************** - -When upgrading from a SQream version earlier than 2021.2 you must upgrade your storage version, as shown in the following example: - - .. code-block:: console - - $ cat /etc/sqream/sqream1_config.json |grep cluster - $ ./upgrade_storage <cluster path> - -For more information on upgrading your SQream version, see `Upgrading SQream Version <https://docs.sqream.com/en/v2021.2/guides/operations/installing_sqream_with_binary.html#upgrading-sqream-version>`_. - -Upgrading Your Client Drivers -************ -For more information on the client drivers for version 2021.2, see `Client Drivers for 2021.2 <https://docs.sqream.com/en/v2021.2/connecting_to_sqream/client_drivers/index.html>`_. - -Configuring Your Instance of SQream -************ -A new configuration method is used starting with Version 2021.2. - -For more information about configuring your instance of SQream, see `Client Drivers for 2021.2 <https://docs.sqream.com/en/v2021.2/configuration_guides/index.html>`_. - diff --git a/releases/2021.2_index.rst b/releases/2021.2_index.rst deleted file mode 100644 index 9bee5fd66..000000000 --- a/releases/2021.2_index.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _2021.2_index: - -************************** -Release Notes 2021.2 -************************** -The 2021.2 Release Notes describe the following releases: - -.. contents:: - :local: - :depth: 1 - -.. toctree:: - :maxdepth: 1 - :glob: - - 2021.2.1.24 - 2021.2.1 - 2021.2 \ No newline at end of file diff --git a/releases/index.rst b/releases/index.rst index 4b082aa8b..9abcc4187 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -55,6 +55,6 @@ Release Notes 4.0_index 2022.1_index - 2021.2_index + From 0fe53a539d83a327a10f41b70bb515525ab051c8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Apr 2024 16:23:31 +0300 Subject: [PATCH 1301/1892] Maintenance --- configuration_guides/cache_persistent_gb.rst | 5 +- .../copy_to_restrict_utf8.rst | 5 +- .../cuda_mem_cpy_max_size_bytes.rst | 5 +- configuration_guides/cuda_mem_quota.rst | 5 +- configuration_guides/flip_join_order.rst | 5 +- configuration_guides/graceful_shutdown.rst | 2 - .../client_drivers/dataiku/index.rst | 1 - .../client_platforms/informatica.rst | 48 +--- data_type_guides/sql_data_types_boolean.rst | 6 +- data_type_guides/sql_data_types_date.rst | 9 +- .../sql_data_types_floating_point.rst | 8 +- data_type_guides/sql_data_types_integer.rst | 7 +- data_type_guides/sql_data_types_numeric.rst | 2 +- external_storage_platforms/index.rst | 9 +- operational_guides/hdfs.rst | 265 ------------------ operational_guides/s3.rst | 129 --------- 16 files changed, 44 insertions(+), 467 deletions(-) delete mode 100644 operational_guides/hdfs.rst delete mode 100644 operational_guides/s3.rst diff --git a/configuration_guides/cache_persistent_gb.rst b/configuration_guides/cache_persistent_gb.rst index 418364e5c..ff223b299 100644 --- a/configuration_guides/cache_persistent_gb.rst +++ b/configuration_guides/cache_persistent_gb.rst @@ -1,8 +1,9 @@ .. _cache_persistent_gb: -************************* +***************************************** Setting Data Stored Persistently on Cache -************************* +***************************************** + The ``cachePersistentGB`` flag sets the amount of data (GB) for the cache to store persistently . The following describes the ``cachePersistentGB`` flag: diff --git a/configuration_guides/copy_to_restrict_utf8.rst b/configuration_guides/copy_to_restrict_utf8.rst index 869de3bea..66ee4ab72 100644 --- a/configuration_guides/copy_to_restrict_utf8.rst +++ b/configuration_guides/copy_to_restrict_utf8.rst @@ -1,8 +1,9 @@ .. _copy_to_restrict_utf8: -************************* +************************************* Enabling High Bin Control Granularity -************************* +************************************* + The ``copyToRestrictUtf8`` flag sets the custom bin size in the cache to enable high bin control granularity. The following describes the ``copyToRestrictUtf8`` flag: diff --git a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst index 371c9bda4..9c7de07ce 100644 --- a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst +++ b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst @@ -1,8 +1,9 @@ .. _cuda_mem_cpy_max_size_bytes: -************************* +********************************************** Setting Chunk Size for Copying from CPU to GPU -************************* +********************************************** + The ``cudaMemcpyMaxSizeBytes`` flag sets the chunk size for copying from CPU to GPU. If this value is set to ``0``, do not divide. The following describes the ``cudaMemcpyMaxSizeBytes`` flag: diff --git a/configuration_guides/cuda_mem_quota.rst b/configuration_guides/cuda_mem_quota.rst index 43f9d4943..b659c566d 100644 --- a/configuration_guides/cuda_mem_quota.rst +++ b/configuration_guides/cuda_mem_quota.rst @@ -1,8 +1,9 @@ .. _cuda_mem_quota: -************************* +**************************************************** Setting Total Device Memory Usage in SQream Instance -************************* +**************************************************** + The ``cudaMemQuota`` flag sets the percentage of total device memory used by your instance of SQream. The following describes the ``cudaMemQuota`` flag: diff --git a/configuration_guides/flip_join_order.rst b/configuration_guides/flip_join_order.rst index 341f12ada..d160beb5a 100644 --- a/configuration_guides/flip_join_order.rst +++ b/configuration_guides/flip_join_order.rst @@ -1,8 +1,9 @@ .. _flip_join_order: -************************* +************************************** Flipping Join Order to Force Equijoins -************************* +************************************** + The ``flipJoinOrder`` flag reorders join to force equijoins and/or equijoins sorted by table size. The following describes the ``flipJoinOrder`` flag: diff --git a/configuration_guides/graceful_shutdown.rst b/configuration_guides/graceful_shutdown.rst index f136f87d7..f461a5262 100644 --- a/configuration_guides/graceful_shutdown.rst +++ b/configuration_guides/graceful_shutdown.rst @@ -18,6 +18,4 @@ For related flags, see the folowing: * :ref:`is_healer_on` - :: - * :ref:`healer_max_inactivity_hours` \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index ff5787bcb..72b6fd8d8 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -52,5 +52,4 @@ In your Dataiku web interface: a. Filling in the values in the Plugin form b. Set the Project Variables or set the Global Variables when DSS Variables are used - diff --git a/connecting_to_sqream/client_platforms/informatica.rst b/connecting_to_sqream/client_platforms/informatica.rst index 9a5c41023..b8b5e9cc2 100644 --- a/connecting_to_sqream/client_platforms/informatica.rst +++ b/connecting_to_sqream/client_platforms/informatica.rst @@ -23,13 +23,9 @@ The **Establishing a Connection between SQream and Informatica** page describes 1. Go to the `Informatica Cloud homepage <https://emw1.dm-em.informaticacloud.com/diUI/products/integrationDesign/main/home>`_. - :: - 2. Do one of the following: 1. Log in using your credentials. - - :: 2. Log in using your SAML Identity Provider. @@ -38,26 +34,16 @@ The **Establishing a Connection between SQream and Informatica** page describes The SQream dashboard is displayed. - - :: - - 4. In the menu on the left, click **Runtime Environments**. The **Runtime Environments** panel is displayed. - :: - 5. Click **Download Secure Agent**. - :: - 6. When the **Download the Secure Agent** panel is displayed, do the following: 1. Select a platform (Windows 64 or Linux 64). - - :: 2. Click **Copy** and save the token on your local hard drive. @@ -68,27 +54,18 @@ The **Establishing a Connection between SQream and Informatica** page describes 7. Click **Download**. The installation begins. - - :: + 8. When the **Informatica Cloud Secure Agent Setup** panel is displayed, click **Next**. - :: - - 9. Provide your **User Name** and **Install Token** and click **Register**. - :: - - 10. From the Runtime Environments panel, click **New Runtime Environment**. The **New Secure Agent Group** window is displayed. - - :: 11. On the New Secure Agent Group window, click **OK** to connect your Runtime Environment with the running agent. @@ -110,24 +87,16 @@ After establishing a connection between SQream and Informatica you can establish **To establish an ODBC connection in your environment:** 1. Click **Add**. - - :: 2. Click **Configure**. .. note:: Verify that **Use Server Picker** is selected. 3. Click **Test**. - - :: 4. Verify that the connection has tested successfully. - - :: 5. Click **Save**. - - :: 6. Click **Actions** > **Publish**. @@ -141,27 +110,18 @@ After establishing a connection between SQream and Informatica you can establish 1. Create a new DB connection by clicking **Connections** > **New Connection**. The **New Connection** window is displayed. - - :: 2. In the **JDBC_IC Connection Properties** section, in the **JDBC Connection URL** field, establish a JDBC connection by providing the correct connection string. - For connection string examples, see `Connection Strings <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/jdbc/index.html#connection-string-examples>`_. - - :: + For connection string examples, see :ref:`Connection Strings<java_jdbc>`. + 3. Click **Test**. - - :: 4. Verify that the connection has tested successfully. - - :: 5. Click **Save**. - - :: 6. Click **Actions** > **Publish**. @@ -172,6 +132,4 @@ SQream supports the following SQream driver versions: * **JDBC** - Version 4.3.4 and above. - :: - * **ODBC** - Version 4.0.0 and above. diff --git a/data_type_guides/sql_data_types_boolean.rst b/data_type_guides/sql_data_types_boolean.rst index 84b7c14ce..8142ae6f6 100644 --- a/data_type_guides/sql_data_types_boolean.rst +++ b/data_type_guides/sql_data_types_boolean.rst @@ -3,6 +3,7 @@ ************************* Boolean ************************* + The following table describes the Boolean data type. .. list-table:: @@ -17,7 +18,8 @@ The following table describes the Boolean data type. - 1 byte, but resulting average data sizes may be lower after compression. Boolean Examples -^^^^^^^^^^ +^^^^^^^^^^^^^^^^ + The following is an example of the Boolean syntax: .. code-block:: postgres @@ -37,7 +39,7 @@ The following is an example of the correct output: "kiwi","Is not angry" Boolean Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following table shows the possible Boolean value conversions: diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index 5c2a3a4a9..33b3f7ec5 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -3,11 +3,13 @@ ************************* Date ************************* + ``DATE`` is a type designed for storing year, month, and day. ``DATETIME`` is a type designed for storing year, month, day, hour, minute, seconds, and milliseconds in UTC with 1 millisecond precision. Date Types ^^^^^^^^^^^^^^^^^^^^^^ + The following table describes the Date types: .. list-table:: Date Types @@ -35,6 +37,7 @@ Aliases Syntax ^^^^^^^^ + ``DATE`` values are formatted as string literals. The following is an example of the DATETIME syntax: @@ -60,12 +63,14 @@ SQream attempts to guess if the string literal is a date or datetime based on co Size ^^^^^^ + A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes in length. However, the size of these values is compressed by SQream DB. Date Examples -^^^^^^^^^^ +^^^^^^^^^^^^^ + The following is an example of the Date syntax: .. code-block:: postgres @@ -96,7 +101,7 @@ The following is an example of the correct output: Date Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^ The following table shows the possible ``DATE`` and ``DATETIME`` value conversions: diff --git a/data_type_guides/sql_data_types_floating_point.rst b/data_type_guides/sql_data_types_floating_point.rst index 3edc8362d..4ea388dd7 100644 --- a/data_type_guides/sql_data_types_floating_point.rst +++ b/data_type_guides/sql_data_types_floating_point.rst @@ -3,12 +3,14 @@ ************************* Floating Point ************************* + The **Floating Point** data types (``REAL`` and ``DOUBLE``) store extremely close value approximations, and are therefore recommended for values that tend to be inexact, such as Scientific Notation. While Floating Point generally runs faster than Numeric, it has a lower precision of ``9`` (``REAL``) or ``17`` (``DOUBLE``) compared to Numeric's ``38``. For operations that require a higher level of precision, using :ref:`Numeric <numeric>` is recommended. The floating point representation is based on `IEEE 754 <https://en.wikipedia.org/wiki/IEEE_754>`_. Floating Point Types ^^^^^^^^^^^^^^^^^^^^^^ + The following table describes the Floating Point data types. .. list-table:: @@ -42,7 +44,8 @@ The following table shows information relevant to the Floating Point data types. - Floating point types are either 4 or 8 bytes, but size could be lower after compression. Floating Point Examples -^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^ + The following are examples of the Floating Point syntax: .. code-block:: postgres @@ -61,7 +64,8 @@ The following are examples of the Floating Point syntax: .. note:: Most SQL clients control display precision of floating point numbers, and values may appear differently in some clients. Floating Point Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following table shows the possible Floating Point value conversions: .. list-table:: diff --git a/data_type_guides/sql_data_types_integer.rst b/data_type_guides/sql_data_types_integer.rst index cd27f6956..24ace31b9 100644 --- a/data_type_guides/sql_data_types_integer.rst +++ b/data_type_guides/sql_data_types_integer.rst @@ -3,12 +3,14 @@ ************************* Integer ************************* + Integer data types are designed to store whole numbers. For more information about identity sequences (sometimes called auto-increment or auto-numbers), see :ref:`identity`. Integer Types ^^^^^^^^^^^^^^^^^^^ + The following table describes the Integer types. .. list-table:: @@ -48,7 +50,8 @@ The following table describes the Integer data type. - Integer types range between 1, 2, 4, and 8 bytes - but resulting average data sizes could be lower after compression. Integer Examples -^^^^^^^^^^ +^^^^^^^^^^^^^^^^ + The following is an example of the Integer syntax: .. code-block:: postgres @@ -67,7 +70,7 @@ The following is an example of the correct output: -5,127,32000,45000000000 Integer Casts and Conversions -^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following table shows the possible Integer value conversions: diff --git a/data_type_guides/sql_data_types_numeric.rst b/data_type_guides/sql_data_types_numeric.rst index cb1b7a810..6a7a7b6ec 100644 --- a/data_type_guides/sql_data_types_numeric.rst +++ b/data_type_guides/sql_data_types_numeric.rst @@ -9,7 +9,7 @@ The **Numeric** data type (also known as **Decimal**) is recommended for values The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. If no parameters are specified, Numeric defaults to ``numeric(38, 0)``. Numeric Examples -^^^^^^^^^^ +^^^^^^^^^^^^^^^^ The following is an example of the Numeric syntax: diff --git a/external_storage_platforms/index.rst b/external_storage_platforms/index.rst index bec142ce0..ec8aaf2d0 100644 --- a/external_storage_platforms/index.rst +++ b/external_storage_platforms/index.rst @@ -1,8 +1,9 @@ .. _external_storage_platforms: -*********************** +************************** External Storage Platforms -*********************** +************************** + SQream supports the following external storage platforms: .. toctree:: @@ -19,11 +20,7 @@ SQream supports the following external storage platforms: For more information, see the following: * :ref:`foreign_tables` - - :: * :ref:`copy_from` - - :: * :ref:`copy_to` diff --git a/operational_guides/hdfs.rst b/operational_guides/hdfs.rst deleted file mode 100644 index e59c49cc7..000000000 --- a/operational_guides/hdfs.rst +++ /dev/null @@ -1,265 +0,0 @@ -.. _hdfs: - -.. _back_to_top_hdfs: - -Using SQream in an HDFS Environment -======================================= - -.. _configuring_an_hdfs_environment_for_the_user_sqream: - -Configuring an HDFS Environment for the User **sqream** ----------------------------------------------------------- - -This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. - -**To configure an HDFS environment for the user sqream:** - -1. Open your **bash_profile** configuration file for editing: - - .. code-block:: console - - $ vim /home/sqream/.bash_profile - -.. - Comment: - see below; do we want to be a bit more specific on what changes we're talking about? - - .. code-block:: console - - $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin - - $ #export PATH - - $ # PS1 - $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') - $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" - - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME - - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - - - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH - -2. Verify that the edits have been made: - - .. code-block:: console - - source /home/sqream/.bash_profile - -3. Check if you can access Hadoop from your machine: - - .. code-block:: console - - $ hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ - -.. - Comment: - - **NOTICE:** If you cannot access Hadoop from your machine because it uses Kerberos, see `Connecting a SQream Server to Cloudera Hadoop with Kerberos <https://sqream.atlassian.net/wiki/spaces/DOC/pages/822902789/How+to+connect+sqream+server+to+Cloudera+Hadoop+with+kerberos>`_ - - -4. Verify that an HDFS environment exists for SQream services: - - .. code-block:: console - - $ ls -l /etc/sqream/sqream_env.sh - -.. _step_6: - - -5. If an HDFS environment does not exist for SQream services, create one (sqream_env.sh): - - .. code-block:: console - - $ #!/bin/bash - - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME - - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - - - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH - -:ref:`Back to top <back_to_top_hdfs>` - -.. _authenticate_hadoop_servers_that_require_kerberos: - -Authenticating Hadoop Servers that Require Kerberos ---------------------------------------------------- -If your Hadoop server requires Kerberos authentication, do the following: - -1. Create a principal for the user **sqream**. - - .. code-block:: console - - $ kadmin -p root/admin@SQ.COM - $ addprinc sqream@SQ.COM - -2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: - - .. code-block:: console - - $ kadmin.local - - Running **kadmin.local** does not require a password. - -3. If a password is not required, change your password to **sqream@SQ.COM**. - - .. code-block:: console - - $ change_password sqream@SQ.COM - -4. Connect to the hadoop name node using ssh: - - .. code-block:: console - - $ cd /var/run/cloudera-scm-agent/process - -5. Check the most recently modified content of the directory above: - - .. code-block:: console - - $ ls -lrt - -6. Look for a recently updated folder containing the text **hdfs**. - - The following is an example of the correct folder name: - - .. code-block:: console - - cd <number>-hdfs-<something> - - This folder should contain a file named **hdfs.keytab** or another similar .keytab file. - - - -.. - Comment: - Does "something" need to be replaced with "file name" - - -7. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. - - :: - -8. Copy the following files to the **sqream sqream@server:<sqream folder>/hdfs/hadoop/etc/hadoop:** directory: - - * core-site.xml - * hdfs-site.xml - -9. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: - - .. code-block:: console - - $ sudo chown sqream:sqream /home/sqream/hdfs.keytab - $ sudo chmod 600 /home/sqream/hdfs.keytab - -10. Log into the sqream server. - - :: - -11. Log in as the user **sqream**. - - :: - -12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: - - .. code-block:: console - - $ klist -kt hdfs.keytab - - The following is an example of the correct output: - - .. code-block:: console - - $ sqream@Host-121 ~ $ klist -kt hdfs.keytab - $ Keytab name: FILE:hdfs.keytab - $ KVNO Timestamp Principal - $ ---- ------------------- ------------------------------------------------------ - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - -13. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. - - :: - -14. Run the following: - - .. code-block:: console - - $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM - -15. Verify that the output is correct: - - .. code-block:: console - - $ klist - - The following is an example of the correct output: - - .. code-block:: console - - $ Ticket cache: FILE:/tmp/krb5cc_1000 - $ Default principal: sqream@SQ.COM - $ - $ Valid starting Expires Service principal - $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM - -16. List the files located at the defined server name or IP address: - - .. code-block:: console - - $ hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ - -17. Do one of the following: - - :: - - * If the list below is output, continue with Step 18. - - :: - - * If the list is not output, verify that your environment has been set up correctly. - -If any of the following are empty, verify that you followed :ref:`Step 6 <step_6>` in the **Configuring an HDFS Environment for the User sqream** section above correctly: - - .. code-block:: console - - $ echo $JAVA_HOME - $ echo $SQREAM_HOME - $ echo $CLASSPATH - $ echo $HADOOP_COMMON_LIB_NATIVE_DIR - $ echo $LD_LIBRARY_PATH - $ echo $PATH - -18. Verify that you copied the correct keytab file. - - :: - -19. Review this procedure to verify that you have followed each step. - -:ref:`Back to top <back_to_top_hdfs>` \ No newline at end of file diff --git a/operational_guides/s3.rst b/operational_guides/s3.rst deleted file mode 100644 index 5e4f8b264..000000000 --- a/operational_guides/s3.rst +++ /dev/null @@ -1,129 +0,0 @@ -.. _s3: - -*********************** -Inserting Data Using Amazon S3 -*********************** -SQream uses a native S3 connector for directly inserting data from a number of external sources directly into SQream. This is done using the ``s3://`` URI to specify an external file path on an S3 bucket. Your files can be saved in CSV or columnar format, such as Parquet and ORC, and your file names can include wildcard characters. - -The **Amazon S3** page describes the following topics: - -.. contents:: - :local: - :depth: 1 - -Configuring Amazon S3 -============================== -Any database host with access to S3 endpoints can access S3 without any configuration. To read files from an S3 bucket, the database must have listable files. - -Setting the S3 URI Format -=============== -With S3, specify a location for a file (or files) when using :ref:`copy_from` or :ref:`external_tables`. - -The following is an example of the general S3 syntax: - -.. code-block:: console - - s3://bucket_name/path - -Authenticating Users -================= - -SQream supports ``AWS ID`` and ``AWS SECRET`` authentication. These should be specified when executing a statement. - -Examples -========== -You can use a foreign table to stage data from S3 before loading from CSV, Parquet, or ORC files. - -This section includes the following examples: - -.. contents:: - :local: - :depth: 1 - -Planning for Data Staging --------------------------------- -The examples in this section are based on the CSV file shown in the following table: - -.. csv-table:: nba-t10 - :file: ../_static/samples/nba-t10.csv - :widths: auto - :header-rows: 1 - -This CSV file is stored on Amazon S3, and this bucket is public and listable. To create a matching ``CREATE FOREIGN TABLE`` statement you can make a record of your source file's structure and use it to reproduce a corresponding foreign table, as shown in the following section. - -Creating a Foreign Table ------------------------------ -Based on the source file's structure above, you can create a foreign table with the structure you want and point it to your file, as shown in the following example: - -.. code-block:: postgres - - CREATE FOREIGN TABLE nba - ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float - ) - WRAPPER csv_fdw - OPTIONS - ( - LOCATION = 's3://sqream-demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n' -- DOS delimited file - ) - ; - -.. note:: In the example above the file format is CSV and is stored as an S3 object. If your file has an HDFS path, you must change the URI accordingly. Note that the record delimiter is a DOS newline (``\r\n``). - -For more information, see the following: - -* **Creating a foreign table** - see :ref:`creating a foreign table<create_foreign_table>`. -* **Using SQream in an HDFS environment** - see :ref:`hdfs`. - -Querying Foreign Tables ------------------------------- -The following shows the data located in the foreign table: - -.. code-block:: psql - - t=> SELECT * FROM nba LIMIT 10; - name | team | number | position | age | height | weight | college | salary - --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- - Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 - Jae Crowder | Boston Celtics | 99 | SF | 25 | 6-6 | 235 | Marquette | 6796117 - John Holland | Boston Celtics | 30 | SG | 27 | 6-5 | 205 | Boston University | - R.J. Hunter | Boston Celtics | 28 | SG | 22 | 6-5 | 185 | Georgia State | 1148640 - Jonas Jerebko | Boston Celtics | 8 | PF | 29 | 6-10 | 231 | | 5000000 - Amir Johnson | Boston Celtics | 90 | PF | 29 | 6-9 | 240 | | 12000000 - Jordan Mickey | Boston Celtics | 55 | PF | 21 | 6-8 | 235 | LSU | 1170960 - Kelly Olynyk | Boston Celtics | 41 | C | 25 | 7-0 | 238 | Gonzaga | 2165160 - Terry Rozier | Boston Celtics | 12 | PG | 22 | 6-2 | 190 | Louisville | 1824360 - Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 - -Bulk Loading a File from a Public S3 Bucket ----------------------------------------------- -Youc an use the ``COPY FROM`` command to load data without staging it first. - -.. note:: The bucket must be publicly available and objects can be listed. - -The following is an example of bulk loading a file from a public S3 bucket: - -.. code-block:: postgres - - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; - -For more information on the ``COPY FROM`` command, see :ref:`copy_from`. - -Loading Files from an Authenticated S3 Bucket ---------------------------------------------------- -The following is an example of loading fles from an authenticated S3 bucket: - -.. code-block:: postgres - - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' - AWS_ID '12345678' - AWS_SECRET 'super_secretive_secret'; \ No newline at end of file From 10161e77ae95c3a34ee7ad31c630cc821eede8a8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Apr 2024 15:49:15 +0300 Subject: [PATCH 1302/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index b74ae2e76..8464885dd 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -49,10 +49,7 @@ If any doubt arises, consult the documentation for your server or your hardware - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. * - **Intel Turbo Boost** - **Enabled** - - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. * - **Intel Virtualization Technology** (VT-d) - **Disable** - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. From 8ac4eebc039ea6fd16c0133e85db5c3072c3a113 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Apr 2024 16:13:32 +0300 Subject: [PATCH 1303/1892] Update recommended_pre-installation_configurations.rst --- .../recommended_pre-installation_configurations.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index 8464885dd..da31ee5fe 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -4,16 +4,16 @@ Pre-Installation Configuration ****************************** -Before installing SQreamDB, it is recommended that you to tune your system for better performance and stability. +Before installing SQreamDB, it is essential that you to tune your system for better performance and stability. .. contents:: :local: :depth: 1 -Recommended Basic Input/Output System Settings -============================================== +Basic Input/Output System Settings +================================== -The first step when setting your pre-installation configurations is to use the recommended basic input/output system (BIOS) settings. +The first step when setting your pre-installation configurations is to use the basic input/output system (BIOS) settings. The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. From b3e99516ce8e2475cf49fe3407a5e8b4f2aea45f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 08:11:23 +0300 Subject: [PATCH 1304/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 7272cd8d2..8fa0ee577 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -493,6 +493,12 @@ Revoke permissions on specific objects (table, view, foreign table, or catalog) .. code-block:: postgres REVOKE SELECT, INSERT, DELETE, DDL, UPDATE ON TABLE schema_name.table_name FROM role_name; + +Revoke execute function permission from a role: + +.. code-block:: postgres + + REVOKE EXECUTE ON FUNCTION function_name FROM role_name; Revoke column-level permissions from a role: From 594e3eb96e61f0c1c19510b809a4e1bce3427376 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:02:16 +0300 Subject: [PATCH 1305/1892] Linear Regression --- operational_guides/index.rst | 1 + operational_guides/linear_regression.rst | 103 +++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 operational_guides/linear_regression.rst diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 9bbb4530d..3426caba5 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -24,4 +24,5 @@ This section summarizes the following operational guides: security saved_queries optimization_best_practices + linear_regression \ No newline at end of file diff --git a/operational_guides/linear_regression.rst b/operational_guides/linear_regression.rst new file mode 100644 index 000000000..62d1564d2 --- /dev/null +++ b/operational_guides/linear_regression.rst @@ -0,0 +1,103 @@ +.. _linear_regression: + +*********************** +In-DB Linear Regression +*********************** + +Linear regression is a fundamental component of the data science pipeline, used to model relationships between variables and make predictions based on observed data. + +SQreamDB supports data preparation and standardization, data training, and inference using data stored in and outside SQreamDB, providing a comprehensive platform for conducting end-to-end data analysis and machine learning tasks. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +* Python version + +* SQreamDB :ref:`JDBC connector<java_jdbc>` version + +* SQDB version + +* Missing data is not supported + +Parameters +---------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Default + - Description + * - Tolerance + - ``1e-4`` + - Tolerance determines when to stop training based on the improvement in model performance. If the improvement falls below the tolerance threshold, training stops early. + * - Label Index + - ``0`` + - Label index identifies the position of the target variable (dependent variable) within the dataset, crucial for training a linear regression model. + * - Max Number of Epochs + - ``1500`` + - Max number of epochs sets the limit on how many times the training algorithm iterates over the dataset during model training, helping control training duration and complexity. + +Importing Python Libraries +========================== + +.. code-block:: python + + df = session.table('customers') + .join('orders',on='customer_id') + .filter('active') + .to_pandas() + +Data Preparation +================ + +Missing data is not supported. + +* All data, including labels and features, should be stored in the same table. + +* Ensure that feature values (X) are within the same range. If not, consider normalizing or standardizing the features (X) separately for both training and testing datasets. + +.. _normalization: + +Normalization (Standardization) +------------------------------- + +Centering and scaling should be done independently on each feature by computing the relevant statistics on the samples in the training set. + +We suggest standardizing features by removing the mean and scaling to unit variance. The standard score of a sample :math:`x` is calculated as :math:`z = x - \frac{u}{s}`, where: + +* :math:`u` is the mean of the training samples + +* :math:`s` is the standard deviation of the training samples + +Training Data +============= + +There is no need to export data out of SQreamDB for the training process. + +.. code-block:: + + def train(data): + model = sk.LinearRegression() + X,y = df #... + X_train, X_test, y_train, y_test = split_train_test(X,y) + model.fit(X_train,y_train) + + session.register('train_sp',train) + model = session.execute('train_sp', source_table='customers') + +Testing and Inference +===================== + +.. code-block:: python + + session.import_model('model0',model) + test_results = session.table('customers_test').predict('model0') + # compare test results and test ground truth... + prediction_results = session.sql('select *,predict(''model0'',*) from customers'); + From 7124f50057a2fdf25ac1693a127f8fa1a3b2036e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 15:16:47 +0300 Subject: [PATCH 1306/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 8fa0ee577..16a28fa2c 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -1,8 +1,8 @@ .. _access_control_permissions: -************** +*********** Permissions -************** +*********** SQreamDB’s primary permission object is a role. The role operates in a dual capacity as both a user and a group. As a user, a role may have permissions to execute operations like creating tables, querying data, and administering the database. The group attribute may be thought of as a membership. As a group, a role may extend its permissions to other roles defined as its group members. This becomes handy when privileged roles wish to extend their permissions and grant multiple permissions to multiple roles. The information about all system role permissions is stored in the metadata. From 5f8000b01b31cf46aaad2b23ec339fa67bc0498d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:09:39 +0300 Subject: [PATCH 1307/1892] recommended_pre-installation_configurations -> pre-installation_configurations --- ...eparing_your_machine_to_install_sqream.rst | 2 +- .../installing_and_launching_sqream.rst | 2 +- .../pre-installation_configurations.rst | 1213 +++++++++++++++++ ...mended_pre-installation_configurations.rst | 2 +- 4 files changed, 1216 insertions(+), 3 deletions(-) create mode 100644 installation_guides/pre-installation_configurations.rst diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index b8d807e66..432089fc0 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -32,5 +32,5 @@ To prepare your machine to install SQreamDB, do the following: * A SQreamDB license - Contact `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for your license key. For more information, see the following: -* :ref:`recommended_pre-installation_configurations` +* :ref:`pre-installation_configurations` * :ref:`hardware_guide` \ No newline at end of file diff --git a/installation_guides/installing_and_launching_sqream.rst b/installation_guides/installing_and_launching_sqream.rst index 990081cd7..506d8e814 100644 --- a/installation_guides/installing_and_launching_sqream.rst +++ b/installation_guides/installing_and_launching_sqream.rst @@ -10,7 +10,7 @@ The **Installing and Launching SQreamDB** page includes the following installati :maxdepth: 1 :glob: - recommended_pre-installation_configurations + pre-installation_configurations installing_sqream_with_binary installing_monit launching_sqream_with_monit \ No newline at end of file diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst new file mode 100644 index 000000000..9ad30faca --- /dev/null +++ b/installation_guides/pre-installation_configurations.rst @@ -0,0 +1,1213 @@ +.. _pre-installation_configurations: + +****************************** +Pre-Installation Configuration +****************************** + +Before installing SQreamDB, it is essential that you to tune your system for better performance and stability. + +.. contents:: + :local: + :depth: 1 + +Basic Input/Output System Settings +================================== + +The first step when setting your pre-installation configurations is to use the basic input/output system (BIOS) settings. + +The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. + +If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. + +.. list-table:: + :widths: 25 25 50 + :header-rows: 1 + + * - Item + - Setting + - Rationale + * - **Management console access** + - **Connected** + - Connection to Out-of-band (OOB) required to preserve continuous network uptime. + * - **All drives** + - **Connected and displayed on RAID interface** + - Prerequisite for cluster or OS installation. + * - **RAID volumes** + - **Configured according to project guidelines. Must be rebooted to take effect.** + - Clustered to increase logical volume and provide redundancy. + * - **Fan speed Thermal Configuration.** + - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. + - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. + * - **Power regulator or iDRAC power unit policy** + - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. + - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. + * - **System Profile**, **Power Profile**, or **Performance Profile** + - **High Performance** + - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. + * - **Power Cap Policy** or **Dynamic power capping** + - **Disabled** + - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. + * - **Intel Turbo Boost** + - **Enabled** + - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Logical Processor** + - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** + - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. + * - **Intel Virtualization Technology** (VT-d) + - **Disable** + - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. + * - **Processor C-States** (Minimum processor idle power core state) + - **Disable** + - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. + * - **HPe**: **Energy/Performance bias** + - **Maximum performance** + - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. + * - **HPe**: **DIMM voltage** + - **Optimized for Performance** + - Setting a higher voltage for DIMMs may increase performance. + * - **Memory Operating Mode** + - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** + - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQreamDB. + * - **HPe**: **Memory power savings mode** + - **Maximum performance** + - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. + * - **HPe ACPI SLIT** + - **Enabled** + - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. + * - **QPI Snoop** + - **Cluster on Die** or **Home Snoop** + - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. + +Installing the Operating System +================================ + +Before You Begin +------------------- + +* Your system must have at least 200 gigabytes of free space on the root ``/`` mount. + +* For a multi-node cluster, you must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. + +* Once the BIOS settings have been set, you must install the operating system. + +* A typical SQreamDB installation requires RHEL7.9/CentOS 7.9 or RHEL8.X (RHEL8.8 recommended) + +* Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. + +Installation +---------------- + +#. Select a language (English recommended). +#. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. + + Selecting the **Development Tools** group installs the following tools: + + * autoconf + * automake + * binutils + * bison + * flex + * gcc + * gcc-c++ + * gettext + * libtool + * make + * patch + * pkgconfig + * redhat-rpm-config + * rpm-build + * rpm-sign + +#. Continue the installation. +#. Set up the necessary drives and users as per the installation process. + + The OS shell is booted up. + +Configuring the Operating System +================================== + +When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. + +Creating a ``sqream`` User +---------------------------- + +**The sqream user must have the same UID and GID across all servers in your cluster.** + +If the ``sqream`` user does not have the same UID and GID across all servers and there is no critical data stored under ``/home/sqream``, it is recommended to delete the ``sqream`` user and sqream group from your servers. Subsequently, create new ones with the same ID, using the following command: + + .. code-block:: console + + sudo userdel sqream + sudo rm /var/spool/mail/sqream + +Before adding a user with a specific UID and GID, it is crucial to verify that such Ids do not already exist. + +The steps below guide you on creating a ``sqream`` user with an exemplary ID of ``1111``. + +1. Verify that a ``1111`` UID does not already exists: + + .. code-block:: console + + cat /etc/passwd |grep 1111 + +2. Verify that a ``1111`` GID does not already exists: + + .. code-block:: console + + cat /etc/group |grep 1111 + +3. Add a user with an identical UID on all cluster nodes: + + .. code-block:: console + + useradd -u 1111 sqream + +4. Add a ``sqream`` user to the ``wheel`` group. + + .. code-block:: console + + sudo usermod -aG wheel sqream + + You can remove the ``sqream`` user from the ``wheel`` group when the installation and configuration are complete: + + .. code-block:: console + + passwd sqream + +5. Log out and log back in as ``sqream``. + +6. If you deleted the ``sqream`` user and recreated it to have a new ID, you must change its ownership to ``/home/sqream`` in order to avoid permission errors. + + .. code-block:: console + + sudo chown -R sqream:sqream /home/sqream + +Setting Up A Locale +----------------------- + +SQreamDB enables you to set up a locale using your own location. To find out your current time-zone, run the ``timedatectl list-timezones`` command. + +1. Set the language of the locale: + + .. code-block:: console + + sudo localectl set-locale LANG=en_US.UTF-8 + +2. Set the time stamp (time and date) of the locale: + + .. code-block:: console + + sudo timedatectl set-timezone Asia/Jerusalem + +Installing Required Software +--------------------------------- + +.. contents:: + :local: + :depth: 1 + +Installing EPEL Repository +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**CentOS7/RHEL8** + + .. code-block:: console + + sudo yum install epel-release + +**RHEL7** + + .. code-block:: console + + sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + +**RHEL8** + + .. code-block:: console + + sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + +Enabling Additional Red Hat Repositories +""""""""""""""""""""""""""""""""""""""""" + +Enabling additional Red Hat repositories is essential to install the required packages in the subsequent procedures. + +**RHEL7** + + .. code-block:: console + + sudo subscription-manager repos --enable rhel-7-server-optional-rpms + +**RHEL8** + + .. code-block:: console + + sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms + sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms + sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms + +Installing Required Packages +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**RHEL7/CentOS7** + + .. code-block:: console + + sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel + +**RHEL8** + + .. code-block:: console + + sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo + +Installing Recommended Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**RHEL7/CentOS7** + + .. code-block:: console + + sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix + +**RHEL8** + + .. code-block:: console + + sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix + +Installing Python +^^^^^^^^^^^^^^^^^^^ + +**For SQreamDb version 4.3 or older, install Python 3.6.7.** + +1. Download the Python 3.6.7 source code tarball file from the following URL into the ``/home/sqream`` directory: + + .. code-block:: console + + wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz + +2. Extract the Python 3.6.7 source code into your current directory: + + .. code-block:: console + + tar -xf Python-3.6.7.tar.xz + +3. Navigate to the Python 3.6.7 directory: + + .. code-block:: console + + cd Python-3.6.7 + +4. Run the ``./configure`` script: + + .. code-block:: console + + ./configure --enable-loadable-sqlite-extensions + +5. Build the software: + + .. code-block:: console + + make -j30 + +6. Install the software: + + .. code-block:: console + + sudo make install + +7. Verify that Python 3.6.7 has been installed: + + .. code-block:: console + + python3 --version + +**For SQreamDB version 4.4 or newer, install Python 3.9.13.** + +1. Download the Python 3.9.13 source code tarball file from the following URL into the ``/home/sqream`` directory: + + .. code-block:: console + + wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz + +2. Extract the Python 3.9.13 source code into your current directory: + + .. code-block:: console + + tar -xf Python-3.9.13.tar.xz + +3. Navigate to the Python 3.9.13 directory: + + .. code-block:: console + + cd Python-3.9.13 + +4. Run the ``./configure`` script: + + .. code-block:: console + + ./configure --enable-loadable-sqlite-extensions + +5. Build the software: + + .. code-block:: console + + make -j30 + +6. Install the software: + + .. code-block:: console + + sudo make install + +7. Verify that Python 3.9.13 has been installed: + + .. code-block:: console + + python3 --version + +Installing NodeJS +^^^^^^^^^^^^^^^^^^ + +NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not, you can skip this step. + +1. Download the NodeJS source code tarball file from the following URL into the ``/home/sqream`` directory: + + .. code-block:: console + + wget https://nodejs.org/dist/v16.20.0/node-v16.20.0-linux-x64.tar.xz + tar -xf node-v16.20.0-linux-x64.tar.xz + +2. Move the node-v16.20.0-linux-x64 file to the */usr/local* directory. + + .. code-block:: console + + sudo mv node-v16.20.0-linux-x64 /usr/local + +3. Navigate to the ``/usr/bin/`` directory: + + .. code-block:: console + + cd /usr/bin + +4. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/node node`` directory: + + .. code-block:: console + + sudo ln -s ../local/node-v16.20.0-linux-x64//bin/node node + +5. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npm npm`` directory: + + .. code-block:: console + + sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npm npm + +6. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npx npx`` directory: + + .. code-block:: console + + sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npx npx + +7. Install the ``pm2`` process management: + + .. code-block:: console + + sudo npm install pm2 -g + +8. If installing the ``pm2`` process management fails, install it offline: + + a. On a machine with internet access, install the following: + + * nodejs + * npm + * pm2 + + b. Extract the pm2 module to the correct directory: + + .. code-block:: console + + cd /usr/local/node-v16.20.0-linux-x64/lib/node_modules + tar -czvf pm2_x86.tar.gz pm2 + + c. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. + + :: + + d. Move the ``pm2`` folder to the ``/usr/local/node-v16.20.0-linux-x64/lib/node_modules`` directory: + + .. code-block:: console + + sudo mv pm2 /usr/local/node-v16.20.0-linux-x64/lib/node_modules + + e. Navigate back to the ``/usr/bin`` directory: + + .. code-block:: console + + cd /usr/bin + + f. Create a symbolink to the ``pm2`` service: + + .. code-block:: console + + sudo ln -s /usr/local/node-v16.20.0-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 + + g. Verify that installation was successful without using ``sudo``: + + .. code-block:: console + + pm2 list + + h. Verify that the node versions for the above are correct: + + .. code-block:: console + + node --version + +Configuring the Network Time Protocol +-------------------------------------- + +This Network Time Protocol (NTP) configuration is intended for use on systems running RHEL7 and CentOS7 exclusively. + +If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. + +1. Install the NTP file. + + .. code-block:: console + + sudo yum install ntp + +2. Enable the **ntpd** program. + + .. code-block:: console + + sudo systemctl enable ntpd + +3. Start the **ntdp** program. + + .. code-block:: console + + sudo systemctl start ntpd + +4. Print a list of peers known to the server and a summary of their states. + + .. code-block:: console + + sudo ntpq -p + +Configuring the Network Time Protocol Server +-------------------------------------------- + +If your organization has a Network Time Protocol (NTP) server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled. + +1. Output your NTP server address and append ``/etc/ntpd.conf`` to the output: + + .. code-block:: console + + echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf + +2. Restart the service: + + .. code-block:: console + + sudo systemctl restart ntpd + +3. Check that synchronization is enabled: + + .. code-block:: console + + sudo timedatectl + + Checking that synchronization is enabled generates the following output: + + .. code-block:: console + + Local time: Sat 2019-10-12 17:26:13 EDT + Universal time: Sat 2019-10-12 21:26:13 UTC + RTC time: Sat 2019-10-12 21:26:13 + Time zone: America/New_York (EDT, -0400) + NTP enabled: yes + NTP synchronized: yes + RTC in local TZ: no + DST active: yes + Last DST change: DST began at + Sun 2019-03-10 01:59:59 EST + Sun 2019-03-10 03:00:00 EDT + Next DST change: DST ends (the clock jumps one hour backwards) at + Sun 2019-11-03 01:59:59 EDT + Sun 2019-11-03 01:00:00 EST + +Configuring Chrony for RHEL8 Only +---------------------------------- + +#. Start the Chrony service: + + .. code-block:: console + + sudo systemctl start chronyd + +#. Enable the Chrony service to start automatically at boot time: + + .. code-block:: + + sudo systemctl enable chronyd + +#. Check the status of the Chrony service: + + .. code-block:: + + sudo systemctl status chronyd + +Configuring the Server to Boot Without Linux GUI +---------------------------------------------------- + +We recommend that you configure your server to boot without a Linux GUI by running the following command: + + .. code-block:: console + + sudo systemctl set-default multi-user.target + +Running this command activates the **NO-UI** server mode. + +Configuring the Security Limits +-------------------------------- + +The security limits refer to the number of open files, processes, etc. + + .. code-block:: console + + sudo bash + + .. code-block:: console + + echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nroot soft nproc 1000000\nroot hard nproc 1000000\nroot soft nofile 1000000\nroot hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf + +Configuring the Kernel Parameters +--------------------------------- + +1. Insert a new line after each kernel parameter: + + .. code-block:: console + + echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf + +2. Check the maximum value of the ``fs.file``: + + .. code-block:: console + + sysctl -n fs.file-max + +3. **Only** if the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: + + .. code-block:: console + + echo "fs.file-max=2097152" >> /etc/sysctl.conf + +Configuring the Firewall +-------------------------- + +The example in this section shows the open ports for four ``sqreamd`` sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. + +The ports listed below are required, and the same logic applies to all additional SQreamDB Worker ports. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Port + - Use + * - 8080 + - UI port + * - 443 + - UI over HTTPS ( requires nginx installation ) + * - 3105 + - SqreamDB metadataserver service + * - 3108 + - SqreamDB serverpicker service + * - 3109 + - SqreamDB serverpicker service over ssl + * - 5000 + - SqreamDB first worker default port + * - 5100 + - SqreamDB first worker over ssl default port + * - 5001 + - SqreamDB second worker default port + * - 5101 + - SqreamDB second worker over ssl default port + +1. Start the service and enable FirewallID on boot: + + .. code-block:: console + + systemctl start firewalld + +2. Add the following ports to the permanent firewall: + + .. code-block:: console + + firewall-cmd --zone=public --permanent --add-port=8080/tcp + firewall-cmd --zone=public --permanent --add-port=3105/tcp + firewall-cmd --zone=public --permanent --add-port=3108/tcp + firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp + firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp + firewall-cmd --permanent --list-all + +3. Reload the firewall: + + .. code-block:: console + + firewall-cmd --reload + +4. Enable FirewallID on boot: + + .. code-block:: console + + systemctl enable firewalld + + If you do not need the firewall, you can disable it: + + .. code-block:: console + + sudo systemctl stop firewalld + sudo systemctl disable firewalld + +Disabling SELinux +------------------- + +Disabling SELinux is a recommended action. + +1. Show the status of ``selinux``: + + .. code-block:: console + + sudo sestatus + +2. If the output is not ``disabled``, edit the ``/etc/selinux/config`` file: + + .. code-block:: console + + sudo vim /etc/selinux/config + +3. Change ``SELINUX=enforcing`` to ``SELINUX=disabled``: + + The above changes will only take effect after rebooting the server. + + You can disable selinux immediately after rebooting the server by running the following command: + + .. code-block:: console + + sudo setenforce 0 + +Configuring the ``/etc/hosts`` File +------------------------------------ + +1. Edit the ``/etc/hosts`` file: + + .. code-block:: console + + sudo vim /etc/hosts + +2. Call your local host: + + .. code-block:: console + + 127.0.0.1 localhost + <server1 ip> <server_name> + <server2 ip> <server_name> + +Installing the NVIDIA CUDA Driver +================================== + +After configuring your operating system, you must install the NVIDIA CUDA driver. + +.. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. + +Before You Begin +^^^^^^^^^^^^^^^^^ + +1. Verify that the NVIDIA card has been installed and is detected by the system: + + .. code-block:: console + + lspci | grep -i nvidia + +2. Verify that ``gcc`` has been installed: + + .. code-block:: console + + gcc --version + +3. If ``gcc`` has not been installed, install it for RHEL or CentOS: + + .. code-block:: console + + sudo yum install -y gcc + +Updating the Kernel Headers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. Update the kernel headers on RHEL or CentOS: + + .. code-block:: console + + sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) + +2. Make sure kernel-devel and kernel-headers match installed kernel: + + .. code-block:: console + + uname -r + rpm -qa |grep kernel-devel-$(uname -r) + rpm -qa |grep kernel-headers-$(uname -r) + +Disabling Nouveau +^^^^^^^^^^^^^^^^^^^ + +Disable Nouveau, which is the default operating system driver. + +1. Check if the Nouveau driver has been loaded: + + .. code-block:: console + + lsmod | grep nouveau + + If the Nouveau driver has been loaded, the command above generates output. If the Nouveau driver has not been loaded, you may skip step 2 and 3. + +2. Blacklist the Nouveau driver to disable it: + + .. code-block:: console + + cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf + blacklist nouveau + options nouveau modeset=0 + EOF + +3. Regenerate the kernel ``initramfs`` directory set: + + a. Modify the ``initramfs`` directory set: + + .. code-block:: console + + sudo dracut --force + + b. Reboot the server: + + .. code-block:: console + + sudo reboot + +Installing the CUDA Driver +---------------------------- + +.. contents:: + :local: + :depth: 1 + +The current recommendation is for CUDA 12.3.2. + +For A100 GPU and other A series GPUs, you must install CUDA driver **11.4.3** or a later version. + +For H100 GPU and other H series GPUs, you must install CUDA driver **11.8** or a later version. + +For L40S GPU and other L series GPUs, you must install CUDA driver **12.0** or a later version. + +For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. + +Installing the CUDA Driver from the Repository +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Installing the CUDA driver from the Repository is the recommended installation method. + +1. Install the CUDA dependencies for one of the following operating systems: + + * For RHEL7: + + .. code-block:: console + + sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm + + * For RHEL8: + + .. code-block:: console + + sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm + + * For CentOS: + + .. code-block:: console + + sudo yum install epel-release + +2. (Optional) Install the CUDA dependencies from the ``epel`` repository: + + .. code-block:: console + + sudo yum install dkms libvdpau + + Installing the CUDA depedendencies from the ``epel`` repository is only required for installing ``runfile``. + +3. Download and install the required local repository: + + * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + + .. code-block:: console + + wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + + .. code-block:: console + + sudo yum clean all + sudo yum -y install nvidia-driver-latest-dkms + + * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** + + .. code-block:: console + + wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm + + * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + + .. code-block:: console + + wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + + .. code-block:: console + + sudo dnf clean all + sudo dnf -y module install nvidia-driver:latest-dkms + +Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 + + * **IBM Power9 - CUDA 10.1 for RHEL7:** + + .. code-block:: console + + wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm + +If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. + +Tuning Up NVIDIA Performance +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following procedures exclusively relate to Intel. + +.. contents:: + :local: + :depth: 1 + +.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. + +Tune Up NVIDIA Performance when Driver Installed from the Repository +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +1. Check the service status: + + .. code-block:: console + + sudo systemctl status nvidia-persistenced + + If the service exists, it will be stopped by default. + +2. Start the service: + + .. code-block:: console + + sudo systemctl start nvidia-persistenced + +3. Verify that no errors have occurred: + + .. code-block:: console + + sudo systemctl status nvidia-persistenced + +4. Enable the service to start up on boot: + + .. code-block:: console + + sudo systemctl enable nvidia-persistenced + +5. For **H100/A100**, add the following lines: + + .. code-block:: console + + nvidia-persistenced + +6. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: + + .. code-block:: console + + nvidia-smi + + + +Tune Up NVIDIA Performance when Driver Installed from the Runfile +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +1. Change the permissions on the ``rc.local`` file to ``executable``: + + .. code-block:: console + + sudo chmod +x /etc/rc.local + +2. Edit the ``/etc/yum.repos.d/cuda-10-1-local.repo`` file: + + .. code-block:: console + + sudo vim /etc/rc.local + +3. Add the following lines: + + * **For H100/A100**: + + .. code-block:: console + + nvidia-persistenced + + * **For IBM (mandatory)**: + + .. code-block:: console + + sudo systemctl start nvidia-persistenced + sudo systemctl enable nvidia-persistenced + + * **For K80**: + + .. code-block:: console + + nvidia-persistenced + nvidia-smi -pm 1 + nvidia-smi -acp 0 + nvidia-smi --auto-boost-permission=0 + nvidia-smi --auto-boost-default=0 + +4. Reboot the server and run the ``NVIDIA System Management Interface (NVIDIA SMI)``: + + .. code-block:: console + + nvidia-smi + + + +Enabling Core Dumps +==================== + +While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB support to be able to analyze your core dumps, they must be ``gdb`` compatible. + +.. contents:: + :local: + :depth: 1 + +Checking the ``abrtd`` Status +---------------------------- + +1. Check if ``abrtd`` is running: + + .. code-block:: console + + sudo ps -ef |grep abrt + +2. If **abrtd** is running, stop it: + + .. code-block:: console + + for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done + +Setting the Limits +-------------------- + +1. Set the limits: + + .. code-block:: console + + ulimit -c + +2. If the output is ``0``, add the following lines to the ``/etc/security/limits.conf`` file: + + .. code-block:: console + + * soft core unlimited + * hard core unlimited + +3. To apply the limit changes, log out and log back in. + +Creating the Core Dump Directory +----------------------------------- + +Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the ``/tmp/core_dumps`` directory. If necessary, replace path according to your own environment and disk space. + +1. Make the ``/tmp/core_dumps`` directory: + + .. code-block:: console + + mkdir /tmp/core_dumps + +2. Set the ownership of the ``/tmp/core_dumps`` directory: + + .. code-block:: console + + sudo chown sqream.sqream /tmp/core_dumps + +3. Grant read, write, and execute permissions to all users: + + .. code-block:: console + + sudo chmod -R 777 /tmp/core_dumps + + +Setting the Output Directory on the ``/etc/sysctl.conf`` File +------------------------------------------------------------- + +1. Open the ``/etc/sysctl.conf`` file in the Vim text editor: + + .. code-block:: console + + sudo vim /etc/sysctl.conf + +2. Add the following to the bottom of the file: + + .. code-block:: console + + kernel.core_uses_pid = 1 + kernel.core_pattern = /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + fs.suid_dumpable = 2 + +3. To apply the changes without rebooting the server, run the following: + + .. code-block:: console + + sudo sysctl -p + +4. Check that the core output directory points to the following: + + .. code-block:: console + + sudo cat /proc/sys/kernel/core_pattern + + The following shows the correct generated output: + + .. code-block:: console + + /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t + +Verifying that the Core Dumps Work +--------------------------------------------------- + +You can verify that the core dumps work only after installing and running SQreamDB. This causes the server to crash and a new ``core.xxx`` file to be included in the folder that is written in ``/etc/sysctl.conf``. + +1. Stop and restart all SQreamDB services. + + :: + +2. Connect to SQreamDB with ClientCmd and run the following command: + + .. code-block:: console + + select abort_server(); + +Verify Your SQreamDB Installation +------------------------------------ + +1. Verify that the ``sqream`` user exists and has the same ID on all cluster servers. + + .. code-block:: console + + id sqream + +2. please verify that the storage is mounted on all cluster servers. + + .. code-block:: console + + mount + +3. make sure that the driver is properly installed. + + .. code-block:: console + + nvidia-smi + +4. Verify that the kernel file-handles allocation is greater than or equal to ``2097152``: + + .. code-block:: console + + sysctl -n fs.file-max + +5. Verify limits (run this command as a ``sqream`` user): + + .. code-block:: console + + ulimit -c -u -n + + Desired output: + core file size (blocks, -c) unlimited + max user processes (-u) 1000000 + open files (-n) 1000000 + +Troubleshooting Core Dumping +------------------------------ + +This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. + +1. Reboot the server. + + :: + +2. Verify that you have folder permissions: + + .. code-block:: console + + sudo chmod -R 777 /tmp/core_dumps + +3. Verify that the limits have been set correctly: + + .. code-block:: console + + ulimit -c + + If all parameters have been configured correctly, the correct output is: + + .. code-block:: console + + core file size (blocks, -c) unlimited + +4. If all parameters have been configured correctly, but running ``ulimit -c`` outputs ``0``, run the following: + + .. code-block:: console + + sudo vim /etc/profile + +5. Search for the following line and disable it using the ``#`` symbol: + + .. code-block:: console + + ulimit -S -c 0 > /dev/null 2>&1 + +6. Log out and log back in. + + :: + +7. Run the ``ulimit -c`` command: + + .. code-block:: console + + ulimit -a + +8. If the line is not found in ``/etc/profile``, do the following: + + a. Run the following command: + + .. code-block:: console + + sudo vim /etc/init.d/functions + + b. Search for the following line disable it using the ``#`` symbol and reboot the server. + + .. code-block:: console + + ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst index da31ee5fe..516299762 100644 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ b/installation_guides/recommended_pre-installation_configurations.rst @@ -1,4 +1,4 @@ -.. _recommended_pre-installation_configurations: +.. _pre-installation_configurations: ****************************** Pre-Installation Configuration From a66c4ae2cfd41cf66c0893df43401328f534df27 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:19:41 +0300 Subject: [PATCH 1308/1892] Delete recommended_pre-installation_configurations.rst --- ...mended_pre-installation_configurations.rst | 1213 ----------------- 1 file changed, 1213 deletions(-) delete mode 100644 installation_guides/recommended_pre-installation_configurations.rst diff --git a/installation_guides/recommended_pre-installation_configurations.rst b/installation_guides/recommended_pre-installation_configurations.rst deleted file mode 100644 index 516299762..000000000 --- a/installation_guides/recommended_pre-installation_configurations.rst +++ /dev/null @@ -1,1213 +0,0 @@ -.. _pre-installation_configurations: - -****************************** -Pre-Installation Configuration -****************************** - -Before installing SQreamDB, it is essential that you to tune your system for better performance and stability. - -.. contents:: - :local: - :depth: 1 - -Basic Input/Output System Settings -================================== - -The first step when setting your pre-installation configurations is to use the basic input/output system (BIOS) settings. - -The BIOS settings may have a variety of names, or may not exist on your system. Each system vendor has a different set of settings and variables. It is safe to skip any and all of the configuration steps, but this may impact performance. - -If any doubt arises, consult the documentation for your server or your hardware vendor for the correct way to apply the settings. - -.. list-table:: - :widths: 25 25 50 - :header-rows: 1 - - * - Item - - Setting - - Rationale - * - **Management console access** - - **Connected** - - Connection to Out-of-band (OOB) required to preserve continuous network uptime. - * - **All drives** - - **Connected and displayed on RAID interface** - - Prerequisite for cluster or OS installation. - * - **RAID volumes** - - **Configured according to project guidelines. Must be rebooted to take effect.** - - Clustered to increase logical volume and provide redundancy. - * - **Fan speed Thermal Configuration.** - - Dell fan speed: **High Maximum**. Specified minimum setting: **60**. HPe thermal configuration: **Increased cooling**. - - NVIDIA Tesla GPUs are passively cooled and require high airflow to operate at full performance. - * - **Power regulator or iDRAC power unit policy** - - HPe: **HP static high performance** mode enabled. Dell: **iDRAC power unit policy** (power cap policy) disabled. - - Other power profiles (such as "balanced") throttle the CPU and diminishes performance. Throttling may also cause GPU failure. - * - **System Profile**, **Power Profile**, or **Performance Profile** - - **High Performance** - - The Performance profile provides potentially increased performance by maximizing processor frequency, and the disabling certain power saving features such as C-states. Use this setting for environments that are not sensitive to power consumption. - * - **Power Cap Policy** or **Dynamic power capping** - - **Disabled** - - Other power profiles (like "balanced") throttle the CPU and may diminish performance or cause GPU failure. This setting may appear together with the above (Power profile or Power regulator). This setting allows disabling system ROM power calibration during the boot process. Power regulator settings are named differently in BIOS and iLO/iDRAC. - * - **Intel Turbo Boost** - - **Enabled** - - Intel Turbo Boost enables overclocking the processor to boost CPU-bound operation performance. Overclocking may risk computational jitter due to changes in the processor's turbo frequency. This causes brief pauses in processor operation, introducing uncertainty into application processing time. Turbo operation is a function of power consumption, processor temperature, and the number of active cores. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Logical Processor** - - **HPe**: Enable **Hyperthreading** **Dell**: Enable **Logical Processor** - - Hyperthreading doubles the amount of logical processors, which may improve performance by ~5-10% for CPU-bound operations. - * - **Intel Virtualization Technology** (VT-d) - - **Disable** - - VT-d is optimal for running VMs. However, when running Linux natively, disabling VT-d boosts performance by up to 10%. - * - **Processor C-States** (Minimum processor idle power core state) - - **Disable** - - Processor C-States reduce server power when the system is in an idle state. This causes slower cold-starts when the system transitions from an idle to a load state, and may reduce query performance by up to 15%. - * - **HPe**: **Energy/Performance bias** - - **Maximum performance** - - Configures processor sub-systems for high-performance and low-latency. Other power profiles (like "balanced") throttle the CPU and may diminish performance. Use this setting for environments that are not sensitive to power consumption. - * - **HPe**: **DIMM voltage** - - **Optimized for Performance** - - Setting a higher voltage for DIMMs may increase performance. - * - **Memory Operating Mode** - - **Optimizer Mode**, **Disable Node Interleaving**, **Auto Memory Operating Voltage** - - Memory Operating Mode is tuned for performance in **Optimizer** mode. Other modes may improve reliability, but reduce performance. **Node Interleaving** should be disabled because enabling it interleaves the memory between memory nodes, which harms NUMA-aware applications such as SQreamDB. - * - **HPe**: **Memory power savings mode** - - **Maximum performance** - - This setting configures several memory parameters to optimize the performance of memory sub-systems. The default setting is **Balanced**. - * - **HPe ACPI SLIT** - - **Enabled** - - ACPI SLIT sets the relative access times between processors and memory and I/O sub-systems. ACPI SLIT enables operating systems to use this data to improve performance by more efficiently allocating resources and workloads. - * - **QPI Snoop** - - **Cluster on Die** or **Home Snoop** - - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. - -Installing the Operating System -================================ - -Before You Begin -------------------- - -* Your system must have at least 200 gigabytes of free space on the root ``/`` mount. - -* For a multi-node cluster, you must have external shared storage provided by systems like General Parallel File System (GPFS), Weka, or VAST. - -* Once the BIOS settings have been set, you must install the operating system. - -* A typical SQreamDB installation requires RHEL7.9/CentOS 7.9 or RHEL8.X (RHEL8.8 recommended) - -* Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. - -Installation ----------------- - -#. Select a language (English recommended). -#. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. - - Selecting the **Development Tools** group installs the following tools: - - * autoconf - * automake - * binutils - * bison - * flex - * gcc - * gcc-c++ - * gettext - * libtool - * make - * patch - * pkgconfig - * redhat-rpm-config - * rpm-build - * rpm-sign - -#. Continue the installation. -#. Set up the necessary drives and users as per the installation process. - - The OS shell is booted up. - -Configuring the Operating System -================================== - -When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. - -Creating a ``sqream`` User ----------------------------- - -**The sqream user must have the same UID and GID across all servers in your cluster.** - -If the ``sqream`` user does not have the same UID and GID across all servers and there is no critical data stored under ``/home/sqream``, it is recommended to delete the ``sqream`` user and sqream group from your servers. Subsequently, create new ones with the same ID, using the following command: - - .. code-block:: console - - sudo userdel sqream - sudo rm /var/spool/mail/sqream - -Before adding a user with a specific UID and GID, it is crucial to verify that such Ids do not already exist. - -The steps below guide you on creating a ``sqream`` user with an exemplary ID of ``1111``. - -1. Verify that a ``1111`` UID does not already exists: - - .. code-block:: console - - cat /etc/passwd |grep 1111 - -2. Verify that a ``1111`` GID does not already exists: - - .. code-block:: console - - cat /etc/group |grep 1111 - -3. Add a user with an identical UID on all cluster nodes: - - .. code-block:: console - - useradd -u 1111 sqream - -4. Add a ``sqream`` user to the ``wheel`` group. - - .. code-block:: console - - sudo usermod -aG wheel sqream - - You can remove the ``sqream`` user from the ``wheel`` group when the installation and configuration are complete: - - .. code-block:: console - - passwd sqream - -5. Log out and log back in as ``sqream``. - -6. If you deleted the ``sqream`` user and recreated it to have a new ID, you must change its ownership to ``/home/sqream`` in order to avoid permission errors. - - .. code-block:: console - - sudo chown -R sqream:sqream /home/sqream - -Setting Up A Locale ------------------------ - -SQreamDB enables you to set up a locale using your own location. To find out your current time-zone, run the ``timedatectl list-timezones`` command. - -1. Set the language of the locale: - - .. code-block:: console - - sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console - - sudo timedatectl set-timezone Asia/Jerusalem - -Installing Required Software ---------------------------------- - -.. contents:: - :local: - :depth: 1 - -Installing EPEL Repository -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -**CentOS7/RHEL8** - - .. code-block:: console - - sudo yum install epel-release - -**RHEL7** - - .. code-block:: console - - sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - -**RHEL8** - - .. code-block:: console - - sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - -Enabling Additional Red Hat Repositories -""""""""""""""""""""""""""""""""""""""""" - -Enabling additional Red Hat repositories is essential to install the required packages in the subsequent procedures. - -**RHEL7** - - .. code-block:: console - - sudo subscription-manager repos --enable rhel-7-server-optional-rpms - -**RHEL8** - - .. code-block:: console - - sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms - sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms - sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms - -Installing Required Packages -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -**RHEL7/CentOS7** - - .. code-block:: console - - sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel - -**RHEL8** - - .. code-block:: console - - sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo - -Installing Recommended Tools -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -**RHEL7/CentOS7** - - .. code-block:: console - - sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - -**RHEL8** - - .. code-block:: console - - sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix - -Installing Python -^^^^^^^^^^^^^^^^^^^ - -**For SQreamDb version 4.3 or older, install Python 3.6.7.** - -1. Download the Python 3.6.7 source code tarball file from the following URL into the ``/home/sqream`` directory: - - .. code-block:: console - - wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - -2. Extract the Python 3.6.7 source code into your current directory: - - .. code-block:: console - - tar -xf Python-3.6.7.tar.xz - -3. Navigate to the Python 3.6.7 directory: - - .. code-block:: console - - cd Python-3.6.7 - -4. Run the ``./configure`` script: - - .. code-block:: console - - ./configure --enable-loadable-sqlite-extensions - -5. Build the software: - - .. code-block:: console - - make -j30 - -6. Install the software: - - .. code-block:: console - - sudo make install - -7. Verify that Python 3.6.7 has been installed: - - .. code-block:: console - - python3 --version - -**For SQreamDB version 4.4 or newer, install Python 3.9.13.** - -1. Download the Python 3.9.13 source code tarball file from the following URL into the ``/home/sqream`` directory: - - .. code-block:: console - - wget https://www.python.org/ftp/python/3.9.13/Python-3.9.13.tar.xz - -2. Extract the Python 3.9.13 source code into your current directory: - - .. code-block:: console - - tar -xf Python-3.9.13.tar.xz - -3. Navigate to the Python 3.9.13 directory: - - .. code-block:: console - - cd Python-3.9.13 - -4. Run the ``./configure`` script: - - .. code-block:: console - - ./configure --enable-loadable-sqlite-extensions - -5. Build the software: - - .. code-block:: console - - make -j30 - -6. Install the software: - - .. code-block:: console - - sudo make install - -7. Verify that Python 3.9.13 has been installed: - - .. code-block:: console - - python3 --version - -Installing NodeJS -^^^^^^^^^^^^^^^^^^ - -NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not, you can skip this step. - -1. Download the NodeJS source code tarball file from the following URL into the ``/home/sqream`` directory: - - .. code-block:: console - - wget https://nodejs.org/dist/v16.20.0/node-v16.20.0-linux-x64.tar.xz - tar -xf node-v16.20.0-linux-x64.tar.xz - -2. Move the node-v16.20.0-linux-x64 file to the */usr/local* directory. - - .. code-block:: console - - sudo mv node-v16.20.0-linux-x64 /usr/local - -3. Navigate to the ``/usr/bin/`` directory: - - .. code-block:: console - - cd /usr/bin - -4. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/node node`` directory: - - .. code-block:: console - - sudo ln -s ../local/node-v16.20.0-linux-x64//bin/node node - -5. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npm npm`` directory: - - .. code-block:: console - - sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npm npm - -6. Create a symbolic link to the ``/local/node-v16.20.0-linux-x64/bin/npx npx`` directory: - - .. code-block:: console - - sudo ln -s ../local/node-v16.20.0-linux-x64/bin/npx npx - -7. Install the ``pm2`` process management: - - .. code-block:: console - - sudo npm install pm2 -g - -8. If installing the ``pm2`` process management fails, install it offline: - - a. On a machine with internet access, install the following: - - * nodejs - * npm - * pm2 - - b. Extract the pm2 module to the correct directory: - - .. code-block:: console - - cd /usr/local/node-v16.20.0-linux-x64/lib/node_modules - tar -czvf pm2_x86.tar.gz pm2 - - c. Copy the ``pm2_x86.tar.gz`` file to a server without access to the internet and extract it. - - :: - - d. Move the ``pm2`` folder to the ``/usr/local/node-v16.20.0-linux-x64/lib/node_modules`` directory: - - .. code-block:: console - - sudo mv pm2 /usr/local/node-v16.20.0-linux-x64/lib/node_modules - - e. Navigate back to the ``/usr/bin`` directory: - - .. code-block:: console - - cd /usr/bin - - f. Create a symbolink to the ``pm2`` service: - - .. code-block:: console - - sudo ln -s /usr/local/node-v16.20.0-linux-x64/lib/node_modules/pm2/bin/pm2 pm2 - - g. Verify that installation was successful without using ``sudo``: - - .. code-block:: console - - pm2 list - - h. Verify that the node versions for the above are correct: - - .. code-block:: console - - node --version - -Configuring the Network Time Protocol --------------------------------------- - -This Network Time Protocol (NTP) configuration is intended for use on systems running RHEL7 and CentOS7 exclusively. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. - -1. Install the NTP file. - - .. code-block:: console - - sudo yum install ntp - -2. Enable the **ntpd** program. - - .. code-block:: console - - sudo systemctl enable ntpd - -3. Start the **ntdp** program. - - .. code-block:: console - - sudo systemctl start ntpd - -4. Print a list of peers known to the server and a summary of their states. - - .. code-block:: console - - sudo ntpq -p - -Configuring the Network Time Protocol Server --------------------------------------------- - -If your organization has a Network Time Protocol (NTP) server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled. - -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the output: - - .. code-block:: console - - echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf - -2. Restart the service: - - .. code-block:: console - - sudo systemctl restart ntpd - -3. Check that synchronization is enabled: - - .. code-block:: console - - sudo timedatectl - - Checking that synchronization is enabled generates the following output: - - .. code-block:: console - - Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST - -Configuring Chrony for RHEL8 Only ----------------------------------- - -#. Start the Chrony service: - - .. code-block:: console - - sudo systemctl start chronyd - -#. Enable the Chrony service to start automatically at boot time: - - .. code-block:: - - sudo systemctl enable chronyd - -#. Check the status of the Chrony service: - - .. code-block:: - - sudo systemctl status chronyd - -Configuring the Server to Boot Without Linux GUI ----------------------------------------------------- - -We recommend that you configure your server to boot without a Linux GUI by running the following command: - - .. code-block:: console - - sudo systemctl set-default multi-user.target - -Running this command activates the **NO-UI** server mode. - -Configuring the Security Limits --------------------------------- - -The security limits refer to the number of open files, processes, etc. - - .. code-block:: console - - sudo bash - - .. code-block:: console - - echo -e "sqream soft nproc 1000000\nsqream hard nproc 1000000\nsqream soft nofile 1000000\nsqream hard nofile 1000000\nroot soft nproc 1000000\nroot hard nproc 1000000\nroot soft nofile 1000000\nroot hard nofile 1000000\nsqream soft core unlimited\nsqream hard core unlimited" >> /etc/security/limits.conf - -Configuring the Kernel Parameters ---------------------------------- - -1. Insert a new line after each kernel parameter: - - .. code-block:: console - - echo -e "vm.dirty_background_ratio = 5 \n vm.dirty_ratio = 10 \n vm.swappiness = 10 \n vm.vfs_cache_pressure = 200 \n vm.zone_reclaim_mode = 0 \n" >> /etc/sysctl.conf - -2. Check the maximum value of the ``fs.file``: - - .. code-block:: console - - sysctl -n fs.file-max - -3. **Only** if the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: - - .. code-block:: console - - echo "fs.file-max=2097152" >> /etc/sysctl.conf - -Configuring the Firewall --------------------------- - -The example in this section shows the open ports for four ``sqreamd`` sessions. If more than four are required, open the required ports as needed. Port 8080 in the example below is a new UI port. - -The ports listed below are required, and the same logic applies to all additional SQreamDB Worker ports. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Port - - Use - * - 8080 - - UI port - * - 443 - - UI over HTTPS ( requires nginx installation ) - * - 3105 - - SqreamDB metadataserver service - * - 3108 - - SqreamDB serverpicker service - * - 3109 - - SqreamDB serverpicker service over ssl - * - 5000 - - SqreamDB first worker default port - * - 5100 - - SqreamDB first worker over ssl default port - * - 5001 - - SqreamDB second worker default port - * - 5101 - - SqreamDB second worker over ssl default port - -1. Start the service and enable FirewallID on boot: - - .. code-block:: console - - systemctl start firewalld - -2. Add the following ports to the permanent firewall: - - .. code-block:: console - - firewall-cmd --zone=public --permanent --add-port=8080/tcp - firewall-cmd --zone=public --permanent --add-port=3105/tcp - firewall-cmd --zone=public --permanent --add-port=3108/tcp - firewall-cmd --zone=public --permanent --add-port=5000-5003/tcp - firewall-cmd --zone=public --permanent --add-port=5100-5103/tcp - firewall-cmd --permanent --list-all - -3. Reload the firewall: - - .. code-block:: console - - firewall-cmd --reload - -4. Enable FirewallID on boot: - - .. code-block:: console - - systemctl enable firewalld - - If you do not need the firewall, you can disable it: - - .. code-block:: console - - sudo systemctl stop firewalld - sudo systemctl disable firewalld - -Disabling SELinux -------------------- - -Disabling SELinux is a recommended action. - -1. Show the status of ``selinux``: - - .. code-block:: console - - sudo sestatus - -2. If the output is not ``disabled``, edit the ``/etc/selinux/config`` file: - - .. code-block:: console - - sudo vim /etc/selinux/config - -3. Change ``SELINUX=enforcing`` to ``SELINUX=disabled``: - - The above changes will only take effect after rebooting the server. - - You can disable selinux immediately after rebooting the server by running the following command: - - .. code-block:: console - - sudo setenforce 0 - -Configuring the ``/etc/hosts`` File ------------------------------------- - -1. Edit the ``/etc/hosts`` file: - - .. code-block:: console - - sudo vim /etc/hosts - -2. Call your local host: - - .. code-block:: console - - 127.0.0.1 localhost - <server1 ip> <server_name> - <server2 ip> <server_name> - -Installing the NVIDIA CUDA Driver -================================== - -After configuring your operating system, you must install the NVIDIA CUDA driver. - -.. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. - -Before You Begin -^^^^^^^^^^^^^^^^^ - -1. Verify that the NVIDIA card has been installed and is detected by the system: - - .. code-block:: console - - lspci | grep -i nvidia - -2. Verify that ``gcc`` has been installed: - - .. code-block:: console - - gcc --version - -3. If ``gcc`` has not been installed, install it for RHEL or CentOS: - - .. code-block:: console - - sudo yum install -y gcc - -Updating the Kernel Headers -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1. Update the kernel headers on RHEL or CentOS: - - .. code-block:: console - - sudo yum install kernel-devel-$(uname -r) kernel-headers-$(uname -r) - -2. Make sure kernel-devel and kernel-headers match installed kernel: - - .. code-block:: console - - uname -r - rpm -qa |grep kernel-devel-$(uname -r) - rpm -qa |grep kernel-headers-$(uname -r) - -Disabling Nouveau -^^^^^^^^^^^^^^^^^^^ - -Disable Nouveau, which is the default operating system driver. - -1. Check if the Nouveau driver has been loaded: - - .. code-block:: console - - lsmod | grep nouveau - - If the Nouveau driver has been loaded, the command above generates output. If the Nouveau driver has not been loaded, you may skip step 2 and 3. - -2. Blacklist the Nouveau driver to disable it: - - .. code-block:: console - - cat <<EOF | sudo tee /etc/modprobe.d/blacklist-nouveau.conf - blacklist nouveau - options nouveau modeset=0 - EOF - -3. Regenerate the kernel ``initramfs`` directory set: - - a. Modify the ``initramfs`` directory set: - - .. code-block:: console - - sudo dracut --force - - b. Reboot the server: - - .. code-block:: console - - sudo reboot - -Installing the CUDA Driver ----------------------------- - -.. contents:: - :local: - :depth: 1 - -The current recommendation is for CUDA 12.3.2. - -For A100 GPU and other A series GPUs, you must install CUDA driver **11.4.3** or a later version. - -For H100 GPU and other H series GPUs, you must install CUDA driver **11.8** or a later version. - -For L40S GPU and other L series GPUs, you must install CUDA driver **12.0** or a later version. - -For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. - -Installing the CUDA Driver from the Repository -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Installing the CUDA driver from the Repository is the recommended installation method. - -1. Install the CUDA dependencies for one of the following operating systems: - - * For RHEL7: - - .. code-block:: console - - sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - * For RHEL8: - - .. code-block:: console - - sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - - * For CentOS: - - .. code-block:: console - - sudo yum install epel-release - -2. (Optional) Install the CUDA dependencies from the ``epel`` repository: - - .. code-block:: console - - sudo yum install dkms libvdpau - - Installing the CUDA depedendencies from the ``epel`` repository is only required for installing ``runfile``. - -3. Download and install the required local repository: - - * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - - .. code-block:: console - - sudo yum clean all - sudo yum -y install nvidia-driver-latest-dkms - - * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - - * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm - sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm - - .. code-block:: console - - sudo dnf clean all - sudo dnf -y module install nvidia-driver:latest-dkms - -Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 - - * **IBM Power9 - CUDA 10.1 for RHEL7:** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - -If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. - -Tuning Up NVIDIA Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The following procedures exclusively relate to Intel. - -.. contents:: - :local: - :depth: 1 - -.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. - -Tune Up NVIDIA Performance when Driver Installed from the Repository -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -1. Check the service status: - - .. code-block:: console - - sudo systemctl status nvidia-persistenced - - If the service exists, it will be stopped by default. - -2. Start the service: - - .. code-block:: console - - sudo systemctl start nvidia-persistenced - -3. Verify that no errors have occurred: - - .. code-block:: console - - sudo systemctl status nvidia-persistenced - -4. Enable the service to start up on boot: - - .. code-block:: console - - sudo systemctl enable nvidia-persistenced - -5. For **H100/A100**, add the following lines: - - .. code-block:: console - - nvidia-persistenced - -6. Reboot the server and run the **NVIDIA System Management Interface (NVIDIA SMI)**: - - .. code-block:: console - - nvidia-smi - - - -Tune Up NVIDIA Performance when Driver Installed from the Runfile -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" - -1. Change the permissions on the ``rc.local`` file to ``executable``: - - .. code-block:: console - - sudo chmod +x /etc/rc.local - -2. Edit the ``/etc/yum.repos.d/cuda-10-1-local.repo`` file: - - .. code-block:: console - - sudo vim /etc/rc.local - -3. Add the following lines: - - * **For H100/A100**: - - .. code-block:: console - - nvidia-persistenced - - * **For IBM (mandatory)**: - - .. code-block:: console - - sudo systemctl start nvidia-persistenced - sudo systemctl enable nvidia-persistenced - - * **For K80**: - - .. code-block:: console - - nvidia-persistenced - nvidia-smi -pm 1 - nvidia-smi -acp 0 - nvidia-smi --auto-boost-permission=0 - nvidia-smi --auto-boost-default=0 - -4. Reboot the server and run the ``NVIDIA System Management Interface (NVIDIA SMI)``: - - .. code-block:: console - - nvidia-smi - - - -Enabling Core Dumps -==================== - -While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB support to be able to analyze your core dumps, they must be ``gdb`` compatible. - -.. contents:: - :local: - :depth: 1 - -Checking the ``abrtd`` Status ----------------------------- - -1. Check if ``abrtd`` is running: - - .. code-block:: console - - sudo ps -ef |grep abrt - -2. If **abrtd** is running, stop it: - - .. code-block:: console - - for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done - -Setting the Limits --------------------- - -1. Set the limits: - - .. code-block:: console - - ulimit -c - -2. If the output is ``0``, add the following lines to the ``/etc/security/limits.conf`` file: - - .. code-block:: console - - * soft core unlimited - * hard core unlimited - -3. To apply the limit changes, log out and log back in. - -Creating the Core Dump Directory ------------------------------------ - -Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the ``/tmp/core_dumps`` directory. If necessary, replace path according to your own environment and disk space. - -1. Make the ``/tmp/core_dumps`` directory: - - .. code-block:: console - - mkdir /tmp/core_dumps - -2. Set the ownership of the ``/tmp/core_dumps`` directory: - - .. code-block:: console - - sudo chown sqream.sqream /tmp/core_dumps - -3. Grant read, write, and execute permissions to all users: - - .. code-block:: console - - sudo chmod -R 777 /tmp/core_dumps - - -Setting the Output Directory on the ``/etc/sysctl.conf`` File -------------------------------------------------------------- - -1. Open the ``/etc/sysctl.conf`` file in the Vim text editor: - - .. code-block:: console - - sudo vim /etc/sysctl.conf - -2. Add the following to the bottom of the file: - - .. code-block:: console - - kernel.core_uses_pid = 1 - kernel.core_pattern = /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - fs.suid_dumpable = 2 - -3. To apply the changes without rebooting the server, run the following: - - .. code-block:: console - - sudo sysctl -p - -4. Check that the core output directory points to the following: - - .. code-block:: console - - sudo cat /proc/sys/kernel/core_pattern - - The following shows the correct generated output: - - .. code-block:: console - - /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t - -Verifying that the Core Dumps Work ---------------------------------------------------- - -You can verify that the core dumps work only after installing and running SQreamDB. This causes the server to crash and a new ``core.xxx`` file to be included in the folder that is written in ``/etc/sysctl.conf``. - -1. Stop and restart all SQreamDB services. - - :: - -2. Connect to SQreamDB with ClientCmd and run the following command: - - .. code-block:: console - - select abort_server(); - -Verify Your SQreamDB Installation ------------------------------------- - -1. Verify that the ``sqream`` user exists and has the same ID on all cluster servers. - - .. code-block:: console - - id sqream - -2. please verify that the storage is mounted on all cluster servers. - - .. code-block:: console - - mount - -3. make sure that the driver is properly installed. - - .. code-block:: console - - nvidia-smi - -4. Verify that the kernel file-handles allocation is greater than or equal to ``2097152``: - - .. code-block:: console - - sysctl -n fs.file-max - -5. Verify limits (run this command as a ``sqream`` user): - - .. code-block:: console - - ulimit -c -u -n - - Desired output: - core file size (blocks, -c) unlimited - max user processes (-u) 1000000 - open files (-n) 1000000 - -Troubleshooting Core Dumping ------------------------------- - -This section describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. - -1. Reboot the server. - - :: - -2. Verify that you have folder permissions: - - .. code-block:: console - - sudo chmod -R 777 /tmp/core_dumps - -3. Verify that the limits have been set correctly: - - .. code-block:: console - - ulimit -c - - If all parameters have been configured correctly, the correct output is: - - .. code-block:: console - - core file size (blocks, -c) unlimited - -4. If all parameters have been configured correctly, but running ``ulimit -c`` outputs ``0``, run the following: - - .. code-block:: console - - sudo vim /etc/profile - -5. Search for the following line and disable it using the ``#`` symbol: - - .. code-block:: console - - ulimit -S -c 0 > /dev/null 2>&1 - -6. Log out and log back in. - - :: - -7. Run the ``ulimit -c`` command: - - .. code-block:: console - - ulimit -a - -8. If the line is not found in ``/etc/profile``, do the following: - - a. Run the following command: - - .. code-block:: console - - sudo vim /etc/init.d/functions - - b. Search for the following line disable it using the ``#`` symbol and reboot the server. - - .. code-block:: console - - ulimit -S -c ${DAEMON_COREFILE_LIMIT:-0} >/dev/null 2>&1 From 97f18eda1f31e91ee659538de1b1a41c86e99388 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Apr 2024 16:51:43 +0300 Subject: [PATCH 1309/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 9ad30faca..f5e1422fa 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -4,7 +4,7 @@ Pre-Installation Configuration ****************************** -Before installing SQreamDB, it is essential that you to tune your system for better performance and stability. +Before installing SQreamDB, it is essential that you tune your system for better performance and stability. .. contents:: :local: From d3aed4f1d2030cbdb1a99a1e9d58fec6f8040132 Mon Sep 17 00:00:00 2001 From: TaliaSQream <taliar@sqreamtech.com> Date: Tue, 30 Apr 2024 18:38:30 +0300 Subject: [PATCH 1310/1892] Update linear_regression.rst --- operational_guides/linear_regression.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/linear_regression.rst b/operational_guides/linear_regression.rst index 62d1564d2..bdd6ca3f1 100644 --- a/operational_guides/linear_regression.rst +++ b/operational_guides/linear_regression.rst @@ -35,7 +35,7 @@ Parameters - Description * - Tolerance - ``1e-4`` - - Tolerance determines when to stop training based on the improvement in model performance. If the improvement falls below the tolerance threshold, training stops early. + - When the change resulting from an iteration is smaller than the defined tolerance value, the iterations are terminated. * - Label Index - ``0`` - Label index identifies the position of the target variable (dependent variable) within the dataset, crucial for training a linear regression model. @@ -60,7 +60,7 @@ Missing data is not supported. * All data, including labels and features, should be stored in the same table. -* Ensure that feature values (X) are within the same range. If not, consider normalizing or standardizing the features (X) separately for both training and testing datasets. +* Ensure that feature values (X) are within the same range. If not, consider normalizing or standardizing the features (X) for both training and testing datasets. .. _normalization: @@ -78,7 +78,7 @@ We suggest standardizing features by removing the mean and scaling to unit varia Training Data ============= -There is no need to export data out of SQreamDB for the training process. +The training process occurs entirely within the SQream database environment, meaning that all steps—from data preparation to model training—are conducted within SQreamDB. This eliminates the necessity of exporting data out of SQreamDB for training purposes. .. code-block:: From 6d38e9434ac1c1480dda60e5779a557caac851b4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 1 May 2024 12:49:41 +0300 Subject: [PATCH 1311/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 16a28fa2c..396f3d259 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -71,7 +71,7 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Column** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``SELECT`` | Select from catalog | +| ``SELECT`` | Select from column | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Column DDL operations | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ From 26693279670bc1aed0d829f8b07a2dfd8a302203 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 2 May 2024 13:18:42 +0300 Subject: [PATCH 1312/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index f5e1422fa..87e961777 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -870,12 +870,12 @@ Installing the CUDA driver from the Repository is the recommended installation m wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **RHEL8.8 CUDA 12.2.1 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + * **RHEL8.8 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console - wget https://developer.download.nvidia.com/compute/cuda/12.2.1/local_installers/cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm - sudo dnf localinstall cuda-repo-rhel8-12-2-local-12.2.1_535.86.10-1.x86_64.rpm + wget https://developer.download.nvidia.com/compute/cuda/12.3.2/local_installers/cuda-repo-rhel8-12-3-local-12.3.2_545.23.08-1.x86_64.rpm + sudo dnf localinstall cuda-repo-rhel8-12-3-local-12.3.2_545.23.08-1.x86_64.rpm .. code-block:: console From 38eb3028fc90549495c8cc62608d507d9eb34bc9 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 7 May 2024 08:08:37 +0300 Subject: [PATCH 1313/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 396f3d259..017ce2bb6 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -448,6 +448,12 @@ Grant column-level permissions to a role: GRANT SELECT, DDL ON COLUMN column_name IN TABLE schema_name.table_name TO role_name; +Grant view-level permissions to a role: + +.. code-block:: postgres + + GRANT ALL PERMISSIONS ON VIEW "view_name" IN SCHEMA "schema_name" TO role_name; + Grant usage permissions on a service to a role: .. code-block:: postgres @@ -506,6 +512,12 @@ Revoke column-level permissions from a role: REVOKE SELECT, DDL FROM COLUMN column_name IN TABLE schema_name.table_name FROM role_name; +Revoke view-level permissions from a role: + +.. code-block:: postgres + + REVOKE ALL PERMISSIONS ON VIEW "view_name" IN SCHEMA "schema_name" FROM role_name; + Revoke usage permissions on a service from a role: .. code-block:: postgres From 53d1df7a9b82dd2ac2c925e0cca048873704fa03 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 8 May 2024 13:52:08 +0300 Subject: [PATCH 1314/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 739 +++++++++++++++++++- 1 file changed, 738 insertions(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 7710d03c3..87fee4dab 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1 +1,738 @@ -.. _ingesting_from_databases: ****************** External Databases ****************** The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. **SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. .. contents:: :local: :depth: 1 Before You Begin ================ It is essential that you have the following: * Java 17 * SQLoader configuration files * SQLoader.jar file Minimum Hardware Requirements ------------------------------ .. list-table:: :widths: auto :header-rows: 1 * - Component - Type * - CPU cores - 16 * - RAM - 32GB .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------ The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection ============================ Getting the SQLoader Configuration and JAR Files ------------------------------------------------ 1. Download the ``.tar`` file using the following command: .. code-block:: console curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-7.8.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: console tar -xf sqloader-7.8.tar.gz A folder named ``sqloader`` with the following files is created: .. list-table:: :widths: auto :header-rows: 1 * - File - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion * - ``sqload-jdbc.properties`` - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. * - ``sqloader.jar`` - The SQLoader package file Establishing a Connection ------------------------- The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters :widths: auto :header-rows: 1 * - Parameter - Description * - ``HostIp:port`` - The host and IP address number * - ``database_name`` - The name of the database from which data is loaded * - ``user`` - Username of a role to use for connection * - ``password`` - Specifies the password of the selected role * - ``ssl`` - Specifies SSL for this connection .. literalinclude:: connection_string.java :language: java :caption: Properties File Sample :linenos: Starting SQLoader ----------------- To start SQLoader, run the ``sqloader.jar`` file: .. code-block:: console java -jar sqloader.jar --------------------------------- Loading Data into SQreamDB ========================== To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: .. code-block:: console java -jar sqloader.jar -table <source_table_name> .. contents:: :local: :depth: 1 Customizing Data Load --------------------- While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. Please note that any customization done through the CLI will override configurations made using the properties file. .. list-table:: SQLoader CLI Parameters :widths: auto :header-rows: 1 * - CLI Parameter - State - Default - Type - Description * - ``-batchsize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes * - ``-casesensative`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``-check_cdc_chain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table * - ``-chunkSize`` - Optional - ``0`` - - The number of records read at once from the source database * - ``-columnlist`` - Optional - *None* - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n`` * - ``-columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``-config`` - Optional - ``/home/username/downloads/config/sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI * - ``-config_dir`` - Optional - ``/home/username/downloads/config`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error * - ``-count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``-delete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``-drop`` - Optional - ``true`` - - Assuming we're loading into table ``x``: * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: * Creating or replacing a temporary table named ``x_temp`` * The data you intend to load is inserted into the ``x_temp`` table * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` * Any previously existing table named ``x_old`` is dropped from the database * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: * SQLoader first checks if the target table exists and raises an exception if it does not * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used * Data is loaded into the temporary table * Target table is renamed to ``x_old`` * The temporary table ``x_temp`` is renamed to the target table name ``x`` * ``x_old`` is dropped * - ``-fetchsize`` - Optional - ``100000`` - - The number of records to be read at once from source database * - ``-filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded * - ``-h, --help`` - Optional - *No input* - - Displays the help menu and exits * - ``-limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded * - ``-load_dttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``-lock_check`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``-lock_table`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts * - ``-log_dir`` - Optional - ``logs`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``-partition`` - Optional - *None* - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions * - ``-rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``-source_db`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables * - ``-split`` - Optional - *None* - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``-table`` - Mandatory - *None* - Table name ``string`` - Source table name to load data from * - ``-target`` - Optional - Target table name - Table name ``string`` - Target table name to load data into * - ``-thread`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``-truncate`` - Optional - ``false`` - - Truncate target table before loading * - ``-type`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are: * ``full``: The entire data of the source table is loaded into SQreamDB * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``-use_dbms_lob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``-use_partitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements Data Types and Mapping ---------------------- SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. .. contents:: :local: :depth: 1 Automatic Mapping ^^^^^^^^^^^^^^^^^ Oracle """""" .. list-table:: :widths: auto :header-rows: 1 * - Oracle Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - ``BIGINT`` * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``DATE``, ``DATETIME`` - ``DATETIME`` * - ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``CLOB`` - ``TEXT`` * - ``BLOB`` - ``TEXT`` * - ``RAW`` - ``TEXT`` Postgresql """""""""" .. list-table:: :widths: auto :header-rows: 1 * - Postgresql Type - SQreamDB Type * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - ``TEXT`` * - ``TEXT`` - ``TEXT`` * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT``, ``BOOL`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL``, ``FLOAT4`` - ``REAL`` Teradata """""""" .. list-table:: :widths: auto :header-rows: 1 * - Teradata Type - SQreamDB Type * - ``F`` - ``DOUBLE`` * - ``N``, ``D`` - ``NUMERIC`` * - ``CO`` - ``TEXT`` * - ``BO`` - ``TEXT`` * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - ``TEXT`` * - ``I``, ``I4``, ``I(4)`` - ``INT`` * - ``I2``, ``I(2)`` - ``SMALLINT`` * - ``I1``, ``I(1)`` - ``TINYINT`` * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - ``BIGINT`` * - ``TS``, ``DATETIME`` - ``DATETIME`` * - ``DA`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``REAL``, ``DOUBLE`` - ``DOUBLE`` Microsoft SQL Server """""""""""""""""""" .. list-table:: :widths: auto :header-rows: 1 * - Microsoft SQL Server Type - SQreamDB Type * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - ``TEXT`` * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - ``BIGINT`` * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BIT`` - ``BOOL`` * - ``DECIMAL``, ``NUMERIC`` - ``NUMERIC`` * - ``FLOAT``, ``DOUBLE`` - ``DOUBLE`` * - ``REAL`` - ``REAL`` * - ``VARBINARY`` - ``TEXT`` SAP HANA """""""" .. list-table:: :widths: auto :header-rows: 1 * - SAP HANA Type - SQreamDB Type * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - ``BIGINT`` * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - ``TEXT`` * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOLEAN`` - ``TEXT`` * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - ``NUMERIC`` * - ``DOUBLE``, ``REAL`` - ``FLOAT`` * - ``TEXT`` - ``TEXT`` * - ``BIGINT`` - ``BIGINT`` * - ``INT`` - ``INT`` * - ``SMALLINT`` - ``SMALLINT`` * - ``TINYINT`` - ``TINYINT`` * - ``DATETIME`` - ``DATETIME`` * - ``DATE`` - ``DATE`` * - ``BOOL`` - ``BOOL`` * - ``NUMERIC`` - ``NUMERIC`` * - ``DOUBLE`` - ``DOUBLE`` * - ``FLOAT`` - ``FLOAT`` * - ``REAL`` - ``REAL`` Manual Mapping ^^^^^^^^^^^^^^ You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. .. code-block:: json { "oracle": [ { "names": ["column1", "column2", "column3"], "sqream": "bigint", "java": "int", "length": false }, { "type": ["bigint","int","smallint","integer"], "sqream": "bigint", "java": "int", "length": false } } .. code-block:: json { "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], "sqream": "text", "java": "string", "length": true }, { "type": ["date","datetime"], "sqream": "datetime", "java": "datetime", "length": false }, { "type": ["timestamp"], "sqream": "datetime", "java": "timestamp", "length": false }, { "type": ["date"], "sqream": "date", "java": "datetime", "length": false }, { "type": ["boolean"], "sqream": "bool", "java": "boolean", "length": false }, { "type": ["number"], "sqream": "numeric", "java": "bigdecimal", "length": true, "prec": true }, { "type": ["float","double"], "sqream": "double", "java": "double", "length": false }, { "type": ["clob"], "sqream": "text", "java": "clob", "length": false }, { "type": ["blob"], "sqream": "text", "java": "blob", "length": false } ] } --------------------------------- Creating Summary Tables ======================= Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. Summary tables are part of the schema within the database catalog. Examples -------- The following examples use Oracle syntax. A Summary Table ^^^^^^^^^^^^^^^ .. code-block:: sql CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, LAST_VAL_TS DATE VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, ROW_COUNT NUMBER VISIBLE, SQL_FILTER TEXT(200 BYTE) VISIBLE, PARTITION TEXT(200 BYTE) VISIBLE, STMT_TYPE TEXT(200 BYTE) VISIBLE, STATUS TEXT(200 BYTE) VISIBLE, LOG_FILE TEXT(200 BYTE) VISIBLE, DB_URL TEXT(200 BYTE) VISIBLE, PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, THREAD_COUNT NUMBER VISIBLE DEFAULT 1, ELAPSED_MS NUMBER VISIBLE DEFAULT 0, STATUS_CODE NUMBER VISIBLE DEFAULT 0, ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL ); Change Data Capture Summary Tables ---------------------------------- Change Data Capture (CDC) tables are supported only for Oracle. .. code-block:: sql CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, LOAD_TYPE TEXT(200 BYTE) VISIBLE, FREQ_TYPE TEXT(200 BYTE) VISIBLE, FREQ_INTERVAL NUMBER(22,0) VISIBLE, IS_ACTIVE NUMBER VISIBLE DEFAULT 0, STATUS_LOAD NUMBER VISIBLE DEFAULT 0, INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 ); CREATE TABLE public.CDC_TRACKING ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, LAST_UPDATED_DTTM DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, LAST_VAL_TS TIMESTAMP(6) VISIBLE, LAST_VAL_DT DATE VISIBLE ); CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME TEXT(200 BYTE) VISIBLE, TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, COLUMN_NAME TEXT(200 BYTE) VISIBLE, IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); ------------------------------------------------------- CLI Examples ============ Loading data into a CDC table using the ``type`` and ``limit`` parameters: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 Loading data into a table using your own configuration file (this will override the default configuration file): .. code-block:: console java -jar sqloader.jar -config path/to/your/config/file Loading data into a table using a custom configuration file: .. code-block:: console java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false Loading data into a table using a the ``filter`` parameter: .. code-block:: console java -jar sqloader.jar -table <source_table_name> -filter column_name>50 .. toctree:: :maxdepth: 1 :glob: preparing_oracle_for_data_migration \ No newline at end of file +.. _ingesting_from_databases: + +****************** +External Databases +****************** + +The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. + +**SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following: + +* Java 17 +* SQLoader configuration files +* SQLoader.jar file + +Minimum Hardware Requirements +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - CPU cores + - 16 + * - RAM + - 32GB + +.. _sqloader_thread_sizing_guidelines: + +Sizing Guidelines +------------------ + +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. + +--------------------------------- + +Installation and Connection +============================ + +Getting the SQLoader Configuration and JAR Files +------------------------------------------------ + +1. Download the ``.tar`` file using the following command: + + .. code-block:: console + + curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.12.tar + +2. Extract the ``.tar`` file using the following command: + + .. code-block:: console + + tar -xf sqloader-7.12.tar.gz + + A folder named ``sqloader`` with the following files is created: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - File + - Description + * - ``sqream-mapping.json`` + - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion + * - ``sqload-jdbc.properties`` + - Used for defining a connection string and may also be used to reconfigure data loading + * - ``reserved_words.txt`` + - A list of reserved words which cannot be used as table and/or column names. + * - ``sqloader.jar`` + - The SQLoader package file + +Establishing a Connection +------------------------- + +The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. + +1. Open the ``sqload-jdbc.properties`` file. +2. Configure connection parameters for: + + a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings + b. Optionally, Oracle or SQreamDB catalogs (recommended) + +.. list-table:: Connection String Parameters + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``HostIp:port`` + - The host and IP address number + * - ``database_name`` + - The name of the database from which data is loaded + * - ``user`` + - Username of a role to use for connection + * - ``password`` + - Specifies the password of the selected role + * - ``ssl`` + - Specifies SSL for this connection + +.. literalinclude:: connection_string.java + :language: java + :caption: Properties File Sample + :linenos: + +Starting SQLoader +----------------- + +To start SQLoader, run the ``sqloader.jar`` file: + +.. code-block:: console + + java -jar sqloader.jar + +--------------------------------- + +Loading Data into SQreamDB +========================== + +To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: + +.. code-block:: console + + java -jar sqloader.jar -table <source_table_name> + +.. contents:: + :local: + :depth: 1 + +Customizing Data Load +--------------------- + +While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. + +Please note that any customization done through the CLI will override configurations made using the properties file. + +.. list-table:: SQLoader CLI Parameters + :widths: auto + :header-rows: 1 + + * - CLI Parameter + - State + - Default + - Type + - Description + * - ``-batchsize`` + - Optional + - ``10.000`` + - + - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes + * - ``-casesensative`` + - Optional + - ``false`` + - + - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB + * - ``-check_cdc_chain`` + - Optional + - ``false`` + - + - Check CDC chain between tracking table and source table + * - ``-chunkSize`` + - Optional + - ``0`` + - + - The number of records read at once from the source database + * - ``-columnlist`` + - Optional + - *None* + - ``.txt`` + - The name of the file that contains all column names. Columns must be separated using ``\n`` + * - ``-columns`` + - Optional + - All columns + - + - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true + * - ``-config`` + - Optional + - ``/home/username/downloads/config/sqload-jdbc.properties`` + - + - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI + * - ``-config_dir`` + - Optional + - ``/home/username/downloads/config`` + - + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error + * - ``-count`` + - Optional + - ``true`` + - + - Defines whether or not table rows will be counted before being loaded into SQreamDB + * - ``-delete`` + - Optional + - ``true`` + - + - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows + * - ``-drop`` + - Optional + - ``true`` + - + - + Assuming we're loading into table ``x``: + + * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: + + * Creating or replacing a temporary table named ``x_temp`` + * The data you intend to load is inserted into the ``x_temp`` table + * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) + * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` + * Any previously existing table named ``x_old`` is dropped from the database + + * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: + + * SQLoader first checks if the target table exists and raises an exception if it does not + * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables + * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used + * Data is loaded into the temporary table + * Target table is renamed to ``x_old`` + * The temporary table ``x_temp`` is renamed to the target table name ``x`` + * ``x_old`` is dropped + * - ``-fetchsize`` + - Optional + - ``100000`` + - + - The number of records to be read at once from source database + * - ``-filter`` + - Optional + - ``1=1`` + - + - Defines whether or not only records with SQL conditions are loaded + * - ``-h, --help`` + - Optional + - *No input* + - + - Displays the help menu and exits + * - ``-limit`` + - Optional + - ``0`` (no limit) + - + - Limits the number of rows to be loaded + * - ``-load_dttm`` + - Optional + - ``true`` + - + - Add an additional ``load_dttm`` column that defines the time and date of loading + * - ``-lock_check`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader will check source table is locked before the loading starts + * - ``-lock_table`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader will lock target table before the loading starts + * - ``-log_dir`` + - Optional + - ``logs`` + - + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``-partition`` + - Optional + - *None* + - Partition identifier ``string`` + - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions + * - ``-rowid`` + - Optional + - ``false`` + - + - Defines whether or not SQLoader will get row IDs from Oracle tables + * - ``-source_db`` + - Optional + - ``ORCL`` + - + - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables + * - ``-split`` + - Optional + - *None* + - Column name ``string`` + - Column name for split (required for multi-thread loads) + * - ``-table`` + - Mandatory + - *None* + - Table name ``string`` + - Source table name to load data from + * - ``-target`` + - Optional + - Target table name + - Table name ``string`` + - Target table name to load data into + * - ``-thread`` + - Optional + - ``1`` + - + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` + * - ``-truncate`` + - Optional + - ``false`` + - + - Truncate target table before loading + * - ``-type`` + - Optional + - ``full`` + - + - Defines a loading type that affects the table that is created in SQreamDB. Options are: + + * ``full``: The entire data of the source table is loaded into SQreamDB + + * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata + + * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata + Please note that ``cdc``, and ``inc`` are supported only for Oracle + * - ``-use_dbms_lob`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types + * - ``-use_partitions`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader uses partitions in ``SELECT`` statements + +Data Types and Mapping +---------------------- + +SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. + +.. contents:: + :local: + :depth: 1 + +Automatic Mapping +^^^^^^^^^^^^^^^^^ + +Oracle +"""""" + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` + - ``BIGINT`` + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``DATE``, ``DATETIME`` + - ``DATETIME`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``CLOB`` + - ``TEXT`` + * - ``BLOB`` + - ``TEXT`` + * - ``RAW`` + - ``TEXT`` + + + +Postgresql +"""""""""" + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Postgresql Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +Teradata +"""""""" + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Teradata Type + - SQreamDB Type + * - ``F`` + - ``DOUBLE`` + * - ``N``, ``D`` + - ``NUMERIC`` + * - ``CO`` + - ``TEXT`` + * - ``BO`` + - ``TEXT`` + * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` + - ``TEXT`` + * - ``I``, ``I4``, ``I(4)`` + - ``INT`` + * - ``I2``, ``I(2)`` + - ``SMALLINT`` + * - ``I1``, ``I(1)`` + - ``TINYINT`` + * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` + - ``BIGINT`` + * - ``TS``, ``DATETIME`` + - ``DATETIME`` + * - ``DA`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``REAL``, ``DOUBLE`` + - ``DOUBLE`` + +Microsoft SQL Server +"""""""""""""""""""" + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Microsoft SQL Server Type + - SQreamDB Type + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` + - ``TEXT`` + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL`` + - ``REAL`` + * - ``VARBINARY`` + - ``TEXT`` + +SAP HANA +"""""""" + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SAP HANA Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` + - ``BIGINT`` + * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` + - ``TEXT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``TEXT`` + * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` + - ``NUMERIC`` + * - ``DOUBLE``, ``REAL`` + - ``FLOAT`` + * - ``TEXT`` + - ``TEXT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``INT`` + - ``INT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``DATETIME`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOL`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``FLOAT`` + - ``FLOAT`` + * - ``REAL`` + - ``REAL`` + +Manual Mapping +^^^^^^^^^^^^^^ + +You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. + +To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. + +In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. + +.. code-block:: json + + { + "oracle": [ + { + "names": ["column1", "column2", "column3"], + "sqream": "bigint", + "java": "int", + "length": false + }, + { + "type": ["bigint","int","smallint","integer"], + "sqream": "bigint", + "java": "int", + "length": false + } + } + +.. code-block:: json + + { + "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], + "sqream": "text", + "java": "string", + "length": true + }, + { + "type": ["date","datetime"], + "sqream": "datetime", + "java": "datetime", + "length": false + }, + { + "type": ["timestamp"], + "sqream": "datetime", + "java": "timestamp", + "length": false + }, + { + "type": ["date"], + "sqream": "date", + "java": "datetime", + "length": false + }, + { + "type": ["boolean"], + "sqream": "bool", + "java": "boolean", + "length": false + }, + { + "type": ["number"], + "sqream": "numeric", + "java": "bigdecimal", + "length": true, + "prec": true + }, + { + "type": ["float","double"], + "sqream": "double", + "java": "double", + "length": false + }, + { + "type": ["clob"], + "sqream": "text", + "java": "clob", + "length": false + }, + { + "type": ["blob"], + "sqream": "text", + "java": "blob", + "length": false + } + ] + } + +--------------------------------- + +Creating Summary Tables +======================= + +Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. + +Summary tables are part of the schema within the database catalog. + +Examples +-------- + +The following examples use Oracle syntax. + +A Summary Table +^^^^^^^^^^^^^^^ + +.. code-block:: sql + + + CREATE TABLE public.SQLOAD_SUMMARY ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + UPDATED_DTTM_FROM DATE VISIBLE, + UPDATED_DTTM_TO DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE, + LAST_VAL_TS DATE VISIBLE, + START_TIME TIMESTAMP(6) VISIBLE, + FINISH_TIME TIMESTAMP(6) VISIBLE, + ELAPSED_SEC NUMBER VISIBLE, + ROW_COUNT NUMBER VISIBLE, + SQL_FILTER TEXT(200 BYTE) VISIBLE, + PARTITION TEXT(200 BYTE) VISIBLE, + STMT_TYPE TEXT(200 BYTE) VISIBLE, + STATUS TEXT(200 BYTE) VISIBLE, + LOG_FILE TEXT(200 BYTE) VISIBLE, + DB_URL TEXT(200 BYTE) VISIBLE, + PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, + THREAD_COUNT NUMBER VISIBLE DEFAULT 1, + ELAPSED_MS NUMBER VISIBLE DEFAULT 0, + STATUS_CODE NUMBER VISIBLE DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, + TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, + SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, + HOST VARCHAR2(200) DEFAULT NULL + ); + + +Change Data Capture Summary Tables +---------------------------------- + +Change Data Capture (CDC) tables are supported only for Oracle. + +.. code-block:: sql + + CREATE TABLE public.CDC_TABLES ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, + INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, + INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_INTERVAL NUMBER(22,0) VISIBLE, + IS_ACTIVE NUMBER VISIBLE DEFAULT 0, + STATUS_LOAD NUMBER VISIBLE DEFAULT 0, + INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 + ); + + CREATE TABLE public.CDC_TRACKING ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LAST_UPDATED_DTTM DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + LAST_VAL_DT DATE VISIBLE + ); + + CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, + COLUMN_NAME TEXT(200 BYTE) VISIBLE, + IS_NULLABLE NUMBER VISIBLE DEFAULT 0 + ); + +------------------------------------------------------- + +CLI Examples +============ + +Loading data into a CDC table using the ``type`` and ``limit`` parameters: + +.. code-block:: console + + java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 + +Loading data into a table using your own configuration file (this will override the default configuration file): + +.. code-block:: console + + java -jar sqloader.jar -config path/to/your/config/file + +Loading data into a table using a custom configuration file: + +.. code-block:: console + + java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false + +Loading data into a table using a the ``filter`` parameter: + +.. code-block:: console + + java -jar sqloader.jar -table <source_table_name> -filter column_name>50 + + + +.. toctree:: + :maxdepth: 1 + :glob: + + preparing_oracle_for_data_migration From 0b61fa8bd6e1919e052c7985dfe9e62c8ce80dff Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 May 2024 14:17:43 +0300 Subject: [PATCH 1315/1892] SQLoader Service --- data_ingestion/connection_string.java | 32 +- data_ingestion/ingesting_from_databases_2.rst | 801 ++++++++++++++++++ 2 files changed, 817 insertions(+), 16 deletions(-) create mode 100644 data_ingestion/ingesting_from_databases_2.rst diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java index 680ca117c..cb22962d5 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.java @@ -1,26 +1,26 @@ -####mandatory! +// mandatory! -##Postgresql, Oracle, Teradata, SAP HANA, Microsoft SQL Server, and SQreamDB Connection Strings +// Postgresql, Oracle, Teradata, SAP HANA, Microsoft SQL Server, and SQreamDB Connection Strings -#postgres +// postgres source.jdbc.connectionstring=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> -#oracle +// oracle source.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> -#teradata +// teradata source.jdbc.connectionstring=jdbc:teradata://<HostIp>/DATABASE=<database_name>,DBS_PORT=<port>,user=<user_name>,password=<password> -#sap hana +// sap hana source.jdbc.connectionstring=jdbc:sap://<HostIp>:<port>/?user=<user_name>&password=<password> -#microsoft sql server +// microsoft sql server source.jdbc.connectionstring=jdbc:sqlserver://<HostIp>:<port>;databaseName=<database_name>;user=<user_name>;password=<password>;encrypt=<true/false>;trustServerCertificate=<true/false> -#sqream +// sqream sqream.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> -##CDC and Incremental Parameter +// CDC and Incremental Parameter cdc_catalog_table=public.CDC_TABLES cdc_tracking_table=public.CDC_TRACKING @@ -28,13 +28,13 @@ -####Optional! +// Optional! -#Oracle Catalog -#catalog.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> +// Oracle Catalog +// catalog.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> -#SQreamDB Catalog -#catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> +// SQreamDB Catalog +// catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> -#Summary Parameter -#load_summary_table=public.SQLOAD_SUMMARY \ No newline at end of file +// Summary Parameter +// load_summary_table=public.SQLOAD_SUMMARY \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst new file mode 100644 index 000000000..669fabd70 --- /dev/null +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -0,0 +1,801 @@ +.. _ingesting_from_databases_2: + +****************** +External Databases +****************** + +The **SQLoader** is a java service that enables you to load data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. + +**SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following: + +* Java 17 +* SQLoader configuration files +* SQLoader.jar file + + + +Minimum Hardware Requirements +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - CPU cores + - 16 + * - RAM + - 32GB + +.. _sqloader_thread_sizing_guidelines: + +Sizing Guidelines +------------------ + +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. + +Getting the SQLoader Configuration and JAR Files +================================================ + +1. Download the ``.tar`` file using the following command: + +.. code-block:: linux + + curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.12.tar + +2. Extract the ``.tar`` file using the following command: + +.. code-block:: linux + + tar -xf sqloader-7.12.tar.gz + +A folder named ``sqloader`` with the following files is created: + +.. list-table:: SQLoader Files + :widths: auto + :header-rows: 1 + + * - File + - Description + * - ``sqream-mapping.json`` + - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion + * - ``sqload-jdbc.properties`` + - Used for defining a connection string and may also be used to reconfigure data loading + * - ``reserved_words.txt`` + - A list of reserved words which cannot be used as table and/or column names. + * - ``sqloader.jar`` + - The SQLoader package file + +Connection String +================= + +The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. + +1. Open the ``sqload-jdbc.properties`` file. +2. Configure connection parameters for: + + a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings + b. Optionally, Oracle or SQreamDB catalogs (recommended) + +.. list-table:: Connection String Parameters + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``HostIp:port`` + - The host and IP address number + * - ``database_name`` + - The name of the database from which data is loaded + * - ``user`` + - Username of a role to use for connection + * - ``password`` + - Specifies the password of the selected role + * - ``ssl`` + - Specifies SSL for this connection + +.. literalinclude:: connection_string.java + :language: java + :caption: Properties File Sample + :linenos: + +Using SQLoader Service +====================== + +When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, which corresponds to the default ``sqload-jdbc.properties`` file. + +``DEFAULT_PROPERTIES`` can be configured using one of two ways: + +* Setting as an environment variable: + + .. code-block:: + + export DEFAULT_PROPERTIES=/home/avivs/branches/java/sqloader-service/config/sqload-jdbc.properties + + Followed by service execution: + + .. code-block:: + + java -jar target/sqloaderService-8.0.jar + +* Appending to -D flag when executing the jar: + + .. code-block:: + + java -jar -DDEFAULT_PROPERTIES=/home/avivs/branches/java/sqloader-service/config/sqload-jdbc.properties target/sqloaderService-8.0.jar + + .. note:: + + ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. + +Supported Post Requests +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Post + - Description + * - ``load`` + - Send request to service and return + * - ``syncLoad`` + - Send request to service and return once the request is done + * - ``filterLogs`` + - Get logs for a specific request id + * - ``getActiveLoads`` + - Get a list of all active loads currently running in shared queue + * - ``cancelRequest`` + - Cancel an ``async`` request by request id + +Loading Data into SQreamDB Tables +--------------------------------- + +1. Run the ``sqloader.jar`` file using the following CLI command: + +.. code-block:: console + + java -jar sqloader.jar + +2. You may load the entire data of a source table using the following CLI command: + +.. code-block:: console + + java -jar sqloader.jar -table source_table_name + +3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: + +.. list-table:: SQLoader Service Parameters + :widths: auto + :header-rows: 1 + + * - CLI Parameter + - State + - Default + - Type + - Description + * - ``-configFile`` + - Optional + - ``sqload-jdbc.properties`` + - + - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI. If not specified, the service will use ``DEFAULT_PROPERTIES`` parameter + * - ``-connectionStringSqream`` + - Optional + - + - + - JDBC connection string to SQreamDB + * - ``-connectionStringSource`` + - Optional + - + - + - JDBC connection string to source database + * - ``-connectionStringCatalog`` + - Optional + - + - + - JDBC connection string to catalog database + * - ``-cdcCatalogTable`` + - Optional + - + - + - Part of the schema within the catalog database. Holds all inc/cdc tables and their settings + * - ``cdcTrackingTable`` + - Optional + - + - + - Part of the schema within the catalog database. Holds the last tracking value for every inc/cdc table from ``cdcCatalogTable`` table + * - ``cdcPrimaryKeyTable`` + - Optional + - + - + - Part of the schema within the catalog database. Holds all primary keys for every inc/cdc table from ``cdcCatalogTable`` table + * - ``loadSummaryTable`` + - Optional + - + - + - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load + * - ``-batchSize`` + - Optional + - ``10.000`` + - + - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. + * - ``-caseSensitive`` + - Optional + - ``false`` + - + - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB + * - ``-checkCdcChain`` + - Optional + - ``false`` + - + - Check CDC chain between tracking table and source table + * - ``-chunkSize`` + - Optional + - ``0`` + - + - The number of records read at once from the source database + * - ``columnListFilePath`` + - Optional + - + - ``.txt`` + - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` + * - ``-columns`` + - Optional + - All columns + - + - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true + * - ``-configDir`` + - Optional + - ``java -jar target/sqloaderService-8.0.jar --configDir=</path/to/directory/>`` + - + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file + * - ``-count`` + - Optional + - ``true`` + - + - Defines whether or not table rows will be counted before being loaded into SQreamDB + * - ``-cdcDelete`` + - Optional + - ``true`` + - + - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows + * - ``-drop`` + - Optional + - ``true`` + - + - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter + * - ``-fetchSize`` + - Optional + - ``100000`` + - + - The number of records to be read at once from source database. + * - ``-filter`` + - Optional + - ``1=1`` + - + - Defines whether or not only records with SQL conditions are loaded + * - ``-h, --help`` + - Optional + - + - + - Displays the help menu and exits + * - ``-limit`` + - Optional + - ``0`` (no limit) + - + - Limits the number of rows to be loaded + * - ``-loadDttm`` + - Optional + - ``true`` + - + - Add an additional ``load_dttm`` column that defines the time and date of loading + * - ``-lockCheck`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader will check source table is locked before the loading starts + * - ``-lockTable`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader will lock target table before the loading starts + * - ``-log_dir`` + - Optional + - ``logs`` + - ``java -jar -DLOG_DIR=/path/to/log/directory target/sqloaderService-8.0.jar`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``-partitionName`` + - Optional + - + - Partition identifier ``string`` + - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. + * - ``-rowid`` + - Optional + - ``false`` + - + - Defines whether or not SQLoader will get row IDs from Oracle tables + * - ``-sourceDatabaseName`` + - Optional + - ``ORCL`` + - + - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. + * - ``-splitByColumn`` + - Optional + - + - Column name ``string`` + - Column name for split (required for multi-thread loads) + * - ``-sourceTable`` + - Mandatory + - + - Table name ``string`` + - Source table name to load data from + * - ``-sqreamTable`` + - Optional + - Target table name + - Table name ``string`` + - Target table name to load data into + * - ``-threadCount`` + - Optional + - ``1`` + - + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` + * - ``-truncate`` + - Optional + - ``false`` + - + - Truncate target table before loading + * - ``-loadTypeName`` + - Optional + - ``full`` + - + - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle + * - ``-useDbmsLob`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types + * - ``-usePartitions`` + - Optional + - ``true`` + - + - Defines whether or not SQLoader uses partitions in ``SELECT`` statements + +-- Add new flags, review new description and CamelCase for all flags. +-- All new flags are optional + +Using the ``type`` Parameter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Loading Type + - Parameter Option + - Description + * - Full Table + - ``full`` + - The entire data of the source table is loaded into SQreamDB + * - Change Data Capture (CDC) + - ``cdc`` + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only + * - Incremental + - ``inc`` + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only + + +Creating Summary Tables +======================== + +Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. + +Summary tables are part of the schema within the database catalog. + +Creating a Summary Table +-------------------------- + +This summary table uses Oracle syntax. + +Moving to SQLoader service, add the following column: + +.. code-block: sql + + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + +.. code-block:: sql + + + CREATE TABLE public.SQLOAD_SUMMARY ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + UPDATED_DTTM_FROM DATE VISIBLE, + UPDATED_DTTM_TO DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE, + LAST_VAL_TS DATE VISIBLE, + START_TIME TIMESTAMP(6) VISIBLE, + FINISH_TIME TIMESTAMP(6) VISIBLE, + ELAPSED_SEC NUMBER VISIBLE, + ROW_COUNT NUMBER VISIBLE, + SQL_FILTER TEXT(200 BYTE) VISIBLE, + PARTITION TEXT(200 BYTE) VISIBLE, + STMT_TYPE TEXT(200 BYTE) VISIBLE, + STATUS TEXT(200 BYTE) VISIBLE, + LOG_FILE TEXT(200 BYTE) VISIBLE, + DB_URL TEXT(200 BYTE) VISIBLE, + PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, + THREAD_COUNT NUMBER VISIBLE DEFAULT 1, + ELAPSED_MS NUMBER VISIBLE DEFAULT 0, + STATUS_CODE NUMBER VISIBLE DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, + TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, + SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, + HOST VARCHAR2(200) DEFAULT NULL, + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + ); + + +Creating a Change Data Capture Table +-------------------------------------- + +Change Data Capture (CDC) tables are supported only for Oracle. + +.. code-block:: sql + + CREATE TABLE public.CDC_TABLES ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, + INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, + INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_INTERVAL NUMBER(22,0) VISIBLE, + IS_ACTIVE NUMBER VISIBLE DEFAULT 0, + STATUS_LOAD NUMBER VISIBLE DEFAULT 0, + INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 + ); + + CREATE TABLE public.CDC_TRACKING ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LAST_UPDATED_DTTM DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + LAST_VAL_DT DATE VISIBLE + ); + + CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, + COLUMN_NAME TEXT(200 BYTE) VISIBLE, + IS_NULLABLE NUMBER VISIBLE DEFAULT 0 + ); + + +Data Type Mapping +================= + +.. contents:: + :local: + :depth: 1 + +Automatic Mapping +------------------ + +The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. + +Oracle +^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` + - ``BIGINT`` + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``DATE``, ``DATETIME`` + - ``DATETIME`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``CLOB`` + - ``TEXT`` + * - ``BLOB`` + - ``TEXT`` + * - ``RAW`` + - ``TEXT`` + + + +Postgresql +^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Postgresql Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +Teradata +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Teradata Type + - SQreamDB Type + * - ``F`` + - ``DOUBLE`` + * - ``N``, ``D`` + - ``NUMERIC`` + * - ``CO`` + - ``TEXT`` + * - ``BO`` + - ``TEXT`` + * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` + - ``TEXT`` + * - ``I``, ``I4``, ``I(4)`` + - ``INT`` + * - ``I2``, ``I(2)`` + - ``SMALLINT`` + * - ``I1``, ``I(1)`` + - ``TINYINT`` + * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` + - ``BIGINT`` + * - ``TS``, ``DATETIME`` + - ``DATETIME`` + * - ``DA`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``REAL``, ``DOUBLE`` + - ``DOUBLE`` + +Microsoft SQL Server +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Microsoft SQL Server Type + - SQreamDB Type + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` + - ``TEXT`` + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL`` + - ``REAL`` + * - ``VARBINARY`` + - ``TEXT`` + +SAP HANA +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SAP HANA Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` + - ``BIGINT`` + * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` + - ``TEXT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``TEXT`` + * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` + - ``NUMERIC`` + * - ``DOUBLE``, ``REAL`` + - ``FLOAT`` + * - ``TEXT`` + - ``TEXT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``INT`` + - ``INT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``DATETIME`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOL`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``FLOAT`` + - ``FLOAT`` + * - ``REAL`` + - ``REAL`` + +Manually Adjusting Mapping +---------------------------- + +You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. + +``names`` Method +^^^^^^^^^^^^^^^^^ + +To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. + +In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. + +.. code-block:: json + + { + "oracle": [ + { + "names": ["column1", "column2", "column3"], + "sqream": "bigint", + "java": "int", + "length": false + }, + { + "type": ["bigint","int","smallint","integer"], + "sqream": "bigint", + "java": "int", + "length": false + } + } + +.. code-block:: json + + { + "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], + "sqream": "text", + "java": "string", + "length": true + }, + { + "type": ["date","datetime"], + "sqream": "datetime", + "java": "datetime", + "length": false + }, + { + "type": ["timestamp"], + "sqream": "datetime", + "java": "timestamp", + "length": false + }, + { + "type": ["date"], + "sqream": "date", + "java": "datetime", + "length": false + }, + { + "type": ["boolean"], + "sqream": "bool", + "java": "boolean", + "length": false + }, + { + "type": ["number"], + "sqream": "numeric", + "java": "bigdecimal", + "length": true, + "prec": true + }, + { + "type": ["float","double"], + "sqream": "double", + "java": "double", + "length": false + }, + { + "type": ["clob"], + "sqream": "text", + "java": "clob", + "length": false + }, + { + "type": ["blob"], + "sqream": "text", + "java": "blob", + "length": false + } + ] + } + +CLI Examples +============ + +Loading data into a CDC table using the ``type`` and ``limit`` parameters: + +.. code-block:: console + + java -jar sqloader.jar -table source_table_name -type cdc -limit 100 + +Loading data into a table using your own configuration file (this will override the default configuration file): + +.. code-block:: console + + java -jar sqloader.jar -config path/to/your/config/file + +Loading data into a table using a custom configuration file: + +.. code-block:: console + + java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false + +Loading data into a table using a the ``filter`` parameter: + +.. code-block:: console + + java -jar sqloader.jar -table source_table_name -filter column_name>50 From d09f360b6a250e591ffa09826b3d5cf247033a93 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 May 2024 16:37:54 +0300 Subject: [PATCH 1316/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 54 +++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 669fabd70..9fb0da47c 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -138,25 +138,31 @@ When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. -Supported Post Requests +Supported POST Requests ----------------------- .. list-table:: :widths: auto :header-rows: 1 - * - Post + * - POST - Description + - Example * - ``load`` - Send request to service and return + - * - ``syncLoad`` - Send request to service and return once the request is done + - * - ``filterLogs`` - Get logs for a specific request id + - * - ``getActiveLoads`` - Get a list of all active loads currently running in shared queue + - * - ``cancelRequest`` - Cancel an ``async`` request by request id + - Loading Data into SQreamDB Tables --------------------------------- @@ -395,7 +401,49 @@ Using the ``type`` parameter you may define a loading type that affects the tabl - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only - +Using the SQLoader Java Service Web Interface +================================================== + +The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. + +Initiating SQLoader Service Web Interface +----------------------------------------- + +.. code-block:: + + java -jar sqloader-admin-server-0.0.1-SNAPSHOT.jar --server.port=<PORT> Default 7070 + +The SQLoader Service should utilize the ``--spring.boot.admin.client.url`` flag to connect to the admin server. + +Example: + +.. code-block:: + + java -jar sqloaderService-8.0.jar --spring.boot.admin.client.url=http://localhost:7070 + +Grouping Services +----------------- + +Hazelcast cluster name refers to a group of interconnected Hazelcast instances across different JVMs or machines. By default, these instances automatically connect to the same cluster on the network, enabling all SQLoader services within a network to connect to each other and share the same queue. To exert control over how services are grouped, you can use the ``--hzClusterName=<TEXT>`` flag. + +Example: + +.. code-block:: + + +SQLoader Service Web Interface Features +--------------------------------------- + +* Monitor Services: + + * Health Checks: Monitor the health status of services to ensure they are functioning properly. + * Metrics: Monitor real-time performance metrics, including CPU usage, memory usage, and response times. + * Logging: View logs generated by services for troubleshooting and debugging purposes, and dynamically modify log levels during runtime to adjust verbosity for troubleshooting or performance monitoring. + +* Manage Active Load Requests: + + * View a list of currently active data loading requests, including their status, progress, and relevant metadata. + Creating Summary Tables ======================== From 8e4ff357293480935344fab5a944f6d1803b9ed9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 12 May 2024 16:40:43 +0300 Subject: [PATCH 1317/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 9fb0da47c..3e59f4b58 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -122,7 +122,7 @@ When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, export DEFAULT_PROPERTIES=/home/avivs/branches/java/sqloader-service/config/sqload-jdbc.properties - Followed by service execution: + Followed by service execution: .. code-block:: From b11e8d5206f6d346c79f3da6b484bbaf6aea00c2 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 08:42:22 +0300 Subject: [PATCH 1318/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 3e59f4b58..c7d40e5bc 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -4,9 +4,15 @@ External Databases ****************** -The **SQLoader** is a java service that enables you to load data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. +The **SQLoader** is a Java service that enables you to ingest data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. -**SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. +**SQLoader** supports ingesting data from the following DBMSs: + +* Oracle +* Postgresql +* Teradata +* Microsoft SQL Server +* SAP HANA .. contents:: :local: @@ -18,8 +24,8 @@ Before You Begin It is essential that you have the following: * Java 17 -* SQLoader configuration files -* SQLoader.jar file +* :ref:`SQLoader configuration files<getting_the_sqloader_configuration_and_jar_files>` +* :ref:`SQLoader.jar file<getting_the_sqloader_configuration_and_jar_files>` @@ -42,7 +48,9 @@ Minimum Hardware Requirements Sizing Guidelines ------------------ -The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, hence for performance efficiency, considering the table's partition count when managing thread allocation is a must. + +.. _getting_the_sqloader_configuration_and_jar_files: Getting the SQLoader Configuration and JAR Files ================================================ From 6d9002bb360d7ed650680de2e1f6a10cd740ff53 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 11:31:51 +0300 Subject: [PATCH 1319/1892] Create aws_sqreamdb_architecture.png --- _static/images/aws_sqreamdb_architecture.png | Bin 0 -> 267137 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 _static/images/aws_sqreamdb_architecture.png diff --git a/_static/images/aws_sqreamdb_architecture.png b/_static/images/aws_sqreamdb_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..5d464318a227c382358d814ffabbdce36dbe57fc GIT binary patch literal 267137 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 literal 0 HcmV?d00001 From 3e58314adeb76b2cf69521777162c7abccff94f5 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 11:38:11 +0300 Subject: [PATCH 1320/1892] Create aws_architecture --- architecture/aws_architecture | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 architecture/aws_architecture diff --git a/architecture/aws_architecture b/architecture/aws_architecture new file mode 100644 index 000000000..14349a9ab --- /dev/null +++ b/architecture/aws_architecture @@ -0,0 +1,15 @@ +.. _aws_architecture: + +*********************** +SQreamDB on Marketplace +*********************** + + +SQreamDB on AWS Marketplace is a transactional private cloud that enables full management of sensitive data and transactions within a dedicated cloud environment, ensuring high performance, enhanced security, and compliance with industry standards. + +The following diagram describes how SQDB is deployed on AWS infrastructure. + + + +.. figure:: /_static/images/aws_sqreamdb_architecture.png + :scale: 60 % From 5b8fd9d06345bb28615b9657f007293863efdf63 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 11:57:28 +0300 Subject: [PATCH 1321/1892] rst --- architecture/{aws_architecture => aws_architecture.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename architecture/{aws_architecture => aws_architecture.rst} (100%) diff --git a/architecture/aws_architecture b/architecture/aws_architecture.rst similarity index 100% rename from architecture/aws_architecture rename to architecture/aws_architecture.rst From b17a102c0cf061a91aa9febd7e7f20e38db4bf7a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 12:05:37 +0300 Subject: [PATCH 1322/1892] Update aws_architecture.rst --- architecture/aws_architecture.rst | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/architecture/aws_architecture.rst b/architecture/aws_architecture.rst index 14349a9ab..f9f2c50f7 100644 --- a/architecture/aws_architecture.rst +++ b/architecture/aws_architecture.rst @@ -1,11 +1,10 @@ .. _aws_architecture: -*********************** -SQreamDB on Marketplace -*********************** +**************** +AWS Architecture +**************** - -SQreamDB on AWS Marketplace is a transactional private cloud that enables full management of sensitive data and transactions within a dedicated cloud environment, ensuring high performance, enhanced security, and compliance with industry standards. +SQreamDB on AWS private cloud deployment enables full management of sensitive data and transactions within a dedicated cloud environment. The following diagram describes how SQDB is deployed on AWS infrastructure. From a4d28c6afa208160846d145af296bba01b82c085 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 12:46:05 +0300 Subject: [PATCH 1323/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index c7d40e5bc..96844c2fd 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -48,7 +48,7 @@ Minimum Hardware Requirements Sizing Guidelines ------------------ -The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, hence for performance efficiency, considering the table's partition count when managing thread allocation is a must. +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. .. _getting_the_sqloader_configuration_and_jar_files: @@ -117,8 +117,8 @@ The ``sqload-jdbc.properties`` file contains a connection string that must be co :caption: Properties File Sample :linenos: -Using SQLoader Service -====================== +Deploying SQLoader Service +========================== When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, which corresponds to the default ``sqload-jdbc.properties`` file. @@ -136,7 +136,7 @@ When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, java -jar target/sqloaderService-8.0.jar -* Appending to -D flag when executing the jar: +* Appending to ``-D`` flag when executing the JAR file: .. code-block:: @@ -157,19 +157,19 @@ Supported POST Requests - Description - Example * - ``load`` - - Send request to service and return + - Sends a request to the service and returns immediately - * - ``syncLoad`` - - Send request to service and return once the request is done + - Sends a request to the service and returns once the request is complete - * - ``filterLogs`` - - Get logs for a specific request id + - Retrieves logs for a specific request ID - * - ``getActiveLoads`` - - Get a list of all active loads currently running in shared queue + - Returns a list of all active loads currently running in the shared queue - * - ``cancelRequest`` - - Cancel an ``async`` request by request id + - Cancels an active request by request ID - Loading Data into SQreamDB Tables @@ -333,6 +333,11 @@ Loading Data into SQreamDB Tables - - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. + * - ``-port`` + - Optional + - ``6060`` + - + - * - ``-rowid`` - Optional - ``false`` From 0dc7afdbbaf62540697bb1e9e24a4410bcf58c90 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 13:49:56 +0300 Subject: [PATCH 1324/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 96844c2fd..e2669a0db 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -59,13 +59,13 @@ Getting the SQLoader Configuration and JAR Files .. code-block:: linux - curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.12.tar + curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v8.0.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: linux - tar -xf sqloader-7.12.tar.gz + tar -xf sqloader-8.0.tar.gz A folder named ``sqloader`` with the following files is created: From 140f8d8f3de6115ec9fc5eb4ef0c9a844080bf43 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 14:42:11 +0300 Subject: [PATCH 1325/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index e2669a0db..b4103fe2c 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -467,13 +467,16 @@ Summary tables are part of the schema within the database catalog. Creating a Summary Table -------------------------- -This summary table uses Oracle syntax. +The following summary table DDL uses Oracle syntax. -Moving to SQLoader service, add the following column: +.. note:: -.. code-block: sql + If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following columns to your existing summary table instead of re-creating it. - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + .. code-block:: sql + + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUEST_HASH TEXT (200 BYTE) VISIBLE DEFAULT NULL .. code-block:: sql From 02c5b227da9ea36a98a14e397982f026b0cfa974 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 19 May 2024 15:10:47 +0300 Subject: [PATCH 1326/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 174 +++++++++++------- 1 file changed, 104 insertions(+), 70 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index b4103fe2c..43cd69df6 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -8,11 +8,12 @@ The **SQLoader** is a Java service that enables you to ingest data into SQreamDB **SQLoader** supports ingesting data from the following DBMSs: +* Microsoft SQL Server * Oracle * Postgresql -* Teradata -* Microsoft SQL Server * SAP HANA +* Sybase +* Teradata .. contents:: :local: @@ -571,7 +572,35 @@ Data Type Mapping Automatic Mapping ------------------ -The **SQLoader** automatically maps data types used in Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA tables that are loaded into SQreamDB. +The **SQLoader** automatically maps data types used in Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. + +Microsoft SQL Server +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Microsoft SQL Server Type + - SQreamDB Type + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` + - ``TEXT`` + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL`` + - ``REAL`` + * - ``VARBINARY`` + - ``TEXT`` Oracle ^^^^^^^ @@ -606,9 +635,8 @@ Oracle - ``TEXT`` - Postgresql -^^^^^^^^^^^ +^^^^^^^^^^ .. list-table:: :widths: auto @@ -635,72 +663,8 @@ Postgresql * - ``REAL``, ``FLOAT4`` - ``REAL`` -Teradata -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Teradata Type - - SQreamDB Type - * - ``F`` - - ``DOUBLE`` - * - ``N``, ``D`` - - ``NUMERIC`` - * - ``CO`` - - ``TEXT`` - * - ``BO`` - - ``TEXT`` - * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - - ``TEXT`` - * - ``I``, ``I4``, ``I(4)`` - - ``INT`` - * - ``I2``, ``I(2)`` - - ``SMALLINT`` - * - ``I1``, ``I(1)`` - - ``TINYINT`` - * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - - ``BIGINT`` - * - ``TS``, ``DATETIME`` - - ``DATETIME`` - * - ``DA`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``REAL``, ``DOUBLE`` - - ``DOUBLE`` - -Microsoft SQL Server -^^^^^^^^^^^^^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Microsoft SQL Server Type - - SQreamDB Type - * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - - ``TEXT`` - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL`` - - ``REAL`` - * - ``VARBINARY`` - - ``TEXT`` - SAP HANA -^^^^^^^^^ +^^^^^^^^ .. list-table:: :widths: auto @@ -747,6 +711,76 @@ SAP HANA * - ``REAL`` - ``REAL`` +Sybase +^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Sybase Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``LONG VARCHAR``, ``CHARACTER``, ``TEXT`` + - ``TEXT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT``, ``INTEGER`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``NUMERIC(126,38)`` + - ``NUMERIC(38,10)`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``DATETIME``, ``TIMESTAMP``, ``TIME`` + - ``DATETIME`` + * - ``BIT`` + - ``BOOL`` + * - ``VARBINARY``, ``BINARY``, ``LONG BINARY`` + - ``TEXT`` + +Teradata +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Teradata Type + - SQreamDB Type + * - ``F`` + - ``DOUBLE`` + * - ``N``, ``D`` + - ``NUMERIC`` + * - ``CO`` + - ``TEXT`` + * - ``BO`` + - ``TEXT`` + * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` + - ``TEXT`` + * - ``I``, ``I4``, ``I(4)`` + - ``INT`` + * - ``I2``, ``I(2)`` + - ``SMALLINT`` + * - ``I1``, ``I(1)`` + - ``TINYINT`` + * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` + - ``BIGINT`` + * - ``TS``, ``DATETIME`` + - ``DATETIME`` + * - ``DA`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``REAL``, ``DOUBLE`` + - ``DOUBLE`` + Manually Adjusting Mapping ---------------------------- From f2b8bc4e9df2b597c3d8f14ddf7f47b68587118a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 09:43:41 +0300 Subject: [PATCH 1327/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 297 +++++++++++------- 1 file changed, 176 insertions(+), 121 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 43cd69df6..88d04a882 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -8,6 +8,7 @@ The **SQLoader** is a Java service that enables you to ingest data into SQreamDB **SQLoader** supports ingesting data from the following DBMSs: +* Greenplum * Microsoft SQL Server * Oracle * Postgresql @@ -28,8 +29,6 @@ It is essential that you have the following: * :ref:`SQLoader configuration files<getting_the_sqloader_configuration_and_jar_files>` * :ref:`SQLoader.jar file<getting_the_sqloader_configuration_and_jar_files>` - - Minimum Hardware Requirements ------------------------------ @@ -49,12 +48,17 @@ Minimum Hardware Requirements Sizing Guidelines ------------------ -The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader request runs on a single table, meaning concurrent imports of multiple tables require multiple requests. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. + +Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + +Setup and Connectivity +====================== .. _getting_the_sqloader_configuration_and_jar_files: Getting the SQLoader Configuration and JAR Files -================================================ +------------------------------------------------ 1. Download the ``.tar`` file using the following command: @@ -86,14 +90,14 @@ A folder named ``sqloader`` with the following files is created: - The SQLoader package file Connection String -================= +----------------- -The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. +It is recommended that the ``sqload-jdbc.properties`` file will contain a connection string. 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: - a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings + a. Either Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase, Teradata, or SQreamDB connection strings b. Optionally, Oracle or SQreamDB catalogs (recommended) .. list-table:: Connection String Parameters @@ -118,8 +122,11 @@ The ``sqload-jdbc.properties`` file contains a connection string that must be co :caption: Properties File Sample :linenos: +SQLoader Service Deployment and Interface +========================================= + Deploying SQLoader Service -========================== +-------------------------- When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, which corresponds to the default ``sqload-jdbc.properties`` file. @@ -129,97 +136,115 @@ When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, .. code-block:: - export DEFAULT_PROPERTIES=/home/avivs/branches/java/sqloader-service/config/sqload-jdbc.properties + export DEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties Followed by service execution: .. code-block:: - java -jar target/sqloaderService-8.0.jar + java -jar sqloaderService-8.0.jar * Appending to ``-D`` flag when executing the JAR file: .. code-block:: - java -jar -DDEFAULT_PROPERTIES=/home/avivs/branches/java/sqloader-service/config/sqload-jdbc.properties target/sqloaderService-8.0.jar + java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloaderService-8.0.jar .. note:: ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. -Supported POST Requests ------------------------ +Supported HTTP Requests +^^^^^^^^^^^^^^^^^^^^^^^ .. list-table:: :widths: auto :header-rows: 1 - * - POST + * - Request Type + - Request Name + - cURL Command - Description - Example - * - ``load`` - - Sends a request to the service and returns immediately - - - * - ``syncLoad`` + * - POST + - ``load`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/load`` + - Sends a request to the service and returns immediately. This HTTP request is utilized within a load-balancing queue shared across multiple instances. This setup ensures efficient resource utilization by distributing incoming load requests evenly across all available instances. Additionally, the system incorporates :ref:`high availability<high_availability>` mechanisms to recover failed jobs in case an instance crashes, ensuring continuous operation and reliability even during instance failures. Note that if all instances crash, at least one instance must remain operational to recover and execute pending jobs. + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/load`` + * - POST + - ``syncLoad`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/syncLoad`` - Sends a request to the service and returns once the request is complete - - - * - ``filterLogs`` + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/syncLoad`` + * - POST + - ``filterLogs`` + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"", "outputFilePath": ""}' http://127.0.0.1:6060/filterLogs`` - Retrieves logs for a specific request ID - - - * - ``getActiveLoads`` + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"request-1-6a2884a3", "outputFilePath": "/home/avivs/sqloader_request.log"}' http://127.0.0.1:6060/filterLogs`` + * - GET + - ``getActiveLoads`` + - ``curl --header "Content-Type: application/json" --request GET http://127.0.0.1:6060/getActiveLoads`` - Returns a list of all active loads currently running in the shared queue - - * - ``cancelRequest`` + * - GET + - ``cancelRequest`` + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/<RequestId>`` - Cancels an active request by request ID - - + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/request-2-6aa3c53d`` -Loading Data into SQreamDB Tables ---------------------------------- +.. _high_availability: -1. Run the ``sqloader.jar`` file using the following CLI command: +High Availability +^^^^^^^^^^^^^^^^^ -.. code-block:: console +SQLoader as a service supports high availability for asynchronous load requests only. When a service crashes, another service will take over the tasks and execute them from the beginning. However, there are some limited cases where high availability will not provide coverage: - java -jar sqloader.jar - -2. You may load the entire data of a source table using the following CLI command: +* **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. -.. code-block:: console +* **Clustered flag requirement**: The ``clustered`` flag must be set to ``true`` to enable high availability. - java -jar sqloader.jar -table source_table_name - -3. You may customize the data load either by using each of the following parameters within a CLI command or by configuring the ``properties`` file: +* **Limitations for specific tasks**: A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. Re-running the task could lead to data corruption. + +This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. + +SQLoader Service Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^ -.. list-table:: SQLoader Service Parameters +.. list-table:: :widths: auto :header-rows: 1 - * - CLI Parameter + * - HTTP Parameter - State - Default - Type - Description - * - ``-configFile`` + * - ``clustered`` - Optional - - ``sqload-jdbc.properties`` + - ``true`` - - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI. If not specified, the service will use ``DEFAULT_PROPERTIES`` parameter - * - ``-connectionStringSqream`` + - This flag is relevant only for ``load`` requests (``async``), not for ``syncLoad``. Note that this flag affects :ref:`high availability<high_availability>`. When set to ``true``: the request is directed to one of the available instances within a cluster, often through a load balancer. When set to ``false``: the request goes directly to the specified host without load balancing. + * - ``configFile`` - Optional + - ``sqload-jdbc.properties`` + - + - Defines the path to the configuration file you wish to use. If not specified, the service will use ``DEFAULT_PROPERTIES`` parameter + * - ``connectionStringSqream`` + - Mandatory - - - JDBC connection string to SQreamDB - * - ``-connectionStringSource`` - - Optional + * - ``connectionStringSource`` + - Mandatory - - - JDBC connection string to source database - * - ``-connectionStringCatalog`` - - Optional + * - ``connectionStringCatalog`` + - Mandatory - - - JDBC connection string to catalog database - * - ``-cdcCatalogTable`` + * - ``cdcCatalogTable`` - Optional - - @@ -239,22 +264,22 @@ Loading Data into SQreamDB Tables - - - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load - * - ``-batchSize`` + * - ``batchSize`` - Optional - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. - * - ``-caseSensitive`` + * - ``caseSensitive`` - Optional - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB - * - ``-checkCdcChain`` + * - ``checkCdcChain`` - Optional - ``false`` - - Check CDC chain between tracking table and source table - * - ``-chunkSize`` + * - ``chunkSize`` - Optional - ``0`` - @@ -264,139 +289,163 @@ Loading Data into SQreamDB Tables - - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` - * - ``-columns`` + * - ``columns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true - * - ``-configDir`` + * - ``configDir`` - Optional - - ``java -jar target/sqloaderService-8.0.jar --configDir=</path/to/directory/>`` + - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file - * - ``-count`` + * - ``count`` - Optional - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB - * - ``-cdcDelete`` + * - ``cdcDelete`` - Optional - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows - * - ``-drop`` + * - ``drop`` - Optional - ``true`` - - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``-target`` parameter - * - ``-fetchSize`` + - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter + * - ``fetchSize`` - Optional - ``100000`` - - The number of records to be read at once from source database. - * - ``-filter`` + * - ``filter`` - Optional - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded - * - ``-h, --help`` + * - ``h, help`` - Optional - - - Displays the help menu and exits - * - ``-limit`` + * - ``--hzClusterName=<TEXT>`` + - Optional + - + - + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. + + An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. + * - ``limit`` - Optional - ``0`` (no limit) - - Limits the number of rows to be loaded - * - ``-loadDttm`` + * - ``loadDttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading - * - ``-lockCheck`` + * - ``loadTypeName`` + - Optional + - ``full`` + - + - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle + * - ``lockCheck`` - Optional - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts - * - ``-lockTable`` + * - ``lockTable`` - Optional - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts - * - ``-log_dir`` + * - ``log_dir`` - Optional - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory target/sqloaderService-8.0.jar`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file - * - ``-partitionName`` + * - ``partitionName`` - Optional - - Partition identifier ``string`` - - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. - * - ``-port`` + - Specifies the number of table partitions. If configured, ``partition`` ensures that data is loaded according to the specified partition. You may configure the ``thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. + * - ``port`` - Optional - ``6060`` - - - * - ``-rowid`` + * - ``rowid`` - Optional - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables - * - ``-sourceDatabaseName`` + * - ``sourceDatabaseName`` - Optional - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. - * - ``-splitByColumn`` + * - ``splitByColumn`` - Optional - - Column name ``string`` - Column name for split (required for multi-thread loads) - * - ``-sourceTable`` + * - ``sourceTable`` - Mandatory - - Table name ``string`` - Source table name to load data from - * - ``-sqreamTable`` + * - ``--spring.boot.admin.client.url`` + - Mandatory + - ``http://localhost:7070`` + - + - SQLoader admin server connection flag + * - ``sqreamTable`` - Optional - Target table name - Table name ``string`` - Target table name to load data into - * - ``-threadCount`` + * - ``threadCount`` - Optional - ``1`` - - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` - * - ``-truncate`` + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` + * - ``truncate`` - Optional - ``false`` - - Truncate target table before loading - * - ``-loadTypeName`` + * - ``typeMappingPath`` - Optional - - ``full`` + - ``config/sqream-mapping.json`` - - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle - * - ``-useDbmsLob`` + - A mapping file that converts source data types into SQreamDB data types. + * - ``useDbmsLob`` - Optional - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types - * - ``-usePartitions`` + * - ``usePartitions`` - Optional - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements - --- Add new flags, review new description and CamelCase for all flags. --- All new flags are optional + * - ``validateSourceTable`` + - Optional + - ``true`` + - + - Allows control over the validation of table existence during the load. + * - ``Xmx`` + - Optional + - + - + - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` -Using the ``type`` Parameter -^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Using the ``loadTypeName`` Parameter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Using the ``type`` parameter you may define a loading type that affects the table that is created in SQreamDB. +Using the ``loadTypeName`` parameter you may define a loading type that affects the table that is created in SQreamDB. .. list-table:: :widths: auto @@ -416,18 +465,20 @@ Using the ``type`` parameter you may define a loading type that affects the tabl - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only Using the SQLoader Java Service Web Interface -================================================== +--------------------------------------------- The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. Initiating SQLoader Service Web Interface ------------------------------------------ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The default port number is ``7070`` .. code-block:: - java -jar sqloader-admin-server-0.0.1-SNAPSHOT.jar --server.port=<PORT> Default 7070 + java -jar sqloader-admin-server-1.0.jar --server.port=<PORT> -The SQLoader Service should utilize the ``--spring.boot.admin.client.url`` flag to connect to the admin server. +Use the ``--spring.boot.admin.client.url`` flag to connect to the admin server. Example: @@ -436,7 +487,7 @@ Example: java -jar sqloaderService-8.0.jar --spring.boot.admin.client.url=http://localhost:7070 Grouping Services ------------------ +^^^^^^^^^^^^^^^^^ Hazelcast cluster name refers to a group of interconnected Hazelcast instances across different JVMs or machines. By default, these instances automatically connect to the same cluster on the network, enabling all SQLoader services within a network to connect to each other and share the same queue. To exert control over how services are grouped, you can use the ``--hzClusterName=<TEXT>`` flag. @@ -446,7 +497,7 @@ Example: SQLoader Service Web Interface Features ---------------------------------------- +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Monitor Services: @@ -513,7 +564,8 @@ The following summary table DDL uses Oracle syntax. TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL, - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL, + REQUEST_HASH TEXT (200 BYTE) VISIBLE DEFAULT NULL ); @@ -572,7 +624,35 @@ Data Type Mapping Automatic Mapping ------------------ -The **SQLoader** automatically maps data types used in Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. +The **SQLoader** automatically maps data types used in Greenplum, Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. + +Greenplum +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Greenplum Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` Microsoft SQL Server ^^^^^^^^^^^^^^^^^^^^^ @@ -871,29 +951,4 @@ In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGIN ] } -CLI Examples -============ - -Loading data into a CDC table using the ``type`` and ``limit`` parameters: - -.. code-block:: console - - java -jar sqloader.jar -table source_table_name -type cdc -limit 100 - -Loading data into a table using your own configuration file (this will override the default configuration file): - -.. code-block:: console - - java -jar sqloader.jar -config path/to/your/config/file - -Loading data into a table using a custom configuration file: - -.. code-block:: console - - java -jar -config MyConfigFile.properties -table source_table_name -type cdc -target target_table_name -drop true -lock_check false - -Loading data into a table using a the ``filter`` parameter: - -.. code-block:: console - java -jar sqloader.jar -table source_table_name -filter column_name>50 From 75c4c771083ed8576300a4690896c323c071fb14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 12:14:45 +0300 Subject: [PATCH 1328/1892] Update index.rst --- connecting_to_sqream/client_drivers/trino/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/trino/index.rst b/connecting_to_sqream/client_drivers/trino/index.rst index 72b6ef35a..cd424a57f 100644 --- a/connecting_to_sqream/client_drivers/trino/index.rst +++ b/connecting_to_sqream/client_drivers/trino/index.rst @@ -4,7 +4,7 @@ Trino ***** -If you are using Trino for distributed SQL query processing and wish to use it to connect to BLUE, follow these instructions. +If you are using Trino for distributed SQL query processing and wish to use it to connect to SQreamDB, follow these instructions. .. contents:: From 0d0a0bedfb1e448a389a0d153c0f01d898bc8795 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 15:01:31 +0300 Subject: [PATCH 1329/1892] Update ingesting_from_databases_2.rst --- data_ingestion/ingesting_from_databases_2.rst | 225 ++++++------------ 1 file changed, 68 insertions(+), 157 deletions(-) diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 88d04a882..b8018a4b0 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -125,35 +125,6 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec SQLoader Service Deployment and Interface ========================================= -Deploying SQLoader Service --------------------------- - -When the service initializes, it looks for the variable ``DEFAULT_PROPERTIES``, which corresponds to the default ``sqload-jdbc.properties`` file. - -``DEFAULT_PROPERTIES`` can be configured using one of two ways: - -* Setting as an environment variable: - - .. code-block:: - - export DEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties - - Followed by service execution: - - .. code-block:: - - java -jar sqloaderService-8.0.jar - -* Appending to ``-D`` flag when executing the JAR file: - - .. code-block:: - - java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloaderService-8.0.jar - - .. note:: - - ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. - Supported HTTP Requests ^^^^^^^^^^^^^^^^^^^^^^^ @@ -195,20 +166,60 @@ Supported HTTP Requests .. _high_availability: High Availability -^^^^^^^^^^^^^^^^^ +----------------- SQLoader as a service supports high availability for asynchronous load requests only. When a service crashes, another service will take over the tasks and execute them from the beginning. However, there are some limited cases where high availability will not provide coverage: * **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. -* **Clustered flag requirement**: The ``clustered`` flag must be set to ``true`` to enable high availability. +* **Clustered flag requirement**: The SQLoader ``clustered`` flag must be set to ``true`` to enable high availability. * **Limitations for specific tasks**: A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. Re-running the task could lead to data corruption. This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. -SQLoader Service Parameters -^^^^^^^^^^^^^^^^^^^^^^^^^^^ +SQLoader Deployment Parameters +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Default + - Type + - Description + * - ``configDir`` + - Optional + - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` + - + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file + * - ``--hzClusterName=<TEXT>`` + - Optional + - + - + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. + + An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. + * - ``log_dir`` + - Optional + - ``logs`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``--spring.boot.admin.client.url`` + - Optional + - ``http://localhost:7070`` + - + - SQLoader admin server connection flag + * - ``Xmx`` + - Optional + - + - + - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + +SQLoader Request Parameters +--------------------------- .. list-table:: :widths: auto @@ -228,7 +239,7 @@ SQLoader Service Parameters - Optional - ``sqload-jdbc.properties`` - - - Defines the path to the configuration file you wish to use. If not specified, the service will use ``DEFAULT_PROPERTIES`` parameter + - Defines the path to the configuration file you wish to use. If not specified, the service will use the default path provided upon service deployment. * - ``connectionStringSqream`` - Mandatory - @@ -294,11 +305,6 @@ SQLoader Service Parameters - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true - * - ``configDir`` - - Optional - - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` - - - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file * - ``count`` - Optional - ``true`` @@ -329,13 +335,6 @@ SQLoader Service Parameters - - - Displays the help menu and exits - * - ``--hzClusterName=<TEXT>`` - - Optional - - - - - - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. - - An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. * - ``limit`` - Optional - ``0`` (no limit) @@ -361,11 +360,6 @@ SQLoader Service Parameters - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts - * - ``log_dir`` - - Optional - - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``partitionName`` - Optional - @@ -396,11 +390,6 @@ SQLoader Service Parameters - - Table name ``string`` - Source table name to load data from - * - ``--spring.boot.admin.client.url`` - - Mandatory - - ``http://localhost:7070`` - - - - SQLoader admin server connection flag * - ``sqreamTable`` - Optional - Target table name @@ -436,16 +425,13 @@ SQLoader Service Parameters - ``true`` - - Allows control over the validation of table existence during the load. - * - ``Xmx`` - - Optional - - - - - - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + +.. _load_type_name: Using the ``loadTypeName`` Parameter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Using the ``loadTypeName`` parameter you may define a loading type that affects the table that is created in SQreamDB. +Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. .. list-table:: :widths: auto @@ -463,39 +449,20 @@ Using the ``loadTypeName`` parameter you may define a loading type that affects * - Incremental - ``inc`` - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only - -Using the SQLoader Java Service Web Interface ---------------------------------------------- - -The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. - -Initiating SQLoader Service Web Interface -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -The default port number is ``7070`` - -.. code-block:: - - java -jar sqloader-admin-server-1.0.jar --server.port=<PORT> -Use the ``--spring.boot.admin.client.url`` flag to connect to the admin server. -Example: -.. code-block:: + +Using the SQLoader Java Service Web Interface +--------------------------------------------- - java -jar sqloaderService-8.0.jar --spring.boot.admin.client.url=http://localhost:7070 +The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. Grouping Services ^^^^^^^^^^^^^^^^^ Hazelcast cluster name refers to a group of interconnected Hazelcast instances across different JVMs or machines. By default, these instances automatically connect to the same cluster on the network, enabling all SQLoader services within a network to connect to each other and share the same queue. To exert control over how services are grouped, you can use the ``--hzClusterName=<TEXT>`` flag. -Example: - -.. code-block:: - - SQLoader Service Web Interface Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -509,26 +476,25 @@ SQLoader Service Web Interface Features * View a list of currently active data loading requests, including their status, progress, and relevant metadata. -Creating Summary Tables -======================== - -Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. +Creating Summary and Catalog Tables +=================================== -Summary tables are part of the schema within the database catalog. +The summary and catalog tables are pre-aggregated tables that store summarized or aggregated data. Creating a Summary Table --------------------------- +------------------------ + +The summary table is part of the schema within the database catalog. The following summary table DDL uses Oracle syntax. .. note:: - If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following columns to your existing summary table instead of re-creating it. + If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following column to your existing summary table instead of re-creating it. .. code-block:: sql REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL - REQUEST_HASH TEXT (200 BYTE) VISIBLE DEFAULT NULL .. code-block:: sql @@ -564,15 +530,18 @@ The following summary table DDL uses Oracle syntax. TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, HOST VARCHAR2(200) DEFAULT NULL, - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL, - REQUEST_HASH TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL ); -Creating a Change Data Capture Table --------------------------------------- +Creating Catalog Tables +----------------------- + +CDC (Change Data Capture) and Incremental tables are database tables that record changes made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. + +See :ref:`load_type_name` -Change Data Capture (CDC) tables are supported only for Oracle. +Change Data Capture (CDC) and Incremental tables are supported only for Oracle. .. code-block:: sql @@ -891,64 +860,6 @@ In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGIN } } -.. code-block:: json - - { - "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], - "sqream": "text", - "java": "string", - "length": true - }, - { - "type": ["date","datetime"], - "sqream": "datetime", - "java": "datetime", - "length": false - }, - { - "type": ["timestamp"], - "sqream": "datetime", - "java": "timestamp", - "length": false - }, - { - "type": ["date"], - "sqream": "date", - "java": "datetime", - "length": false - }, - { - "type": ["boolean"], - "sqream": "bool", - "java": "boolean", - "length": false - }, - { - "type": ["number"], - "sqream": "numeric", - "java": "bigdecimal", - "length": true, - "prec": true - }, - { - "type": ["float","double"], - "sqream": "double", - "java": "double", - "length": false - }, - { - "type": ["clob"], - "sqream": "text", - "java": "clob", - "length": false - }, - { - "type": ["blob"], - "sqream": "text", - "java": "blob", - "length": false - } - ] - } + From 75e7435bc45134cb12c3764ecd77e9084b558228 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 15:05:08 +0300 Subject: [PATCH 1330/1892] Update connection_string.java --- data_ingestion/connection_string.java | 73 ++++++++++++--------------- 1 file changed, 33 insertions(+), 40 deletions(-) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java index cb22962d5..f7f7147d8 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.java @@ -1,40 +1,33 @@ -// mandatory! - -// Postgresql, Oracle, Teradata, SAP HANA, Microsoft SQL Server, and SQreamDB Connection Strings - -// postgres -source.jdbc.connectionstring=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> - -// oracle -source.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> - -// teradata -source.jdbc.connectionstring=jdbc:teradata://<HostIp>/DATABASE=<database_name>,DBS_PORT=<port>,user=<user_name>,password=<password> - -// sap hana -source.jdbc.connectionstring=jdbc:sap://<HostIp>:<port>/?user=<user_name>&password=<password> - -// microsoft sql server -source.jdbc.connectionstring=jdbc:sqlserver://<HostIp>:<port>;databaseName=<database_name>;user=<user_name>;password=<password>;encrypt=<true/false>;trustServerCertificate=<true/false> - -// sqream -sqream.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> - -// CDC and Incremental Parameter - -cdc_catalog_table=public.CDC_TABLES -cdc_tracking_table=public.CDC_TRACKING -cdc_primary_keys_table=public.CDC_TABLE_PRIMARY_KEYS - - - -// Optional! - -// Oracle Catalog -// catalog.jdbc.connectionstring=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> - -// SQreamDB Catalog -// catalog.jdbc.connectionstring=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> - -// Summary Parameter -// load_summary_table=public.SQLOAD_SUMMARY \ No newline at end of file +name=connect-jdbc +connectionStringSource=<source database connection string> +connectionStringSqream=<sqreamdb connection string> +connectionStringCatalog=<catalog connection string> + +sourceDatabaseName=<source database name> +sourceSchema=<source schema name> +sourceTable=<source table name> + +filter=1=1 +count=true +limit=2000 +threadCount=1 + +rowid=false +batchSize=500 +fetchSize=100000 +chunkSize=0 +caseSensitive=false + +truncate=true +drop=true +loadTypeName=full +cdcCatalogTable=SMSDW.CDC_TABLES +cdcTrackingTable=SMSDW.CDC_TRACKING +loadSummaryTable=SMSDW.SQLOAD_SUMMARY +cdcPrimaryKeyTable=SMSDW.CDC_TABLE_PRIMARY_KEYS +cdcDelete=true +usePartitions=false +lockCheck=false +lockTable=true +loadDttm=false +useDbmsLob=false From b2a1c8e0ff5f803196e15b09fa1f903e4856a5bc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 16:23:42 +0300 Subject: [PATCH 1331/1892] SQLoader Service --- data_ingestion/connection_string.java | 60 +++- data_ingestion/ingesting_from_databases_2.rst | 298 ++++++++++++++---- 2 files changed, 291 insertions(+), 67 deletions(-) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.java index f7f7147d8..c0f8932af 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.java @@ -1,33 +1,67 @@ -name=connect-jdbc -connectionStringSource=<source database connection string> -connectionStringSqream=<sqreamdb connection string> -connectionStringCatalog=<catalog connection string> +# Postgresql, Oracle, Teradata, SAP HANA, Microsoft SQL Server, Sybase and SQreamDB Connection Strings +# (only one source connection string should be specified) -sourceDatabaseName=<source database name> -sourceSchema=<source schema name> -sourceTable=<source table name> +# postgres (and also Greenplum) +connectionStringSource=jdbc:postgresql://<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> +# oracle +connectionStringSource=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> + +# teradata +connectionStringSource=jdbc:teradata://<HostIp>/DATABASE=<database_name>,DBS_PORT=<port>,user=<user_name>,password=<password> + +# sap hana +connectionStringSource=jdbc:sap://<HostIp>:<port>/?user=<user_name>&password=<password> + +# microsoft sql server +connectionStringSource=jdbc:sqlserver://<HostIp>:<port>;databaseName=<database_name>;user=<user_name>;password=<password>;encrypt=<true/false>;trustServerCertificate=<true/false> + +# sybase +connectionStringSource=jdbc:sybase:Tds:<HostIp>:<port>/<database_name>?user=<user_name>&password=<password> + +# sqream +connectionStringSqream=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> + + + +# Catalog Database Parameters + +# Connection string (only one catalog connection string should be specified) +# Catalog database connection string on Oracle: +connectionStringCatalog=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password> + +# Catalog database connection string on SQreamDB: +connectionStringCatalog=jdbc:Sqream://<HostIp:port>/<database_name>;cluster=<true/false>;user=<user_name>;password=<password> + + + +# CDC and Incremental Parameters +cdcCatalogTable=public.CDC_TABLES +cdcTrackingTable=public.CDC_TRACKING +cdcPrimaryKeyTable=public.CDC_TABLE_PRIMARY_KEYS + +# Summary table +loadSummaryTable=public.SQLOAD_SUMMARY + + + +# OPTIONAL - Data transfer options filter=1=1 count=true limit=2000 threadCount=1 - rowid=false batchSize=500 fetchSize=100000 chunkSize=0 caseSensitive=false - truncate=true drop=true loadTypeName=full -cdcCatalogTable=SMSDW.CDC_TABLES -cdcTrackingTable=SMSDW.CDC_TRACKING -loadSummaryTable=SMSDW.SQLOAD_SUMMARY -cdcPrimaryKeyTable=SMSDW.CDC_TABLE_PRIMARY_KEYS cdcDelete=true usePartitions=false lockCheck=false lockTable=true loadDttm=false useDbmsLob=false +# or any other flag.. \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index b8018a4b0..254c88502 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -52,33 +52,38 @@ The SQLoader sizing is determined by the number of concurrent tables and threads Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` -Setup and Connectivity -====================== +Installation and Connectivity +============================= .. _getting_the_sqloader_configuration_and_jar_files: -Getting the SQLoader Configuration and JAR Files ------------------------------------------------- +Getting All Configuration and JAR Files +--------------------------------------- -1. Download the ``.tar`` file using the following command: +Extract the ``.tar`` file using the following command: .. code-block:: linux - curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v8.0.tar - -2. Extract the ``.tar`` file using the following command: - -.. code-block:: linux - - tar -xf sqloader-8.0.tar.gz + tar -xf sqloader_srv_v8.0.tar.gz A folder named ``sqloader`` with the following files is created: -.. list-table:: SQLoader Files +.. code-block:: + + ├── sqloader-v1.sh + ├── bin + │ ├── sqloader-admin-server-1.0.jar + │ └── sqloader-service-8.0.jar + ├── config + ├── reserved_words.txt + ├── sqload-jdbc.properties + └── sqream-mapping.json + +.. list-table:: :widths: auto :header-rows: 1 - * - File + * - File Name - Description * - ``sqream-mapping.json`` - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion @@ -86,8 +91,231 @@ A folder named ``sqloader`` with the following files is created: - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. - * - ``sqloader.jar`` - - The SQLoader package file + * - ``sqloader-service-8.0.jar`` + - The SQLoader service JAR file + * - ``sqloader-admin-server-1.0.jar`` + - The SQLoader admin server JAR file + * - ``sqloader-v1.sh`` + - SQLoader service installer bash file + +Installation +------------ + +Parameters +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Default + - Type + - Description + * - ``configDir`` + - Optional + - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` + - + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file + * - ``--hzClusterName=<TEXT>`` + - Optional + - + - + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. + * - ``log_dir`` + - Optional + - ``logs`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``--spring.boot.admin.client.url`` + - Optional + - ``http://localhost:7070`` + - + - SQLoader admin server connection flag + * - ``Xmx`` + - Optional + - + - + - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + * - ``DEFAULT_PROPERTIES`` + - Mandatory + - ``sqload-jdbc.properties`` + - + - ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. + +Installing the Admin Server and SQLoader Service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. To install the admin server, run the following command (install it only once on one machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -admin + +Output: + +.. code-block:: + + ################################################################################## + Welcome to SQloader Admin-Service installation + ################################################################################## + Please Enter JAVA_HOME PATH + /opt/java + ################################################################################## + The default PATH to install SQloader Admin Service is /usr/local/sqloader-admin + Do you want to change the default PATH ? (y/N) + ################################################################################## + The default PATH to SQloader-Admin logs directory is /var/log/sqloader-admin/logs + Do you want to change the default? (y/N) + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + SQloader-Admin default port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader-admin/ + LOG_DIR=/var/log/sqloader-admin/ + JAR=sqloader-admin-server-1.0.jar + ADMINPORT=7070 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader-Admin Service installed successfuly ####################### + ################################################################################## + To Start SQLoader-Admin Service: sudo systemctl start sqloader-admin + To View SQLoader-Admin Service status: sudo systemctl status sqloader-admin + ################################################################################## + +2. To start the admin server, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-admin + +3. To verify admin server start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-admin + +4. To install SQLoader service, run the following command (you can install per machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -service + +Output: + +.. code-block:: + + ################################################################################## + Welocome to SQloader service installation + ################################################################################## + Please Enter JAVA_HOME Path + /opt/java + ################################################################################## + The Default PATH to install SQloader Service is /usr/local/sqloader + Do you want to change the default? (y/N) + ################################################################################## + The default PATH to SQloader Service logs directory is /var/log/sqloader-service + Do you want to change The default? (y/N) + ################################################################################## + Please enter SQloader Admin IP address + 192.168.5.234 + ################################################################################## + Please enter SQloader MEM size in GB + 20 + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + Default CONFDIR is /usr/local/sqloader/config , Do you want to change the default CONFDIR ? (y/N) + ################################################################################## + Default SQloader Admin port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + Default SQloader Service port is 6060 , Do you want to change the default port ? (y/N) + ################################################################################## + Default sqload-jdbc.properties is /usr/local/sqloader/config, Do you want to change the default? (y/N) + Using default sqload-jdbc.properties PATH + /usr/local/sqloader/config + ################################################################################## + ################################################################################## + Using /usr/local/sqloader/config/sqload-jdbc.properties + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader/bin + LOG_DIR=/var/log/sqloader-service + CONFDIR=/usr/local/sqloader/config + JAR=sqloader-service-8.0.jar + PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties + PORT=6060 + ADMINIP=192.168.5.234 + ADMINPORT=7070 + MEM=20 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader Service installed successfuly ####################### + ################################################################################## + To Start SQLoader Service: sudo systemctl start sqloader-service + To View SQLoader Service status: sudo systemctl status sqloader-service + ################################################################################## + +5. To start the SQLoader service, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-service + +6. To verify SQLoader service start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-service + +Reconfiguration +--------------- + +You may reconfigure the admin server even after you have started it. + + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-admin.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader-admin/config/sqloader_admin.conf + +2. Restart the admin server: + +.. code-block:: + + sudo systemctl restart sqloader-admin + +You may reconfigure the SQLoader service even after you have started it. + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-service.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader/config/sqloader_service.conf + +2. Restart the admin server: + +.. code-block:: + + sudo systemctl restart sqloader-service Connection String ----------------- @@ -178,45 +406,7 @@ SQLoader as a service supports high availability for asynchronous load requests This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. -SQLoader Deployment Parameters ------------------------------- -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - State - - Default - - Type - - Description - * - ``configDir`` - - Optional - - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` - - - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file - * - ``--hzClusterName=<TEXT>`` - - Optional - - - - - - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. - - An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. - * - ``log_dir`` - - Optional - - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file - * - ``--spring.boot.admin.client.url`` - - Optional - - ``http://localhost:7070`` - - - - SQLoader admin server connection flag - * - ``Xmx`` - - Optional - - - - - - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` SQLoader Request Parameters --------------------------- From bd303d4c55abbd2d3e9044029510f34a30a33725 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 17:16:18 +0300 Subject: [PATCH 1332/1892] SQLoader --- ...tion_string.java => connection_string.txt} | 3 +- data_ingestion/ingesting_from_databases_2.rst | 34 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) rename data_ingestion/{connection_string.java => connection_string.txt} (99%) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.txt similarity index 99% rename from data_ingestion/connection_string.java rename to data_ingestion/connection_string.txt index c0f8932af..9a1f17ebe 100644 --- a/data_ingestion/connection_string.java +++ b/data_ingestion/connection_string.txt @@ -64,4 +64,5 @@ lockTable=true loadDttm=false useDbmsLob=false -# or any other flag.. \ No newline at end of file + +.. more flags \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 254c88502..62b681059 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -104,6 +104,8 @@ Installation Parameters ^^^^^^^^^^ +``-D`` flags are not dynamically adjustable at runtime. + .. list-table:: :widths: auto :header-rows: 1 @@ -118,17 +120,17 @@ Parameters - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file - * - ``--hzClusterName=<TEXT>`` + * - ``hzClusterName=<TEXT>`` - Optional - - - - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. - * - ``log_dir`` + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLLoader instances. + * - ``LOG_DIR`` - Optional - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloaderService-8.0.jar`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file - * - ``--spring.boot.admin.client.url`` + - ``-D`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``spring.boot.admin.client.url`` - Optional - ``http://localhost:7070`` - @@ -141,8 +143,8 @@ Parameters * - ``DEFAULT_PROPERTIES`` - Mandatory - ``sqload-jdbc.properties`` - - - - ``-D`` flags are not dynamically adjustable at runtime. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. + - ``-D`` + - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. Installing the Admin Server and SQLoader Service ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -345,8 +347,8 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec * - ``ssl`` - Specifies SSL for this connection -.. literalinclude:: connection_string.java - :language: java +.. literalinclude:: connection_string.txt + :language: :caption: Properties File Sample :linenos: @@ -373,7 +375,7 @@ Supported HTTP Requests * - POST - ``syncLoad`` - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/syncLoad`` - - Sends a request to the service and returns once the request is complete + - Sends a request to the service and returns once the request is complete. There's no load-balancing queue shared across multiple instances; therefore, it's advised that ``syncLoad`` requests be monitored by the user and not heavily sent. Monitor using the ``getActiveLoads`` cURL. - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/syncLoad`` * - POST - ``filterLogs`` @@ -383,7 +385,7 @@ Supported HTTP Requests * - GET - ``getActiveLoads`` - ``curl --header "Content-Type: application/json" --request GET http://127.0.0.1:6060/getActiveLoads`` - - Returns a list of all active loads currently running in the shared queue + - Returns a list of all active loads currently running across all services - * - GET - ``cancelRequest`` @@ -643,15 +645,11 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang -Using the SQLoader Java Service Web Interface ---------------------------------------------- +Using the SQLoader Service Web Interface +---------------------------------------- The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. -Grouping Services -^^^^^^^^^^^^^^^^^ - -Hazelcast cluster name refers to a group of interconnected Hazelcast instances across different JVMs or machines. By default, these instances automatically connect to the same cluster on the network, enabling all SQLoader services within a network to connect to each other and share the same queue. To exert control over how services are grouped, you can use the ``--hzClusterName=<TEXT>`` flag. SQLoader Service Web Interface Features ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 32c08ecd169cb2ef5e8343aa5f267297d4c18c82 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 17:19:52 +0300 Subject: [PATCH 1333/1892] SQLoader --- .../{connection_string.txt => connection_string.java} | 0 data_ingestion/ingesting_from_databases_2.rst | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename data_ingestion/{connection_string.txt => connection_string.java} (100%) diff --git a/data_ingestion/connection_string.txt b/data_ingestion/connection_string.java similarity index 100% rename from data_ingestion/connection_string.txt rename to data_ingestion/connection_string.java diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/ingesting_from_databases_2.rst index 62b681059..82980b786 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/ingesting_from_databases_2.rst @@ -347,8 +347,8 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec * - ``ssl`` - Specifies SSL for this connection -.. literalinclude:: connection_string.txt - :language: +.. literalinclude:: connection_string.java + :language: java :caption: Properties File Sample :linenos: From bc38d8e714f03ef3c0b8772fca0af06bc0bdc21f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 20 May 2024 18:25:03 +0300 Subject: [PATCH 1334/1892] SQLoader --- data_ingestion/index.rst | 15 ++++++++++++++- data_ingestion/ingesting_from_databases.rst | 6 +++--- ...databases_2.rst => sqloader_as_a_service.rst} | 16 ++++++++++++---- 3 files changed, 29 insertions(+), 8 deletions(-) rename data_ingestion/{ingesting_from_databases_2.rst => sqloader_as_a_service.rst} (97%) diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index ad3e27e93..ab4d25111 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -6,9 +6,21 @@ Data Ingestion Sources The **Data Ingestion Sources** page provides information about the following: +* :ref:`Overview<ingesting_data>` +* :ref:`avro` +* :ref:`csv` +* :ref:`parquet` +* :ref:`orc` +* :ref:`json` +* Loading from external databases: + + * :ref:`SQLoader As a Service<sqloader_as_a_service>` + * :ref:`SQLoader As a Process<ingesting_from_databases>` + .. toctree:: :maxdepth: 1 :glob: + :hidden: ingesting_data avro @@ -16,6 +28,7 @@ The **Data Ingestion Sources** page provides information about the following: parquet orc json + sqloader_as_a_service ingesting_from_databases + -For information about database tools and interfaces that SQream supports, see :ref:`Third Party Tools <connecting_to_sqream>`. \ No newline at end of file diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 87fee4dab..cb24cbf42 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -1,8 +1,8 @@ .. _ingesting_from_databases: -****************** -External Databases -****************** +********************* +SQLoader As a Process +********************* The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. diff --git a/data_ingestion/ingesting_from_databases_2.rst b/data_ingestion/sqloader_as_a_service.rst similarity index 97% rename from data_ingestion/ingesting_from_databases_2.rst rename to data_ingestion/sqloader_as_a_service.rst index 82980b786..7a885c11e 100644 --- a/data_ingestion/ingesting_from_databases_2.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -1,8 +1,8 @@ -.. _ingesting_from_databases_2: +.. _sqloader_as_a_service: -****************** -External Databases -****************** +********************* +SQLoader As a Service +********************* The **SQLoader** is a Java service that enables you to ingest data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. @@ -408,7 +408,15 @@ SQLoader as a service supports high availability for asynchronous load requests This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. +Log Rotation +------------ + +Log rotation is based on time and size. At midnight (00:00) or when the file reaches 100MB, rotation occurs. Rotation means the log file ``SQLoader_service.log`` is renamed to ``SQLoader_service_%d_%i.log`` (%d=date, %i=rotation number), and a new, empty ``SQLoader_service.log`` file is created for the SQLoader service to continue writing to. + +Log Automatic cleanup +^^^^^^^^^^^^^^^^^^^^^ +The maximum number of archived log files to keep is set to 360, so Logback will retain the latest 360 log files in the logs directory. Additionally, the total file size in the directory is limited to 50 GB. If the total size of archived log files exceeds this limit, older log files will be deleted to make room for new ones. SQLoader Request Parameters --------------------------- From 3d7e8bd3a218de25d3ceaeafb00e9d5820f71dae Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 11:19:52 +0300 Subject: [PATCH 1335/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 7a885c11e..9a2f4f2cf 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -313,7 +313,7 @@ Output: EnvironmentFile=/usr/local/sqloader/config/sqloader_service.conf -2. Restart the admin server: +2. Restart the SQLoader service: .. code-block:: From ec895cdead3eea13a0830db41a4a3752c6d689b3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 12:37:39 +0300 Subject: [PATCH 1336/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 9a2f4f2cf..8ffb7d5f5 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -278,6 +278,8 @@ Output: Reconfiguration --------------- +**Admin server** + You may reconfigure the admin server even after you have started it. @@ -299,6 +301,8 @@ Output: sudo systemctl restart sqloader-admin +**SQLoader service** + You may reconfigure the SQLoader service even after you have started it. 1. To get the configuration path, run the following command: @@ -404,7 +408,7 @@ SQLoader as a service supports high availability for asynchronous load requests * **Clustered flag requirement**: The SQLoader ``clustered`` flag must be set to ``true`` to enable high availability. -* **Limitations for specific tasks**: A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. Re-running the task could lead to data corruption. +* **Limitations for specific tasks**: A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. @@ -421,6 +425,8 @@ The maximum number of archived log files to keep is set to 360, so Logback will SQLoader Request Parameters --------------------------- + + .. list-table:: :widths: auto :header-rows: 1 From 8c3100d471afcbd0d4e8d1f7addbdb0056e1d384 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 15:18:34 +0300 Subject: [PATCH 1337/1892] SQLoader Service --- ...tion_string.java => connection_string.ini} | 0 data_ingestion/sqloader_as_a_service.rst | 69 ++++++++++++------- 2 files changed, 43 insertions(+), 26 deletions(-) rename data_ingestion/{connection_string.java => connection_string.ini} (100%) diff --git a/data_ingestion/connection_string.java b/data_ingestion/connection_string.ini similarity index 100% rename from data_ingestion/connection_string.java rename to data_ingestion/connection_string.ini diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 8ffb7d5f5..81429fdfa 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -101,10 +101,13 @@ A folder named ``sqloader`` with the following files is created: Installation ------------ -Parameters -^^^^^^^^^^ +Deployment Parameters +^^^^^^^^^^^^^^^^^^^^^ + +When using the ``sqloader-v1.sh`` file (installer), the following flags are already configured. + +All deployment flags are not dynamically adjustable at runtime. -``-D`` flags are not dynamically adjustable at runtime. .. list-table:: :widths: auto @@ -113,37 +116,37 @@ Parameters * - Parameter - State - Default - - Type + - Example - Description * - ``configDir`` - Optional - - ``java -jar sqloaderService-8.0.jar configDir=</path/to/directory/>`` - - + - ``config`` + - ``java -jar sqloaderService-8.0.jar --configDir=</path/to/directory/>`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file * - ``hzClusterName=<TEXT>`` - Optional - - - - - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLLoader instances. + - ``java -jar sqloader-service-8.0.jar --hzClusterName=<TEXT>`` + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. * - ``LOG_DIR`` - Optional - ``logs`` - - ``-D`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.0.jar`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``spring.boot.admin.client.url`` - Optional - ``http://localhost:7070`` - - + - ``java -jar sqloader-service-8.0.jar --spring.boot.admin.client.url=http://IP:PORT`` - SQLoader admin server connection flag * - ``Xmx`` - Optional - - - + - ``java -jar -Xmx<number>g sqloader-service-8.0.jar`` - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` * - ``DEFAULT_PROPERTIES`` - Mandatory - ``sqload-jdbc.properties`` - - ``-D`` + - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.0.jar`` - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. Installing the Admin Server and SQLoader Service @@ -331,8 +334,9 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec 1. Open the ``sqload-jdbc.properties`` file. 2. Configure connection parameters for: - a. Either Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase, Teradata, or SQreamDB connection strings - b. Optionally, Oracle or SQreamDB catalogs (recommended) + a. The source connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase or Teradata + b. The target connection string: SQreamDB + c. The :ref:`catalog<creating_catalog_tables>` connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, SQreamDB, Sybase, or Teradata .. list-table:: Connection String Parameters :widths: auto @@ -351,13 +355,13 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec * - ``ssl`` - Specifies SSL for this connection -.. literalinclude:: connection_string.java - :language: java +.. literalinclude:: connection_string.ini + :language: ini :caption: Properties File Sample :linenos: -SQLoader Service Deployment and Interface -========================================= +SQLoader Service Interface +========================== Supported HTTP Requests ^^^^^^^^^^^^^^^^^^^^^^^ @@ -406,9 +410,11 @@ SQLoader as a service supports high availability for asynchronous load requests * **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. -* **Clustered flag requirement**: The SQLoader ``clustered`` flag must be set to ``true`` to enable high availability. +* **Limitations for specific tasks**: When any of the following is configured: + + * A task involving a ``clustered`` flag must be set to ``true`` to enable high availability. -* **Limitations for specific tasks**: A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. + * A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. @@ -425,7 +431,7 @@ The maximum number of archived log files to keep is set to 360, so Logback will SQLoader Request Parameters --------------------------- - +Mandatory flags must be configured using HTTP flags or in the ``properties`` file. .. list-table:: :widths: auto @@ -591,14 +597,24 @@ SQLoader Request Parameters - - Column name ``string`` - Column name for split (required for multi-thread loads) + * - ``sourceSchema`` + - Mandatory + - + - + - Source schema name to load data from * - ``sourceTable`` - Mandatory - - Table name ``string`` - Source table name to load data from + * - ``sqreamSchema`` + - Optional + - The schema name defined in the ``sourceSchema`` flag + - + - Target schema name to load data into * - ``sqreamTable`` - Optional - - Target table name + - The table name defined in the ``sourceTable`` flag - Table name ``string`` - Target table name to load data into * - ``threadCount`` @@ -614,7 +630,7 @@ SQLoader Request Parameters * - ``typeMappingPath`` - Optional - ``config/sqream-mapping.json`` - - + - JSON - A mapping file that converts source data types into SQreamDB data types. * - ``useDbmsLob`` - Optional @@ -729,12 +745,13 @@ The following summary table DDL uses Oracle syntax. ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, - TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, - SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, - HOST VARCHAR2(200) DEFAULT NULL, + TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, + SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, + HOST TEXT (200 BYTE) DEFAULT NULL, REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL ); +.. _creating_catalog_tables: Creating Catalog Tables ----------------------- From beae35fa7701ecfdb2b450b6ea0d9341d007c4ea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 15:19:44 +0300 Subject: [PATCH 1338/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 81429fdfa..8963d2122 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -431,7 +431,7 @@ The maximum number of archived log files to keep is set to 360, so Logback will SQLoader Request Parameters --------------------------- -Mandatory flags must be configured using HTTP flags or in the ``properties`` file. +Mandatory flags must be configured using HTTP flags or the ``properties`` file. .. list-table:: :widths: auto From 307ecc239924b623193ac648e734aea0ebdf9948 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 15:43:23 +0300 Subject: [PATCH 1339/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 87e961777..2e666824d 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -417,6 +417,8 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console sudo npm install pm2 -g + cd /usr/bin + sudo ln -s ../local/node-v16.20.0-linux-x64/bin/pm2 pm2 8. If installing the ``pm2`` process management fails, install it offline: From 872397ec794b5c7cf6c4f940a3bdc17a6b4a30b7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 21 May 2024 16:08:14 +0300 Subject: [PATCH 1340/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 44 +----------------------- 1 file changed, 1 insertion(+), 43 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 8963d2122..e407a9984 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -440,212 +440,170 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - HTTP Parameter - State - Default - - Type - Description * - ``clustered`` - Optional - ``true`` - - - This flag is relevant only for ``load`` requests (``async``), not for ``syncLoad``. Note that this flag affects :ref:`high availability<high_availability>`. When set to ``true``: the request is directed to one of the available instances within a cluster, often through a load balancer. When set to ``false``: the request goes directly to the specified host without load balancing. * - ``configFile`` - Optional - ``sqload-jdbc.properties`` - - - Defines the path to the configuration file you wish to use. If not specified, the service will use the default path provided upon service deployment. * - ``connectionStringSqream`` - Mandatory - - - - JDBC connection string to SQreamDB * - ``connectionStringSource`` - Mandatory - - - - JDBC connection string to source database * - ``connectionStringCatalog`` - Mandatory - - - - JDBC connection string to catalog database * - ``cdcCatalogTable`` - Optional - - - - Part of the schema within the catalog database. Holds all inc/cdc tables and their settings * - ``cdcTrackingTable`` - Optional - - - - Part of the schema within the catalog database. Holds the last tracking value for every inc/cdc table from ``cdcCatalogTable`` table * - ``cdcPrimaryKeyTable`` - Optional - - - - Part of the schema within the catalog database. Holds all primary keys for every inc/cdc table from ``cdcCatalogTable`` table * - ``loadSummaryTable`` - - Optional + - Mandatory - - - - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load * - ``batchSize`` - Optional - ``10.000`` - - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. * - ``caseSensitive`` - Optional - ``false`` - - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB * - ``checkCdcChain`` - Optional - ``false`` - - - Check CDC chain between tracking table and source table * - ``chunkSize`` - Optional - ``0`` - - - The number of records read at once from the source database * - ``columnListFilePath`` - Optional - - - ``.txt`` - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` * - ``columns`` - Optional - All columns - - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true * - ``count`` - Optional - ``true`` - - - Defines whether or not table rows will be counted before being loaded into SQreamDB * - ``cdcDelete`` - Optional - ``true`` - - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``drop`` - Optional - ``true`` - - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter * - ``fetchSize`` - Optional - ``100000`` - - - The number of records to be read at once from source database. * - ``filter`` - Optional - ``1=1`` - - - Defines whether or not only records with SQL conditions are loaded * - ``h, help`` - Optional - - - - Displays the help menu and exits * - ``limit`` - Optional - ``0`` (no limit) - - - Limits the number of rows to be loaded * - ``loadDttm`` - Optional - ``true`` - - - Add an additional ``load_dttm`` column that defines the time and date of loading * - ``loadTypeName`` - Optional - ``full`` - - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle * - ``lockCheck`` - Optional - ``true`` - - - Defines whether or not SQLoader will check source table is locked before the loading starts * - ``lockTable`` - Optional - ``true`` - - - Defines whether or not SQLoader will lock target table before the loading starts * - ``partitionName`` - Optional - - - Partition identifier ``string`` - Specifies the number of table partitions. If configured, ``partition`` ensures that data is loaded according to the specified partition. You may configure the ``thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. * - ``port`` - Optional - ``6060`` - - - * - ``rowid`` - Optional - ``false`` - - - Defines whether or not SQLoader will get row IDs from Oracle tables * - ``sourceDatabaseName`` - Optional - ``ORCL`` - - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. * - ``splitByColumn`` - Optional - - - Column name ``string`` - Column name for split (required for multi-thread loads) * - ``sourceSchema`` - Mandatory - - - - Source schema name to load data from * - ``sourceTable`` - Mandatory - - - Table name ``string`` - Source table name to load data from * - ``sqreamSchema`` - Optional - The schema name defined in the ``sourceSchema`` flag - - - Target schema name to load data into * - ``sqreamTable`` - Optional - The table name defined in the ``sourceTable`` flag - - Table name ``string`` - Target table name to load data into * - ``threadCount`` - Optional - ``1`` - - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` * - ``truncate`` - Optional - ``false`` - - - Truncate target table before loading * - ``typeMappingPath`` - Optional - ``config/sqream-mapping.json`` - - JSON - A mapping file that converts source data types into SQreamDB data types. * - ``useDbmsLob`` - Optional - ``true`` - - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types * - ``usePartitions`` - Optional - ``true`` - - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements * - ``validateSourceTable`` - Optional - ``true`` - - - Allows control over the validation of table existence during the load. .. _load_type_name: From 6a54f21194a94874efe2b344a28fcedac5eaf6f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 May 2024 14:38:53 +0300 Subject: [PATCH 1341/1892] Update installing_studio_on_stand_alone_server.rst --- ...nstalling_studio_on_stand_alone_server.rst | 97 +------------------ 1 file changed, 2 insertions(+), 95 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 8c7cc6f46..b6c460d7d 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -17,100 +17,7 @@ Before You Begin It is essential you have **NodeJS 16** installed. -Installing NodeJS 16 on the Server ----------------------------------- - -Before installing Studio you must install NodeJS version 16 on the server. - -**To install NodeJS version 16 on the server:** - -1. Check if a version of NodeJS older than version *16.<x.x>* has been installed on the target server. - - .. code-block:: console - - node -v - - The following is the output if a version of NodeJS has already been installed on the target server: - - .. code-block:: console - - bash: /usr/bin/node: No such file or directory - -2. If a version of NodeJS older than *16.<x.x>* has been installed, remove it as follows: - - * On CentOS: - - .. code-block:: console - - sudo yum remove -y nodejs - - * On Ubuntu: - - .. code-block:: console - - sudo apt remove -y nodejs - -3. If you have not installed NodeJS version 16, run the following commands: - - * On CentOS: - - .. code-block:: console - - curl -sL https://rpm.nodesource.com/setup_12.x | sudo bash - - sudo yum clean all && sudo yum makecache fast - sudo yum install -y nodejs - - * On Ubuntu: - - .. code-block:: console - - curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash - - sudo apt-get install -y nodejs - - The following output is displayed if your installation has completed successfully: - - .. code-block:: console - - Transaction Summary - ============================================================================================================================== - Install 1 Package - - Total download size: 22 M - Installed size: 67 M - Downloading packages: - warning: /var/cache/yum/x86_64/7/nodesource/packages/nodejs-12.22.1-1nodesource.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID 34fa74dd: NOKEY - Public key for nodejs-12.22.1-1nodesource.x86_64.rpm is not installed - nodejs-12.22.1-1nodesource.x86_64.rpm | 22 MB 00:00:02 - Retrieving key from file:///etc/pki/rpm-gpg/NODESOURCE-GPG-SIGNING-KEY-EL - Importing GPG key 0x34FA74DD: - Userid : "NodeSource <gpg-rpm@nodesource.com>" - Fingerprint: 2e55 207a 95d9 944b 0cc9 3261 5ddb e8d4 34fa 74dd - Package : nodesource-release-el7-1.noarch (installed) - From : /etc/pki/rpm-gpg/NODESOURCE-GPG-SIGNING-KEY-EL - Running transaction check - Running transaction test - Transaction test succeeded - Running transaction - Warning: RPMDB altered outside of yum. - Installing : 2:nodejs-12.22.1-1nodesource.x86_64 1/1 - Verifying : 2:nodejs-12.22.1-1nodesource.x86_64 1/1 - - Installed: - nodejs.x86_64 2:12.22.1-1nodesource - - Complete! - -4. Confirm the Node version. - - .. code-block:: console - - node -v - - The following is an example of the correct output: - - .. code-block:: console - - v16.20.0 +-- link to NodeJS 16 in installation Installing Studio ================= @@ -153,7 +60,7 @@ Installing Studio :: -5. To access Studio over a secure connection, in your configuration file do the following: +5. To make the communication between Studio and SQreamDB secure, in your configuration file do the following: #. Change your ``port`` value to **3109**. From 084c647c8e7368c5477cc0d9b75dbbc294f00eb3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 May 2024 14:50:36 +0300 Subject: [PATCH 1342/1892] Update installing_studio_on_stand_alone_server.rst --- ...nstalling_studio_on_stand_alone_server.rst | 65 ++++--------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index b6c460d7d..df5ee5376 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -57,14 +57,10 @@ Installing Studio Config generated successfully. Run `npm start` to start the app. For more information about the available set-up arguments, see :ref:`Set-Up Arguments<setup_arguments>`. - - :: 5. To make the communication between Studio and SQreamDB secure, in your configuration file do the following: #. Change your ``port`` value to **3109**. - - :: #. Change your ``ssl`` flag value to **true**. @@ -94,6 +90,8 @@ Installing Studio ] } + Note that for the ``host`` value, you may use the IP address of your SQreamDB machine. + 5. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: .. code-block:: console @@ -102,10 +100,10 @@ Installing Studio Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` -Starting Studio Manually ------------------------- +Starting Studio +--------------- -You can start Studio manually by running the following command: +You can start Studio by running the following command: .. code-block:: console @@ -124,64 +122,27 @@ The following output is displayed: │ 0 │ sqream-studio │ default │ 0.1.0 │ fork │ 11540 │ 0s │ 0 │ online │ 0% │ 15.6mb │ sqream │ disabled │ └─────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ -Starting Studio as a Service ----------------------------- - -Sqream uses the **Process Manager (PM2)** to maintain Studio. - -**To start Studio as a service:** - -1. Run the following command: - - .. code-block:: console - - sudo npm install -g pm2 - -:: - -2. Verify that the PM2 has been installed successfully. - - .. code-block:: console - - pm2 list - - The following is the output: - - .. code-block:: console - - ┌─────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐ - │ id │ name │ namespace │ version │ mode │ pid │ uptime │ ↺ │ status │ cpu │ mem │ user │ watching │ - ├─────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤ - │ 0 │ sqream-studio │ default │ 0.1.0 │ fork │ 11540 │ 2m │ 0 │ online │ 0% │ 31.5mb │ sqream │ disabled │ - └─────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘ - -:: - -2. Start the service with PM2: - * If the **sqream-admin-config.json** file is located in **/etc/sqream/**, run the following command: - - .. code-block:: console - - cd /home/sqream/sqream-admin - NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start --config-location=/etc/sqream/sqream-admin-config.json - - * If the **sqream-admin-config.json** file is not located in **/etc/sqream/**, run the following command: +1. If the **sqream-admin-config.json** file is not located in **/etc/sqream/**, run the following command: .. code-block:: console cd /home/sqream/sqream-admin NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start -:: +2. To verify the process is running, use the ``pm2 list`` command: + + .. code-block:: + + pm2 list -3. Verify that Studio is running. +2. Verify that Studio is running. .. code-block:: console netstat -nltp -4. Verify that SQream_studio is listening on port 8080, as shown below: +3. Verify that SQream_studio is listening on port 8080, as shown below: .. code-block:: console From 682cfd4e01d054382ce4810a4d3d486c8ef31233 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 May 2024 14:52:29 +0300 Subject: [PATCH 1343/1892] Update installing_studio_on_stand_alone_server.rst --- .../installing_studio_on_stand_alone_server.rst | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index df5ee5376..2176e7e8f 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -125,24 +125,24 @@ The following output is displayed: 1. If the **sqream-admin-config.json** file is not located in **/etc/sqream/**, run the following command: - .. code-block:: console + .. code-block:: console - cd /home/sqream/sqream-admin + cd /home/sqream/sqream-admin NODE_ENV=production pm2 start ./server/build/main.js --name=sqream-studio -- start 2. To verify the process is running, use the ``pm2 list`` command: - .. code-block:: + .. code-block:: - pm2 list + pm2 list -2. Verify that Studio is running. +3. Verify that Studio is running. .. code-block:: console netstat -nltp -3. Verify that SQream_studio is listening on port 8080, as shown below: +4. Verify that SQream_studio is listening on port 8080, as shown below: .. code-block:: console @@ -156,9 +156,6 @@ The following output is displayed: tcp6 0 0 :::22 :::* LISTEN - tcp6 0 0 ::1:25 :::* LISTEN - - - -:: 5. Verify the following: @@ -182,7 +179,7 @@ The following output is displayed: 7. Copy and paste the output above and run it. -:: + 8. Save the configuration. From 72e7dcd88e2d6ce030042d01e1d20b05061b8110 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 28 May 2024 15:21:00 +0300 Subject: [PATCH 1344/1892] Studio installation --- ...nstalling_studio_on_stand_alone_server.rst | 89 +++++-------------- .../pre-installation_configurations.rst | 2 + 2 files changed, 24 insertions(+), 67 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index 2176e7e8f..a18122ef1 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -15,18 +15,14 @@ A stand-alone server is a server that does not run SQreamDB based on binary file Before You Begin ================ -It is essential you have **NodeJS 16** installed. - --- link to NodeJS 16 in installation +It is essential you have :ref:`NodeJS 16 installed <installing_nodejs>`. Installing Studio ================= - -**To install Studio:** -1. Copy the SQream Studio package from SQream Artifactory into the target server. For access to the Sqream Studio package, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. - -:: +1. Copy the SQream Studio package from SQream Artifactory into the target server. + + For access to the Sqream Studio package, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. 2. Extract the package: @@ -34,8 +30,6 @@ Installing Studio tar -xvf sqream-acceleration-studio-<version number>.x86_64.tar.gz -:: - 3. Navigate to the new package folder. .. code-block:: console @@ -55,14 +49,12 @@ Installing Studio .. code-block:: console Config generated successfully. Run `npm start` to start the app. - - For more information about the available set-up arguments, see :ref:`Set-Up Arguments<setup_arguments>`. 5. To make the communication between Studio and SQreamDB secure, in your configuration file do the following: - #. Change your ``port`` value to **3109**. + a. Change your ``port`` value to **3109**. - #. Change your ``ssl`` flag value to **true**. + b. Change your ``ssl`` flag value to **true**. The following is an example of the correctly modified configuration file: @@ -90,20 +82,18 @@ Installing Studio ] } - Note that for the ``host`` value, you may use the IP address of your SQreamDB machine. + Note that for the ``host`` value, it is essential that you use the IP address of your SQreamDB machine. -5. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: +6. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: .. code-block:: console mv sqream-admin-config.json /etc/sqream -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` - Starting Studio --------------- -You can start Studio by running the following command: +Start Studio by running the following command: .. code-block:: console @@ -136,7 +126,7 @@ The following output is displayed: pm2 list -3. Verify that Studio is running. +3. Verify that Studio is running: .. code-block:: console @@ -157,15 +147,13 @@ The following output is displayed: tcp6 0 0 ::1:25 :::* LISTEN - -5. Verify the following: +5. Verify that you can: - 1. That you can access Studio from your browser (``http://<IP_Address>:8080``). - - :: + a. Access Studio from your browser (``http://<IP_Address>:8080``) - 2. That you can log in to SQream. + b. Log in to SQream -6. Save the configuration to run on boot. +6. Save the configuration to run on boot: .. code-block:: console @@ -181,14 +169,12 @@ The following output is displayed: -8. Save the configuration. +8. Save the configuration: .. code-block:: console pm2 save -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` - Accessing Studio ---------------- @@ -201,27 +187,19 @@ If port 8080 is blocked by the server firewall, you can unblock it by running th firewall-cmd --zone=public --add-port=8080/tcp --permanent firewall-cmd --reload -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` - Maintaining Studio with the Process Manager (PM2) ------------------------------------------------- -Sqream uses the **Process Manager (PM2)** to maintain Studio. +SQream uses the **Process Manager (PM2)** to maintain Studio. You can use PM2 to do one of the following: * To check the PM2 service status: ``pm2 list`` - - :: * To restart the PM2 service: ``pm2 reload sqream-studio`` - - :: * To see the PM2 service logs: ``pm2 logs sqream-studio`` -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` - Upgrading Studio ---------------- @@ -235,13 +213,11 @@ To upgrade Studio you need to stop the version that you currently have. pm2 list - The process name is displayed. + The process name is displayed.: .. code-block:: console <process name> - -:: 2. Run the following command with the process name: @@ -249,51 +225,30 @@ To upgrade Studio you need to stop the version that you currently have. pm2 stop <process name> -:: - 3. If only one process is running, run the following command: .. code-block:: console pm2 stop all -:: - -4. Change the name of the current **sqream-admin** folder to the old version. +4. Change the name of the current **sqream-admin** folder to the old version: .. code-block:: console mv sqream-admin sqream-admin-<old_version> -:: - -5. Extract the new Studio version. +5. Extract the new Studio version: .. code-block:: console tar -xf sqream-acceleration-studio-<version>tar.gz -:: - -6. Rebuild the configuration file. You can use IP address **127.0.0.1** on a single server. - - .. code-block:: console - - npm run setup -- -y --host=<SQreamD IP> --port=3108 - - The above command creates the **sqream-admin-config.json** configuration file in the **sqream_admin** folder. - -:: - -7. Copy the **sqream-admin-config.json** configuration file to **/etc/sqream/** to overwrite the old configuration file. - -:: - -8. Start PM2. +6. Start PM2: .. code-block:: console pm2 start all -Back to :ref:`Installing Studio on a Stand-Alone Server<install_studio_top>` +7. To access Studio over a secure (HTTPS) connection, follow :ref:`NGINX instructions<installing_nginx_proxy_over_secure_connection>`. + diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 2e666824d..0fb9ab93e 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -370,6 +370,8 @@ Installing Python python3 --version +.. _installing_nodejs: + Installing NodeJS ^^^^^^^^^^^^^^^^^^ From cc9ac37b7f7d38bb39269d012078318fb175c114 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 29 May 2024 11:08:13 +0300 Subject: [PATCH 1345/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index dd41cb935..42737b012 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -636,4 +636,4 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. .. code-block:: postgres - COPY my_table (date_col1, date_col2, date_col3) FROM '/tmp/my_data.csv' WITH CSV HEADER datetime_format 'DMY'; + COPY my_table (date_col1, date_col2, date_col3) FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/my_data.csv', offset = 2, datetime_format 'DMY'); From 63803f07b81f9d97de41afa5da4b2a19acdf834e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 30 May 2024 09:36:23 +0300 Subject: [PATCH 1346/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 37781b1c3..31d18969d 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -42,7 +42,8 @@ Syntax | CONTINUE_ON_ERROR = { true | false } | ERROR_COUNT = '{ error count }' | AWS_SECRET '{ AWS SECRET }', - | OFFSET -- for CSV and JSON only + | OFFSET -- for CSV and JSON only, + | QUOTE = {'C' | E'\ooo') -- for CSV only } path_spec ::= { local filepath | S3 URI | HDFS URI } @@ -98,6 +99,8 @@ Parameters - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction continues despite rejected data and rows containing partially faulty data are skipped entirely. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false``. * - ``ERROR_COUNT`` - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. Default value: ``unlimited``. Value range: 1 to 2147483647. + * - ``QUOTE`` + - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. QUOTE can be used with ``csv_fdw`` in ``COPY FROM`` and foreign tables. The following characters cannot be an alternative quote character: ``"-.:\\0123456789abcdefghijklmnopqrstuvwxyzN"`` @@ -190,4 +193,19 @@ Using the ``CONTINUE_ON_ERROR`` and ``ERROR_COUNT`` Parameters continue_on_error = true, ERROR_COUNT = 3 ) + ; + +Customizing Quotations Using Alternative Characters +--------------------------------------------------- + +.. code-block:: + + CREATE OR REPLACE FOREIGN TABLE cool_animalz + (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) + WRAPPER csv_fdw + OPTIONS + ( LOCATION = '/home/rhendricks/cool_animals.csv', + DELIMITER = '\t', + QUOTE = '@' + ) ; \ No newline at end of file From 006e0a60ecccccc2392671f787a2e1f70b1fc3d4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 30 May 2024 11:17:13 +0300 Subject: [PATCH 1347/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 42737b012..c0b2ff0a0 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -21,13 +21,13 @@ Syntax .. code-block:: postgres - COPY [schema name.]table_name + COPY [schema name.]table_name [ (<column_name>) [, ...] ] FROM WRAPPER fdw_name OPTIONS ( [ copy_from_option [, ...] ] ) - ; + schema_name ::= identifer @@ -637,3 +637,18 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. .. code-block:: postgres COPY my_table (date_col1, date_col2, date_col3) FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/my_data.csv', offset = 2, datetime_format 'DMY'); + +Loading Specific Columns +------------------------ + +.. code-block:: postgres + + COPY + new_nba (name, salary) + FROM + WRAPPER + parquet_fdw + OPTIONS + ( + LOCATION = '/tmp/nba.parquet' + ); \ No newline at end of file From 929144ea1dc55fd381a4db0c7e1cd4b1e9217055 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 30 May 2024 14:26:33 +0300 Subject: [PATCH 1348/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index c0b2ff0a0..e0d1ab1a1 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -641,6 +641,8 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. Loading Specific Columns ------------------------ +Loading specific columns using the COPY FROM command is not supported when using the CSV file format. + .. code-block:: postgres COPY From 361705dc20cf0aa482158554a72ef0e82948954f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 30 May 2024 14:29:59 +0300 Subject: [PATCH 1349/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index e0d1ab1a1..f5f8b8b19 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -641,7 +641,7 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. Loading Specific Columns ------------------------ -Loading specific columns using the COPY FROM command is not supported when using the CSV file format. +Loading specific columns using the ``COPY FROM`` command is not supported when using the CSV file format. .. code-block:: postgres From 907fe82b62afa1a8d06331e333dda7217806301a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 30 May 2024 15:32:41 +0300 Subject: [PATCH 1350/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 0b9bc3a62..7890f4aa1 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -128,7 +128,8 @@ Inserting arrayed values into a table: ( ARRAY ['1','2','3'], ARRAY ['4','5','6'], - ARRAY [7,8,9,10] + ARRAY [7,8,9,10], + ARRAY [0.4354,0.5365435,3.6456] ); Converting arrayed elements into a set of rows: @@ -136,15 +137,15 @@ Converting arrayed elements into a set of rows: .. code-block:: sql SELECT - UNNEST(ARRAY ['1','2','3'], ARRAY ['4','5','6']); + UNNEST(clmn1) FROM my_array; .. code-block:: console - clmn1 | clmn2 - ----------+---------- - "1" | "4" - "2" | "5" - "3" | "6" + clmn1 | + --------+ + 1 | + 2 | + 3 | Updating table values: From 347d353ca398bbfea9e1ffd31bd4740d20a1f462 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 2 Jun 2024 11:25:08 +0300 Subject: [PATCH 1351/1892] Update sqream_sql.rst --- reference/cli/sqream_sql.rst | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index ae37f9d0c..b514d0051 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -4,7 +4,7 @@ Linux Sqream SQL ************************ -SQream DB comes with a built-in client for executing SQL statements either interactively or from the command-line. +SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. This page serves as a reference for the options and parameters. Learn more about using SQream DB SQL with the CLI by visiting the :ref:`first_steps` tutorial. @@ -14,23 +14,17 @@ This page serves as a reference for the options and parameters. Learn more about Installing Sqream SQL ===================== -If you have a SQream DB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQream DB installation, under the name ``sqream``. - - -.. versionchanged:: 2020.1 - As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. +If you have a SQreamDB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQreamDB installation, under the name ``sqream``. - To run ``sqream sql`` on any other Linux host: -#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. #. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` #. Start the client: .. code-block:: psql - $ cd sqream-sql-v2020.1.1_stable.x86_64 - $ ./sqream sql --port=5000 --username=jdoe --databasename=master + cd sqream-sql-<xxxx.x.x>_stable.x86_64 + ./sqream sql --port=5000 --username=<jdoe> --databasename=master Password: Interactive client mode @@ -365,7 +359,7 @@ Command Line Arguments - Changes the mode of operation to multi-command, non-interactive. Use this argument to run a sequence of statements from an external file and immediately exit. * - ``--host`` - ``127.0.0.1`` - - Address of the SQream DB worker. + - Address of the SQreamDB worker. * - ``--port`` - ``5000`` - Sets the connection port. @@ -380,7 +374,7 @@ Command Line Arguments - Specify the password using the command line argument. If not specified, the client will prompt the user for the password. * - ``--clustered`` - False - - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQream DB worker. + - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQreamDB worker. * - ``--service`` - ``sqream`` - :ref:`Service name (queue)<workload_manager>` that statements will file into. From df5a7993dce35a52ba345239f08c2c92503fee7b Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 2 Jun 2024 11:49:39 +0300 Subject: [PATCH 1352/1892] Update rechunk.rst --- reference/sql/sql_statements/utility_commands/rechunk.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/rechunk.rst b/reference/sql/sql_statements/utility_commands/rechunk.rst index 649e75b24..1313caae5 100644 --- a/reference/sql/sql_statements/utility_commands/rechunk.rst +++ b/reference/sql/sql_statements/utility_commands/rechunk.rst @@ -4,7 +4,7 @@ RECHUNK ******* -SQreamDB is most efficient processing large data chunks. The ``rechunk`` function improves performance when handling tables with small data chunks by allowing you to consolidate these small chunks into larger ones. Additionally, this function also addresses mixed chunks, which are those containing one or more deleted records. When applied to mixed chunks, the function performs a :ref:`cleanup operation<delete_guide>`, resulting in clean, large data chunks. +SQreamDB is the most efficient for processing large data chunks. The ``rechunk`` function improves performance when handling tables with small data chunks by allowing you to consolidate these small chunks into larger ones. This function also handles mixed chunks, which include one or more deleted records and/or records marked for deletion but not yet purged (i.e., awaiting the removal of deleted data). When applied to mixed chunks, the function performs a :ref:`cleanup operation<delete_guide>`, resulting in clean, large data chunks. Syntax ========== @@ -37,4 +37,4 @@ Example Permissions ============= -Using the ``rechunk`` command requires no special permissions. \ No newline at end of file +Using the ``rechunk`` command requires no special permissions. From 7d89cc847223e84259cc02b980c2f4b3c15b8d0b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jun 2024 08:11:02 +0300 Subject: [PATCH 1353/1892] Remove SELECT DATA READ METRICS --- reference/sql/sql_statements/index.rst | 2 - .../select_data_read_metrics.rst | 95 ------------------- 2 files changed, 97 deletions(-) delete mode 100644 reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 4830f109c..a60b2114f 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -113,8 +113,6 @@ The following table shows the Utility commands: * - Command - Usage - * - :ref:`DATA READ METRICS<select_data_read_metrics>` - - Monitor license quota usage by reviewing monthly or daily data read usage * - :ref:`DROP SAVED QUERY<drop_saved_query>` - Drops a saved query * - :ref:`DUMP DATABASE DDL<dump_database_ddl>` diff --git a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst b/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst deleted file mode 100644 index 3d55b88cb..000000000 --- a/reference/sql/sql_statements/utility_commands/select_data_read_metrics.rst +++ /dev/null @@ -1,95 +0,0 @@ -.. _select_data_read_metrics: - -************************* -SELECT DATA READ METRICS -************************* - -The ``SELECT data_read_metrics`` utility function enables you to examine your cluster's data read during a specified time period, ensuring adherence to license limits. - -The data read result is presented in this format: Year-Month-Day, showcasing data read on each specified date, along with the total data read according to your license plan. - -Syntax -========== - -.. code-block:: sql - - SELECT data_read_metrics(['monthly'] | ['daily'], <'start-date'>, <'end-date'>) - -Parameters -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - State - - Description - * - ``monthly`` or ``daily`` - - Mandatory - - Specifies the time frame within which data was read - * - ``start-date`` - - Mandatory - - The starting date for the data retrieval period - * - ``end-date`` - - Mandatory - - The ending date for the data retrieval period - -Output -============ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``date`` - - Date of data read - * - ``actual_data_read`` - - Total data read within the specified date - * - ``data_read_limit_license_value`` - - Data read quota limit as per license plan - - -Examples -=========== - -Daily data reads are cumulative. For a comprehensive view of your data read usage, execute a monthly data read. - -.. code-block:: postgres - - SELECT data_read_metrics('daily','2023-05-01', '2023-05-05'); - -Output: - -.. code-block:: console - - date | actual_data_read | data_read_limit_license_value - ------------+--------------------+------------------------------ - 2023-May-01 | 20GB | 5000GB - 2023-May-02 | 50GB | 5000GB - 2023-May-03 | 10GB | 5000GB - 2023-May-04 | 5GB | 5000GB - 2023-May-05 | 4GB | 5000GB - - -Monthly data reads: - -.. code-block:: postgres - - SELECT data_read_metrics('monthly','2023-05-15', '2023-06-05'); - -Output: - -.. code-block:: console - - date | actual_data_read | data_read_limit_license_value - ------------+--------------------+------------------------------ - 2023 May, | 20GB | 5000GB - 2023 June | 50GB | 5000GB - -Permissions -============= - -Using the ``SELECT data_read_metrics`` command requires ``SUPERUSER`` permissions. \ No newline at end of file From 23f613c4ad3827abfaf35eef5653dc3eb9234508 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jun 2024 08:37:53 +0300 Subject: [PATCH 1354/1892] swap table names --- reference/sql/sql_statements/index.rst | 2 + .../utility_commands/swap_table_names.rst | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/swap_table_names.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index a60b2114f..033aecd1c 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -161,6 +161,8 @@ The following table shows the Utility commands: - Stops or aborts an active statement * - :ref:`SHOW VERSION<show_version>` - Returns the system version for SQream DB + * - :ref:`swap_table_names` + - Swaps the names of two tables contained within a schema Workload Management diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst new file mode 100644 index 000000000..25a682bfe --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -0,0 +1,42 @@ +.. _swap_table_names: + +**************** +SWAP TABLE NAMES +**************** + +The ``SWAP_TABLE_NAMES`` command enables you to swap the names of two tables contained within a schema. + +Syntax +====== + +.. code-block:: postgres + + SELECT SWAP_TABLE_NAMES (<schema_name>, <table1_name>, <table2_name>) + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema both tables are contained within + * - ``table_name`` + - The table name you wish to swap names for + +Notes +===== + +Operations like views that are pointing to table name will continue to work on the name table that renamed to the old table, depending on same properties like columns etc.. + +Examples +======== + +.. code-block:: postgres + + +Permissions +=========== \ No newline at end of file From 544aa9603c6c8fa59ab9a22b80c0e51eaf8dc352 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jun 2024 11:16:55 +0300 Subject: [PATCH 1355/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index 9abcc4187..c76b5b6c4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -35,7 +35,7 @@ Release Notes * `New Apache Spark Connector <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ * `Physical Deletion Performance Enhancement <https://docs.sqream.com/en/latest/releases/4.2.html#new-features>`_ -:ref:`Version 4.1 - March 01, 2032<4.1>` +:ref:`Version 4.1 - March 01, 2023<4.1>` * `LDAP Management Enhancements <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ * `New Trino Connector <https://docs.sqream.com/en/latest/releases/4.1.html#new-features>`_ From 1b368c1c067e5542c2de87f2774e3fba1fb206f2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jun 2024 14:19:25 +0300 Subject: [PATCH 1356/1892] Remove underscore from commands --- .../get_all_roles_global_ddl.rst | 19 ++++++++++------ .../get_role_database_ddl.rst | 2 +- .../utility_commands/get_role_global_ddl.rst | 22 ++++++++++++------- .../utility_commands/get_role_permissions.rst | 18 ++++++++++----- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst index 7a77dd810..498713ddd 100644 --- a/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst @@ -1,8 +1,9 @@ .. _get_all_roles_global_ddl: -******************** -GET_ALL_ROLES_GLOBAL_DDL -******************** +************************ +GET ALL ROLES GLOBAL DDL +************************ + The ``GET_ALL_ROLES_GLOBAL_DDL`` statement returns the definition of all global roles in DDL format. .. contents:: @@ -10,7 +11,8 @@ The ``GET_ALL_ROLES_GLOBAL_DDL`` statement returns the definition of all global :depth: 1 Syntax -========== +====== + The following is the correct syntax for using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: .. code-block:: postgres @@ -18,7 +20,8 @@ The following is the correct syntax for using the ``GET_ALL_ROLES_GLOBAL_DDL`` s select get_all_roles_global_ddl() Example -=========== +======= + The following is an example of using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: .. code-block:: psql @@ -27,7 +30,8 @@ The following is an example of using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: Output -========== +====== + The following is an example of the output of the ``GET_ALL_ROLES_GLOBAL_DDL`` statement: .. code-block:: postgres @@ -35,7 +39,8 @@ The following is an example of the output of the ``GET_ALL_ROLES_GLOBAL_DDL`` st create role "public"; create role "sqream"; grant superuser, login to "sqream" ; Permissions -============= +=========== + Using the ``GET_ALL_ROLES_GLOBAL_DDL`` statement requires no special permissions. For more information, see the following: diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index 13dd0d98b..5a557f690 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -1,7 +1,7 @@ .. _get_role_database_ddl: ********************* -GET_ROLE_DATABASE_DDL +GET ROLE DATABASE DDL ********************* The ``GET_ROLE_DATABASE_DDL`` statement returns the definition of a role's database in DDL format. diff --git a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst index 3ba0255d3..d622654d9 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst @@ -1,8 +1,9 @@ .. _get_role_global_ddl: -******************** -GET_ROLE_GLOBAL_DDL -******************** +******************* +GET ROLE GLOBAL DDL +******************* + The ``GET_ROLE_GLOBAL_DDL`` statement returns the definition of a global role in DDL format. The ``GET_ROLE_GLOBAL_DDL`` page describes the following: @@ -12,7 +13,8 @@ The ``GET_ROLE_GLOBAL_DDL`` page describes the following: :depth: 1 Syntax -========== +====== + The following is the correct syntax for using the ``GET_ROLE_GLOBAL_DDL`` statement: .. code-block:: postgres @@ -20,7 +22,8 @@ The following is the correct syntax for using the ``GET_ROLE_GLOBAL_DDL`` statem select get_role_global_ddl(<'role_name'>) Example -=========== +======= + The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: .. code-block:: psql @@ -28,7 +31,8 @@ The following is an example of using the ``GET_ROLE_GLOBAL_DDL`` statement: select get_role_global_ddl('public'); Parameters -============ +========== + The following table shows the ``GET_ROLE_GLOBAL_DDL`` parameters: .. list-table:: @@ -41,7 +45,8 @@ The following table shows the ``GET_ROLE_GLOBAL_DDL`` parameters: - The definition of the global role in DDL format. Output -========== +====== + The following is an example of the output of the ``GET_ROLE_GLOBAL_DDL`` statement: .. code-block:: postgres @@ -49,7 +54,8 @@ The following is an example of the output of the ``GET_ROLE_GLOBAL_DDL`` stateme create role "public"; Permissions -============= +=========== + Using the ``GET_ROLE_GLOBAL_DDL`` statement requires no special permissions. For more information, see the following: diff --git a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst index 8723f98c8..cccc7d78f 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst @@ -1,8 +1,9 @@ .. _get_role_permissions: ******************** -GET_ROLE_PERMISSIONS +GET ROLE PERMISSIONS ******************** + The ``GET_ROLE_PERMISSIONS`` statement returns all permissions granted to a role in table format. The ``GET_ROLE_PERMISSIONS`` page describes the following: @@ -12,7 +13,8 @@ The ``GET_ROLE_PERMISSIONS`` page describes the following: :depth: 1 Syntax -========== +====== + The following is the correct syntax for using the ``GET_ROLE_PERMISSIONS`` statement: .. code-block:: postgres @@ -20,7 +22,8 @@ The following is the correct syntax for using the ``GET_ROLE_PERMISSIONS`` state select get_role_permissions() Example -=========== +======= + The following is an example of using the ``GET_ROLE_PERMISSIONS`` statement: .. code-block:: psql @@ -28,7 +31,8 @@ The following is an example of using the ``GET_ROLE_PERMISSIONS`` statement: select get_role_permissions(); Parameters -============ +========== + The following table shows the ``GET_ROLE_PERMISSIONS`` parameters: .. list-table:: @@ -41,7 +45,8 @@ The following table shows the ``GET_ROLE_PERMISSIONS`` parameters: - The permissions belonging to the role. Output -========== +====== + The following is an example of the output of the ``GET_ROLE_PERMISSIONS`` statement: .. list-table:: @@ -62,7 +67,8 @@ The following is an example of the output of the ``GET_ROLE_PERMISSIONS`` statem - master.public.nba Permissions -============= +=========== + Using the ``GET_ROLE_PERMISSIONS`` statement requires no special permissions. For more information, see the following: From 711005844753fa91d572b3e741bb7d98c4dff2a6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:42:04 +0300 Subject: [PATCH 1357/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 196 ++++++++++-------- 1 file changed, 111 insertions(+), 85 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 31d18969d..c465ec57c 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -1,68 +1,63 @@ .. _create_foreign_table: -*********************** +******************** CREATE FOREIGN TABLE -*********************** +******************** ``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. Changes in the source data can result in corresponding modifications to the content of a foreign table. Consistent access to remote files might impact performance. Permissions -============= +=========== The role must have the ``CREATE`` permission at the database level. Syntax -========== +====== .. code-block:: postgres - create_table_statement ::= - CREATE [ OR REPLACE ] FOREIGN TABLE [schema_name].table_name ( - { column_def [, ...] } - ) - [ FOREIGN DATA ] WRAPPER fdw_name - [ OPTIONS ( option_def [, ... ] ) ] - - - schema_name ::= identifier - - table_name ::= identifier + CREATE [ OR REPLACE ] FOREIGN TABLE [ <schema_name> ].table_name ( + { column_def [, ...] } + ) + [ FOREIGN DATA ] WRAPPER fdw_name + [ OPTIONS ( option_def [, ... ] ) ] - fdw_name ::= - { csv_fdw | orc_fdw | parquet_fdw | json_fdw | avro_fdw } + fdw_name ::= + { csv_fdw | orc_fdw | parquet_fdw | json_fdw | avro_fdw } - option_def ::= - { - LOCATION = '{ path_spec }', - | DELIMITER = '{ field_delimiter }' -- for CSV only, - | RECORD_DELIMITER = '{ record_delimiter }', -- for CSV only - | AWS_ID '{ AWS ID }', - | CONTINUE_ON_ERROR = { true | false } - | ERROR_COUNT = '{ error count }' - | AWS_SECRET '{ AWS SECRET }', - | OFFSET -- for CSV and JSON only, - | QUOTE = {'C' | E'\ooo') -- for CSV only - } + option_def ::= + { + LOCATION = '{ path_spec }', + | DELIMITER = '{ field_delimiter }' -- for CSV only, + | RECORD_DELIMITER = '{ record_delimiter }', -- for CSV only + | AWS_ID '{ AWS ID }', + | CONTINUE_ON_ERROR = { true | false } + | ERROR_COUNT = '{ error count }' + | AWS_SECRET '{ AWS SECRET }', + | OFFSET -- for CSV and JSON only, + | QUOTE = {'C' | E'\ooo'} -- for CSV only + } - path_spec ::= { local filepath | S3 URI | HDFS URI } + path_spec ::= + { local filepath | S3 URI | HDFS URI } - field_delimiter ::= delimiter_character + field_delimiter ::= delimiter_character - record_delimiter ::= delimiter_character + record_delimiter ::= delimiter_character - column_def ::= - { column_name type_name [ default ] [ column_constraint ] } + column_def ::= + { column_name type_name [ default ] [ column_constraint ] } - column_name ::= identifier + column_name ::= identifier - column_constraint ::= - { NOT NULL | NULL } + column_constraint ::= + { NOT NULL | NULL } - default ::= - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] + default ::= + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] .. _cft_parameters: @@ -112,14 +107,19 @@ A simple table from Tab-delimited file (TSV) .. code-block:: postgres - CREATE OR REPLACE FOREIGN TABLE cool_animals - (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) - WRAPPER csv_fdw - OPTIONS - ( LOCATION = '/home/rhendricks/cool_animals.csv', - DELIMITER = '\t' - ) - ; + CREATE + OR REPLACE FOREIGN TABLE cool_animals ( + id INT NOT NULL, + name TEXT NOT NULL, + weight FLOAT NOT NULL + ) + WRAPPER + csv_fdw + OPTIONS + ( + LOCATION = '/home/rhendricks/cool_animals.csv', + DELIMITER = '\t' + ); A table from a directory of Parquet files on HDFS @@ -127,28 +127,36 @@ A table from a directory of Parquet files on HDFS .. code-block:: postgres - CREATE FOREIGN TABLE users - (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) - WRAPPER parquet_fdw - OPTIONS - ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' - ); + CREATE FOREIGN TABLE users ( + id INT NOT NULL, + name TEXT NOT NULL, + email TEXT NOT NULL + ) + WRAPPER + parquet_fdw + OPTIONS + ( + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' + ); A table from a bucket of ORC files on S3 ------------------------------------------ .. code-block:: postgres - CREATE FOREIGN TABLE users - (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) - WRAPPER orc_fdw - OPTIONS - ( - LOCATION = 's3://pp-secret-bucket/users/*.orc', - AWS_ID = 'our_aws_id', - AWS_SECRET = 'our_aws_secret' - ); + CREATE FOREIGN TABLE users ( + id INT NOT NULL, + name TEXT NOT NULL, + email TEXT NOT NULL + ) + WRAPPER + orc_fdw + OPTIONS + ( + LOCATION = 's3://pp-secret-bucket/users/*.orc', + AWS_ID = 'our_aws_id', + AWS_SECRET = 'our_aws_secret' + ); Changing a foreign table to a regular table @@ -160,8 +168,12 @@ Materializes a foreign table into a regular table. .. code-block:: postgres - CREATE TABLE real_table - AS SELECT * FROM some_foreign_table; + CREATE TABLE + real_table AS + SELECT + * + FROM + some_foreign_table; Using the ``OFFSET`` Parameter -------------------------------- @@ -170,12 +182,16 @@ The ``OFFSET`` parameter may be used with Parquet and CSV textual formats. .. code-block:: - CREATE FOREIGN TABLE users7 - (id INT NOT NULL, name text(30) NOT NULL, email text(50) NOT NULL) - WRAPPER parquet_fdw + CREATE FOREIGN TABLE users7 ( + id INT NOT NULL, + name TEXT NOT NULL, + email TEXT NOT NULL + ) + WRAPPER + parquet_fdw OPTIONS ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet', + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet', OFFSET = 2 ); @@ -184,28 +200,38 @@ Using the ``CONTINUE_ON_ERROR`` and ``ERROR_COUNT`` Parameters .. code-block:: - CREATE OR REPLACE FOREIGN TABLE cool_animalz - (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) - WRAPPER csv_fdw + CREATE + OR REPLACE FOREIGN TABLE cool_animalz ( + id INT NOT NULL, + name TEXT NOT NULL, + weight FLOAT NOT NULL + ) + WRAPPER + csv_fdw OPTIONS - ( LOCATION = '/home/rhendricks/cool_animals.csv', - DELIMITER = '\t', - continue_on_error = true, - ERROR_COUNT = 3 - ) - ; + ( + LOCATION = '/home/rhendricks/cool_animals.csv', + DELIMITER = '\t', + CONTINUE_ON_ERROR = true, + ERROR_COUNT = 3 + ); Customizing Quotations Using Alternative Characters --------------------------------------------------- .. code-block:: - CREATE OR REPLACE FOREIGN TABLE cool_animalz - (id INT NOT NULL, name text(30) NOT NULL, weight FLOAT NOT NULL) - WRAPPER csv_fdw + CREATE + OR REPLACE FOREIGN TABLE cool_animalz ( + id INT NOT NULL, + name TEXT NOT NULL, + weight FLOAT NOT NULL + ) + WRAPPER + csv_fdw OPTIONS - ( LOCATION = '/home/rhendricks/cool_animals.csv', + ( + LOCATION = '/home/rhendricks/cool_animals.csv', DELIMITER = '\t', QUOTE = '@' - ) - ; \ No newline at end of file + ); \ No newline at end of file From c8b4d9e3295cb68995400eaafb6b0fc6608c5130 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:54:54 +0300 Subject: [PATCH 1358/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index f5f8b8b19..d0dd4b19b 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -1,10 +1,10 @@ .. _copy_from: -********************** +********* COPY FROM -********************** +********* -``COPY ... FROM`` is a statement that allows loading data from files on the filesystem and importing them into SQream tables. This is the recommended way for bulk loading CSV files into SQream DB. In general, ``COPY`` moves data between filesystem files and SQream DB tables. +``COPY ... FROM`` is a statement that allows loading data from files on the filesystem and importing them into SQreamDB tables. This is the recommended way for bulk loading CSV files into SQreamDB. In general, ``COPY`` moves data between filesystem files and SQreamDB tables. .. note:: * Learn how to migrate from CSV files in the :ref:`csv` guide @@ -12,12 +12,12 @@ COPY FROM * To load Parquet or ORC files, see :ref:`CREATE FOREIGN TABLE<create_foreign_table>` Permissions -============= +=========== The role must have the ``INSERT`` permission to the destination table. Syntax -========== +====== .. code-block:: postgres @@ -641,7 +641,11 @@ In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. Loading Specific Columns ------------------------ -Loading specific columns using the ``COPY FROM`` command is not supported when using the CSV file format. +Loading specific columns using the ``COPY FROM`` command: + +* Does not support CSV files + +* Requires that the target table columns be nullable .. code-block:: postgres From 9804fa554063daedefd5bfe2a8c58f6e525a934a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 4 Jun 2024 12:56:16 +0300 Subject: [PATCH 1359/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 105 +++++++++--------- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index c465ec57c..12288a310 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -18,46 +18,42 @@ Syntax .. code-block:: postgres - CREATE [ OR REPLACE ] FOREIGN TABLE [ <schema_name> ].table_name ( - { column_def [, ...] } - ) - [ FOREIGN DATA ] WRAPPER fdw_name - [ OPTIONS ( option_def [, ... ] ) ] + CREATE [ OR REPLACE ] FOREIGN TABLE [ "<schema_name>" ]."<table_name>" ( + [ column_def [, ...] ] -- When creating foreign tables using CSV source files, it is mandatory to provide the complete table DDL + ) + [ FOREIGN DATA ] WRAPPER fdw_name + [ OPTIONS ( option_def [, ... ] ) ] fdw_name ::= - { csv_fdw | orc_fdw | parquet_fdw | json_fdw | avro_fdw } + { csv_fdw | orc_fdw | parquet_fdw } option_def ::= - { - LOCATION = '{ path_spec }', - | DELIMITER = '{ field_delimiter }' -- for CSV only, - | RECORD_DELIMITER = '{ record_delimiter }', -- for CSV only - | AWS_ID '{ AWS ID }', - | CONTINUE_ON_ERROR = { true | false } - | ERROR_COUNT = '{ error count }' - | AWS_SECRET '{ AWS SECRET }', - | OFFSET -- for CSV and JSON only, - | QUOTE = {'C' | E'\ooo'} -- for CSV only - } + LOCATION = '{ path_spec }' + [ + | DELIMITER = '{ field_delimiter }' -- for CSV only + | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only + | AWS_ID '{ AWS ID }' + | AWS_SECRET '{ AWS SECRET }' + | QUOTE = {'C' | E'\ooo') -- for CSV only + ] - path_spec ::= - { local filepath | S3 URI | HDFS URI } + path_spec ::= { GS URI | S3 URI | HDFS URI } field_delimiter ::= delimiter_character record_delimiter ::= delimiter_character column_def ::= - { column_name type_name [ default ] [ column_constraint ] } + { column_name type_name [ default ] [ column_constraint ] } column_name ::= identifier - column_constraint ::= - { NOT NULL | NULL } + column_constraint ::= + { NOT NULL | NULL } default ::= - DEFAULT default_value - | IDENTITY [ ( start_with [ , increment_by ] ) ] + DEFAULT default_value + | IDENTITY [ ( start_with [ , increment_by ] ) ] .. _cft_parameters: @@ -77,7 +73,7 @@ Parameters * - ``table_name`` - The name of the table to create, which must be unique inside the schema * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally + - A comma separated list of column definitions. A minimal column definition includes a name and datatype. Other column constraints and default values may optionally be added. When creating foreign tables using CSV source files, it is mandatory to provide the complete table DDL * - ``WRAPPER ...`` - Specifies the format of the source files, such as ``parquet_fdw``, ``orc_fdw``, ``json_fdw``, or ``csv_fdw`` * - ``LOCATION = ...`` @@ -91,9 +87,9 @@ Parameters * - ``OFFSET`` - Used to specify the number of rows to skip from the beginning of the result set * - ``CONTINUE_ON_ERROR`` - - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction continues despite rejected data and rows containing partially faulty data are skipped entirely. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false``. + - Specifies if errors should be ignored or skipped. When set to ``true``, the transaction continues despite rejected data and rows containing partially faulty data are skipped entirely. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file can’t be opened it will be skipped. Default value: ``false``. Value range: ``true`` or ``false`` * - ``ERROR_COUNT`` - - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. Default value: ``unlimited``. Value range: 1 to 2147483647. + - Specifies the threshold for the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``CONTINUE_ON_ERROR``. Default value: ``unlimited``. Value range: 1 to 2147483647 * - ``QUOTE`` - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. QUOTE can be used with ``csv_fdw`` in ``COPY FROM`` and foreign tables. The following characters cannot be an alternative quote character: ``"-.:\\0123456789abcdefghijklmnopqrstuvwxyzN"`` @@ -102,35 +98,40 @@ Parameters Examples =========== -A simple table from Tab-delimited file (TSV) ----------------------------------------------- +Creating a Tab-Delimited Table +------------------------------ .. code-block:: postgres CREATE - OR REPLACE FOREIGN TABLE cool_animals ( - id INT NOT NULL, - name TEXT NOT NULL, - weight FLOAT NOT NULL + OR REPLACE FOREIGN TABLE nba_new( + "player_name" text null, + "team_name" text null, + "jersey_number" int null, + "position" text null, + "age" int null, + "height" text null, + "weight" int null, + "college" text null, + "salary" int null ) WRAPPER csv_fdw OPTIONS - ( - LOCATION = '/home/rhendricks/cool_animals.csv', - DELIMITER = '\t' + (LOCATION = 'gs://blue_docs/nba.csv', + DELIMITER = '\t' ); -A table from a directory of Parquet files on HDFS ------------------------------------------------------ +Creating a Table Located In a HDFS Directory +-------------------------------------------- .. code-block:: postgres CREATE FOREIGN TABLE users ( id INT NOT NULL, - name TEXT NOT NULL, - email TEXT NOT NULL + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL ) WRAPPER parquet_fdw @@ -139,15 +140,15 @@ A table from a directory of Parquet files on HDFS LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/users/*.parquet' ); -A table from a bucket of ORC files on S3 ------------------------------------------- +Creating a Table Located Within a S3 Bucket of ORC Files +-------------------------------------------------------- .. code-block:: postgres CREATE FOREIGN TABLE users ( id INT NOT NULL, - name TEXT NOT NULL, - email TEXT NOT NULL + name TEXT(30) NOT NULL, + email TEXT(50) NOT NULL ) WRAPPER orc_fdw @@ -159,12 +160,10 @@ A table from a bucket of ORC files on S3 ); -Changing a foreign table to a regular table ------------------------------------------------- - -Materializes a foreign table into a regular table. +Converting a Foreign Table to an Internal Table +----------------------------------------------- -.. tip: Using a foreign table allows you to perform ETL-like operations in SQream DB by applying SQL functions and operations to raw files +Using a foreign table allows you to perform ETL-like operations by applying SQL functions and operations to raw files. .. code-block:: postgres @@ -176,15 +175,15 @@ Materializes a foreign table into a regular table. some_foreign_table; Using the ``OFFSET`` Parameter --------------------------------- +------------------------------ The ``OFFSET`` parameter may be used with Parquet and CSV textual formats. .. code-block:: CREATE FOREIGN TABLE users7 ( - id INT NOT NULL, - name TEXT NOT NULL, + id INT NOT NULL, + name TEXT NOT NULL, email TEXT NOT NULL ) WRAPPER @@ -224,7 +223,7 @@ Customizing Quotations Using Alternative Characters CREATE OR REPLACE FOREIGN TABLE cool_animalz ( id INT NOT NULL, - name TEXT NOT NULL, + name text(30) NOT NULL, weight FLOAT NOT NULL ) WRAPPER From 5ad7886619d285b6e15d534375b5c4c784a207de Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:15:23 +0300 Subject: [PATCH 1360/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index d0dd4b19b..a4466c80c 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -628,9 +628,7 @@ When the source of the files does not match the table structure, tell the ``COPY Loading Non-Standard Dates ---------------------------------- -If files contain dates not formatted as ``ISO8601``, tell ``COPY`` how to parse the column. After parsing, the date will appear as ``ISO8601`` inside SQreamDB. - -These are called date parsers. You can find the supported dates in the :ref:`'Supported date parsers' table<copy_date_parsers>` above. +If your files contain dates in a format other than ``ISO8601``, you can specify a :ref:`parsing<copy_date_parsers>` format to convert them during the import process. This ensures the dates are stored internally as ``ISO8601`` within the database. In this example, ``date_col1`` and ``date_col2`` in the table are non-standard. ``date_col3`` is mentioned explicitly, but can be left out. Any column that is not specified is assumed to be ``ISO8601``. From a17ab4226dad5671eade4c3a2443b90dff804d86 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:42:05 +0300 Subject: [PATCH 1361/1892] Update swap_table_names.rst --- .../sql/sql_statements/utility_commands/swap_table_names.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst index 25a682bfe..90ee73665 100644 --- a/reference/sql/sql_statements/utility_commands/swap_table_names.rst +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -30,7 +30,7 @@ Parameters Notes ===== -Operations like views that are pointing to table name will continue to work on the name table that renamed to the old table, depending on same properties like columns etc.. +When setting views or performing any operation that points to a table whose name has been swapped, the view will address the same table name. If no columns are specified, the operation will succeed. However, if the operation references specific columns, it will fail because the view points to a table containing different columns. Examples ======== From 0b1beba10cf5c8cfeb0ffcb33ad37f40a70cd656 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 4 Jun 2024 16:02:05 +0300 Subject: [PATCH 1362/1892] Remove Linear Regression --- operational_guides/index.rst | 2 +- operational_guides/linear_regression.rst | 103 ----------------------- 2 files changed, 1 insertion(+), 104 deletions(-) delete mode 100644 operational_guides/linear_regression.rst diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 3426caba5..82df793f0 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -24,5 +24,5 @@ This section summarizes the following operational guides: security saved_queries optimization_best_practices - linear_regression + \ No newline at end of file diff --git a/operational_guides/linear_regression.rst b/operational_guides/linear_regression.rst deleted file mode 100644 index bdd6ca3f1..000000000 --- a/operational_guides/linear_regression.rst +++ /dev/null @@ -1,103 +0,0 @@ -.. _linear_regression: - -*********************** -In-DB Linear Regression -*********************** - -Linear regression is a fundamental component of the data science pipeline, used to model relationships between variables and make predictions based on observed data. - -SQreamDB supports data preparation and standardization, data training, and inference using data stored in and outside SQreamDB, providing a comprehensive platform for conducting end-to-end data analysis and machine learning tasks. - -.. contents:: - :local: - :depth: 1 - -Before You Begin -================ - -* Python version - -* SQreamDB :ref:`JDBC connector<java_jdbc>` version - -* SQDB version - -* Missing data is not supported - -Parameters ----------- - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - Default - - Description - * - Tolerance - - ``1e-4`` - - When the change resulting from an iteration is smaller than the defined tolerance value, the iterations are terminated. - * - Label Index - - ``0`` - - Label index identifies the position of the target variable (dependent variable) within the dataset, crucial for training a linear regression model. - * - Max Number of Epochs - - ``1500`` - - Max number of epochs sets the limit on how many times the training algorithm iterates over the dataset during model training, helping control training duration and complexity. - -Importing Python Libraries -========================== - -.. code-block:: python - - df = session.table('customers') - .join('orders',on='customer_id') - .filter('active') - .to_pandas() - -Data Preparation -================ - -Missing data is not supported. - -* All data, including labels and features, should be stored in the same table. - -* Ensure that feature values (X) are within the same range. If not, consider normalizing or standardizing the features (X) for both training and testing datasets. - -.. _normalization: - -Normalization (Standardization) -------------------------------- - -Centering and scaling should be done independently on each feature by computing the relevant statistics on the samples in the training set. - -We suggest standardizing features by removing the mean and scaling to unit variance. The standard score of a sample :math:`x` is calculated as :math:`z = x - \frac{u}{s}`, where: - -* :math:`u` is the mean of the training samples - -* :math:`s` is the standard deviation of the training samples - -Training Data -============= - -The training process occurs entirely within the SQream database environment, meaning that all steps—from data preparation to model training—are conducted within SQreamDB. This eliminates the necessity of exporting data out of SQreamDB for training purposes. - -.. code-block:: - - def train(data): - model = sk.LinearRegression() - X,y = df #... - X_train, X_test, y_train, y_test = split_train_test(X,y) - model.fit(X_train,y_train) - - session.register('train_sp',train) - model = session.execute('train_sp', source_table='customers') - -Testing and Inference -===================== - -.. code-block:: python - - session.import_model('model0',model) - test_results = session.table('customers_test').predict('model0') - # compare test results and test ground truth... - prediction_results = session.sql('select *,predict(''model0'',*) from customers'); - From be275c9b6feb92e4be63a81b676adfb588ea0746 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 9 Jun 2024 09:33:20 +0300 Subject: [PATCH 1363/1892] Update preparing_your_machine_to_install_sqream.rst --- .../preparing_your_machine_to_install_sqream.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index 432089fc0..fb8556384 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -1,8 +1,8 @@ .. _preparing_your_machine_to_install_sqream: -******************************************* +****************************************** Preparing Your Machine to Install SQreamDB -******************************************* +****************************************** To prepare your machine to install SQreamDB, do the following: @@ -14,7 +14,7 @@ To prepare your machine to install SQreamDB, do the following: * Red Hat Enterprise Linux v7.x / v8.6 - 8.8 - * CentOS v7.x + * CentOS v8.x * Amazon Linux 7 From 1253b157181b23dc6be2bdb77fe91a910024f141 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 9 Jun 2024 10:57:35 +0300 Subject: [PATCH 1364/1892] Update preparing_your_machine_to_install_sqream.rst --- .../preparing_your_machine_to_install_sqream.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index fb8556384..fbb426d43 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -12,9 +12,7 @@ To prepare your machine to install SQreamDB, do the following: * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - * Red Hat Enterprise Linux v7.x / v8.6 - 8.8 - - * CentOS v8.x + * Red Hat Enterprise Linux v8.6 - 8.8 * Amazon Linux 7 @@ -33,4 +31,4 @@ To prepare your machine to install SQreamDB, do the following: For more information, see the following: * :ref:`pre-installation_configurations` -* :ref:`hardware_guide` \ No newline at end of file +* :ref:`hardware_guide` From 4d67804e4b404bcfb185e4c2e4974d95b8c6889a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jun 2024 14:47:46 +0300 Subject: [PATCH 1365/1892] RHEL --- getting_started/hardware_guide.rst | 5 +- .../non_production_hardware_guide.rst | 80 ++++++++++--------- 2 files changed, 44 insertions(+), 41 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index bfb85acf3..1af7b821e 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -158,7 +158,7 @@ The following table shows SQreamDB's recommended Studio server specifications: * - Onboard storage - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v7.9 or CentOS v7.9 + - Red Hat Enterprise Linux v8.8 Cluster Design Considerations ============================= @@ -231,8 +231,7 @@ Operating System SQreamDB can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v7.9 - * CentOS v7.9 + * Red Hat Enterprise Linux (RHEL) v8.8 * Amazon Linux 2018.03 diff --git a/getting_started/non_production_hardware_guide.rst b/getting_started/non_production_hardware_guide.rst index 6b990401c..4f8739f90 100644 --- a/getting_started/non_production_hardware_guide.rst +++ b/getting_started/non_production_hardware_guide.rst @@ -1,50 +1,54 @@ .. non_production_hardware_guide: -*************************************** +************************************** Staging and Development Hardware Guide -*************************************** +************************************** The **Staging and Development Hardware Guide** describes the SQream recommended HW for development, staging and or QA desktop and servers. .. warning:: The HW specification in this page are not intended for production use! Development Desktop ------------------------------------ - -+------------------+-----------------------------------------------+ -| **Component** | **Type** | -+==================+===============================================+ -| Server | PC | -+------------------+-----------------------------------------------+ -| Processor | Intel i7 | -+------------------+-----------------------------------------------+ -| RAM | 64GB RAM | -+------------------+-----------------------------------------------+ -| Onboard storage | 2TB SSD | -+------------------+-----------------------------------------------+ -| GPU | 1x NVIDIA RTX A4000 16GB | -+------------------+-----------------------------------------------+ -| Operating System | Red Hat Enterprise Linux v7.9 or CentOS v7.9 | -+------------------+-----------------------------------------------+ +------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - Server + - PC + * - Processor + - Intel i7 + * - RAM + - 64GB RAM + * - Onboard storage + - 2TB SSD + * - GPU + - 1x NVIDIA RTX A4000 16GB + * - Operating System + - Red Hat Enterprise Linux v8.8 Lab Server ------------------------------------ - -+------------------+------------------------------------------------------------+ -| **Component** | **Type** | -+==================+============================================================+ -| Server | Dell R640 or similar | -+------------------+------------------------------------------------------------+ -| Processor | x2 Intel(R) Xeon(R) Silver 4112 CPU @ 2.60GHz | -+------------------+------------------------------------------------------------+ -| RAM | 128 or 256 GB | -+------------------+------------------------------------------------------------+ -| Onboard storage | "2x 960GB SSD 2.5in hot plug for OS, RAID1 | -+------------------+------------------------------------------------------------+ -| | 1(or more)x 3.84TB SSD 2.5in Hot plug for storage, RAID5" | -+------------------+------------------------------------------------------------+ -| GPU | 1xNVIDIA T4 or A40 or A10 | -+------------------+------------------------------------------------------------+ -| Operating System | Red Hat Enterprise Linux v7.9 or CentOS v7.9 | -+------------------+------------------------------------------------------------+ +---------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - Server + - Dell R640 or similar + * - Processor + - x2 Intel(R) Xeon(R) Silver 4112 CPU @ 2.60GHz + * - RAM + - 128 or 256 GB + * - Onboard storage + - "2x 960GB SSD 2.5in hot plug for OS, RAID1, 1(or more)x 3.84TB SSD 2.5in Hot plug for storage, RAID5" + * - GPU + - 1xNVIDIA T4 or A40 or A10 + * - Operating System + - Red Hat Enterprise Linux v8.8 From 24881457cda90f7144792c10694a980335f807d0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jun 2024 15:27:32 +0300 Subject: [PATCH 1366/1892] Maintenance --- releases/4.0.rst | 4 ++-- sqream_studio/getting_started.rst | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/releases/4.0.rst b/releases/4.0.rst index ed6dc628c..a8354496b 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -1,8 +1,8 @@ .. _4.0: -************************** +***************** Release Notes 4.0 -************************** +***************** SQream is introducing a new version release system that follows the more commonly used Major.Minor versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. diff --git a/sqream_studio/getting_started.rst b/sqream_studio/getting_started.rst index 1dc2d02e5..3ddf1a236 100644 --- a/sqream_studio/getting_started.rst +++ b/sqream_studio/getting_started.rst @@ -26,6 +26,8 @@ Logging In to Studio When you sign in, the License Warning is displayed. +.. _monitoring_workers_and_services_from_the_dashboard: + Navigating Studio's Main Features ----------------------------------- From 997143d3ada8cf8ff033c525a87d5d3e8a354304 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:29:49 +0300 Subject: [PATCH 1367/1892] Update index.rst --- architecture/index.rst | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/architecture/index.rst b/architecture/index.rst index 17c27e984..213700b35 100644 --- a/architecture/index.rst +++ b/architecture/index.rst @@ -1,16 +1,14 @@ .. _architecture: -******************* +************ Architecture -******************* +************ -The :ref:`internals_architecture` and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. +The :ref:`internals_architecture`, :ref:`concurrency_and_scaling_in_sqream`, and :ref:`filesystem_and_filesystem_usage` guides are walk-throughs for end-users, database administrators, and system architects who wish to get familiarized with the SQreamDB system and its unique capabilities. .. figure:: /_static/images/sqream_db_table_crop.png :scale: 60 % - - .. toctree:: :hidden: From 6533021d2bd7ea272a19808b461853fc86dd6959 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 16 Jun 2024 13:59:52 +0300 Subject: [PATCH 1368/1892] Update create_foreign_table.rst --- .../ddl_commands/create_foreign_table.rst | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 12288a310..3f91975f2 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -8,10 +8,7 @@ CREATE FOREIGN TABLE Changes in the source data can result in corresponding modifications to the content of a foreign table. Consistent access to remote files might impact performance. -Permissions -=========== -The role must have the ``CREATE`` permission at the database level. Syntax ====== @@ -93,7 +90,14 @@ Parameters * - ``QUOTE`` - Specifies an alternative quote character. The quote character must be a single, 1-byte printable ASCII character, and the equivalent octal syntax of the copy command can be used. The quote character cannot be contained in the field delimiter, the record delimiter, or the null marker. QUOTE can be used with ``csv_fdw`` in ``COPY FROM`` and foreign tables. The following characters cannot be an alternative quote character: ``"-.:\\0123456789abcdefghijklmnopqrstuvwxyzN"`` +Usage Notes +=========== +The automatic foreign table DDL resolution feature supports Parquet, ORC, JSON, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. + +Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. + +.. note:: When using this feature, SQream assumes that all files in the path use the same schema. Examples =========== @@ -233,4 +237,11 @@ Customizing Quotations Using Alternative Characters LOCATION = '/home/rhendricks/cool_animals.csv', DELIMITER = '\t', QUOTE = '@' - ); \ No newline at end of file + ); + +Permissions +=========== + +The role must have the ``CREATE`` permission at the database level. + +The automatic foreign table DDL resolution feature requires **Read** permissions. \ No newline at end of file From 1c817fbf5bc12c6b42bd4a0cce2cb5257dd389e6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jun 2024 08:33:01 +0300 Subject: [PATCH 1369/1892] Update create_table.rst --- reference/sql/sql_statements/ddl_commands/create_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index 9e0f81e59..ed456f378 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -41,7 +41,7 @@ Syntax | IDENTITY [ ( start_with [ , increment_by ] ) ] Parameters -============ +========== The following parameters can be used when creating a table: From 7044c584f883f5c0cfb84ac6fa9374429501c2a6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:41:20 +0300 Subject: [PATCH 1370/1892] Update create_table.rst --- .../ddl_commands/create_table.rst | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_table.rst b/reference/sql/sql_statements/ddl_commands/create_table.rst index ed456f378..111e15229 100644 --- a/reference/sql/sql_statements/ddl_commands/create_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_table.rst @@ -6,9 +6,7 @@ CREATE TABLE The ``CREATE TABLE`` statement is used to create a new table in an existing database. -.. tip:: - * To create a table based on the result of a select query, see :ref:`CREATE TABLE AS <create_table_as>`. - * To create a table based on files like Parquet and ORC, see :ref:`CREATE FOREIGN TABLE <create_foreign_table>` +See also: :ref:`CREATE TABLE AS <create_table_as>`, :ref:`CREATE FOREIGN TABLE <create_foreign_table>` .. contents:: :local: @@ -52,20 +50,23 @@ The following parameters can be used when creating a table: * - Parameter - Description * - ``OR REPLACE`` - - Creates a new table and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check table contents or structure, only the table name. + - Creates a new table and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check table contents or structure, only the table name * - ``schema_name`` - - The name of the schema in which to create the table. + - The name of the schema in which to create the table * - ``table_name`` - - The name of the table to create, which must be unique inside the schema. + - The name of the table to create, which must be unique inside the schema * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally + * - ``LIKE`` + - Duplicates the column structure of an existing table. The newly created table is granted default ``CREATE TABLE`` permissions: ``SELECT``, ``INSERT``, ``DELETE``, ``DDL``, and ``UPDATE`` + * - ``INCLUDE PERMISSIONS`` + - In addition to the default ``CREATE TABLE`` permissions (``SELECT``, ``INSERT``, ``DELETE``, ``DDL``, and ``UPDATE``), the newly created table is granted the source table existing permissions * - ``CLUSTER BY column_name1 ...`` - - A comma separated list of clustering column keys. + A comma separated list of clustering column keys - See :ref:`cluster_by` for more information. - * - ``LIKE`` - - Duplicates the column structure of an existing table. + See :ref:`cluster_by` for more information + Usage Notes =========== From 42f0af12c03ed27333a46f7899d7bcd02d73f921 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:19:31 +0300 Subject: [PATCH 1371/1892] Update alter_table.rst --- .../ddl_commands/alter_table.rst | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/alter_table.rst b/reference/sql/sql_statements/ddl_commands/alter_table.rst index 4046a31fe..752125ad2 100644 --- a/reference/sql/sql_statements/ddl_commands/alter_table.rst +++ b/reference/sql/sql_statements/ddl_commands/alter_table.rst @@ -1,17 +1,23 @@ .. _alter_table: -********************** +*********** ALTER TABLE -********************** -You can use the ``ALTER TABLE`` command to make schema changes to a table, and can be used in conjunction with several sub-commands. +*********** -Locks -======= -Making changes to a schema makes an exclusive lock on tables. While these operations do not typically take much time, other statements may have to wait until the schema changes are completed. +You can use the ``ALTER TABLE`` command to: + +* Add, drop, and rename table columns +* Rename tables +* Add and reorder table clustering keys +* Drop table clustering keys + +Usage Note +========== + +Making changes to a schema makes an :ref:`exclusive lock<concurrency_and_locks>` on tables. While these operations do not typically take much time, other statements may have to wait until the schema changes are completed. Sub-Commands -============== -The following table shows the sub-commands that can be used with the ``ALTER TABLE`` command: +============ .. list-table:: :widths: auto From 323e3bf6c6ee9c6920733d27bfd569b956f1c52a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:45:07 +0300 Subject: [PATCH 1372/1892] ALTER TABLE maintenance --- .../ddl_commands/add_column.rst | 82 +++++++++---------- .../ddl_commands/cluster_by.rst | 76 ++++++++--------- .../ddl_commands/drop_clustering_key.rst | 45 +++++----- .../ddl_commands/drop_column.rst | 55 ++++++------- .../ddl_commands/rename_column.rst | 59 +++++-------- .../ddl_commands/rename_table.rst | 45 +++++----- 6 files changed, 163 insertions(+), 199 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/add_column.rst b/reference/sql/sql_statements/ddl_commands/add_column.rst index 0cf7143fd..0fb006226 100644 --- a/reference/sql/sql_statements/ddl_commands/add_column.rst +++ b/reference/sql/sql_statements/ddl_commands/add_column.rst @@ -1,40 +1,35 @@ .. _add_column: -********************** +********** ADD COLUMN -********************** +********** The ``ADD COLUMN`` command is used to add columns to an existing table. Syntax -========== - -The following is the correct syntax for adding a column to an existing table: +====== .. code-block:: postgres - alter_table_add_column_statement ::= - ALTER TABLE [schema_name.]table_name { ADD COLUMN column_def [, ...] } - ; + ALTER TABLE [schema_name.]table_name { ADD COLUMN column_def [, ...] } - table_name ::= identifier - - schema_name ::= identifier - - column_def :: = { column_name type_name [ default ] [ column_constraint ] CHECK('CS "compression_type"') } + schema_name ::= identifier + + table_name ::= identifier + + column_def ::= + { column_name type_name [ default ] [ column_constraint ] CHECK('CS "compression_type"') } - column_name ::= identifier - - column_constraint ::= - { NOT NULL | NULL } - - default ::= - DEFAULT default_value + column_name ::= identifier + + column_constraint ::= + { NOT NULL | NULL } + + default ::= + DEFAULT default_value Parameters -============ - -The following parameters can be used for adding a table: +========== .. list-table:: :widths: auto @@ -43,13 +38,13 @@ The following parameters can be used for adding a table: * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``table_name`` - - The table name to apply the change to. + - The table name to apply the change to * - ``ADD COLUMN column_def`` - A comma separated list of ADD COLUMN commands * - ``column_def`` - - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + - A column definition. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally Usage Notes =========== @@ -57,40 +52,43 @@ Usage Notes When adding an empty column, the default values for that column will be set to ``NULL``. Examples -=========== +======== Adding a Simple Column with a Default Value ------------------------------------------ - -This example shows how to add a simple column with a default value: +------------------------------------------- .. code-block:: postgres - ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; + ALTER TABLE + cool_animals + ADD + COLUMN number_of_eyes INT DEFAULT 2 NOT NULL; Adding Several Columns in One Command -------------------------------------------- - -This example shows how to add several columns in one command: +------------------------------------- .. code-block:: postgres - ALTER TABLE cool_animals - ADD COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, - ADD COLUMN date_seen DATE DEFAULT '2019-08-01'; + ALTER TABLE + cool_animals + ADD + COLUMN number_of_eyes INT DEFAULT 2 NOT NULL, + ADD + COLUMN date_seen DATE DEFAULT '2019-08-01'; Adding Compressed Column --------------------------- +------------------------ .. code-block:: - ALTER TABLE coo_animals ADD COLUMN animal_salary INT CHECK('CS "dict"'); + ALTER TABLE + coo_animals + ADD + COLUMN animal_salary INT CHECK('CS "dict"'); Follow SQreamDB :ref:`compression guide<compression>` for compression types and methods. - Permissions -============= +=========== The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/cluster_by.rst b/reference/sql/sql_statements/ddl_commands/cluster_by.rst index 7dcedaaf1..1d1aa4ae2 100644 --- a/reference/sql/sql_statements/ddl_commands/cluster_by.rst +++ b/reference/sql/sql_statements/ddl_commands/cluster_by.rst @@ -1,46 +1,35 @@ .. _cluster_by: -********************** +********** CLUSTER BY -********************** -The ``CLUSTER BY`` command is used for changing clustering keys in a table. +********** -For more information, see the following: +The ``CLUSTER BY`` command is used for changing clustering keys in a table. -* :ref:`drop_clustering_key` - - :: - -* :ref:`create_table` +For more information, see :ref:`drop_clustering_key`, :ref:`create_table` Syntax -========== -The following is the correct syntax for the CLUSTER BY command: +====== .. code-block:: postgres - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] - ; - - create_table_statement ::= - CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( - { column_def [, ...] } - ) - [ CLUSTER BY { column_name [, ...] } ] - ; - - column_def :: = { column_name type_name [ default ] [ column_constraint ] } + ALTER TABLE [schema_name.]table_name CLUSTER BY column_name [, ...] - table_name ::= identifier + + create_table_statement ::= + CREATE [ OR REPLACE ] TABLE [schema_name.]table_name ( + { column_def [, ...] } + ) + [ CLUSTER BY { column_name [, ...] } ] - column_name ::= identifier + column_def :: = { column_name type_name [ default ] [ column_constraint ] } -.. note:: SQream does not support clustering by TEXT columns. + table_name ::= identifier + + column_name ::= identifier Parameters -============ -The following table shows the CLUSTER BY parameters: +========== .. list-table:: :widths: auto @@ -49,33 +38,38 @@ The following table shows the CLUSTER BY parameters: * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``OR REPLACE`` - - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name. + - Creates a new tables and overwrites any existing table by the same name. Does not return an error if the table already exists. ``CREATE OR REPLACE`` does not check the table contents or structure, only the table name * - ``column_def`` - - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally. + - A comma separated list of column definitions. A minimal column definition includes a name identifier and a datatype. Other column constraints and default values can be added optionally * - ``table_name`` - - The table name to apply the change to. + - The table name to apply the change to * - ``column_name [, ... ]`` - - Comma separated list of columns to create clustering keys for. + - Comma separated list of columns to create clustering keys for Usage Notes -================= -Removing clustering keys does not affect existing data. +=========== + +* Clustering by ``TEXT`` columns is not supported + +* Removing clustering keys does not affect existing data -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table`). +* To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table`). Example -=========== +======= + Reclustering a Table ------------------------------------------ -The following example shows how to recluster a table: +-------------------- .. code-block:: postgres - ALTER TABLE public.users CLUSTER BY start_date; + ALTER TABLE + public.users CLUSTER BY start_date; Permissions -============= +=========== + The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst index 73d822631..42c457c3f 100644 --- a/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst +++ b/reference/sql/sql_statements/ddl_commands/drop_clustering_key.rst @@ -1,8 +1,8 @@ .. _drop_clustering_key: -********************** +******************* DROP CLUSTERING KEY -********************** +******************* ``DROP CLUSTERING KEY`` drops all clustering keys in a table. @@ -10,25 +10,17 @@ Read our :ref:`cluster_by` guide for more information. See also :ref:`create_table` - -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - Syntax -========== +====== .. code-block:: postgres - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]table_name DROP CLUSTERING KEY - ; + ALTER TABLE [schema_name.]table_name DROP CLUSTERING KEY - table_name ::= identifier + table_name ::= identifier Parameters -============ +========== .. list-table:: :widths: auto @@ -37,28 +29,29 @@ Parameters * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``table_name`` - - The table name to apply the change to. + - The table name to apply the change to Usage notes -================= - -Removing clustering keys does not affect existing data. - -To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`). - +=========== +* Removing clustering keys does not affect existing data +* To force data to re-cluster, the table has to be recreated (i.e. with :ref:`create_table_as`) Examples -=========== +======== -Dropping clustering keys in a table ------------------------------------------ +Dropping Clustering Keys in a Table +----------------------------------- .. code-block:: postgres - ALTER TABLE public.users DROP CLUSTERING KEY + ALTER TABLE + public.users DROP CLUSTERING KEY +Permissions +=========== +The role must have the ``DDL`` permission at the database or table level. diff --git a/reference/sql/sql_statements/ddl_commands/drop_column.rst b/reference/sql/sql_statements/ddl_commands/drop_column.rst index f4c4e4504..0fa54c049 100644 --- a/reference/sql/sql_statements/ddl_commands/drop_column.rst +++ b/reference/sql/sql_statements/ddl_commands/drop_column.rst @@ -1,35 +1,26 @@ .. _drop_column: -********************** +*********** DROP COLUMN -********************** +*********** ``DROP COLUMN`` can be used to remove columns from a table. -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - Syntax -========== +====== .. code-block:: postgres - alter_table_drop_column_statement ::= - ALTER TABLE [schema_name.]table_name DROP COLUMN column_name - ; - - table_name ::= identifier - - schema_name ::= identifier - - column_name ::= identifier + ALTER TABLE [schema_name.]table_name DROP COLUMN column_name + schema_name ::= identifier + + table_name ::= identifier + column_name ::= identifier Parameters -============ +========== .. list-table:: :widths: auto @@ -38,26 +29,32 @@ Parameters * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``table_name`` - - The table name to apply the change to. + - The table name to apply the change to * - ``column_name`` - - The column to remove. + - The column to remove Examples -=========== +======== -Removing a column ------------------------------------------ +Removing a Column +----------------- .. code-block:: postgres - -- Remove the 'weight' column - ALTER TABLE users DROP COLUMN weight; + ALTER TABLE + users DROP COLUMN weight; -Removing a column with a quoted identifier name ----------------------------------------------------- +Removing a Column with a Quoted Identifier Name +----------------------------------------------- .. code-block:: postgres - ALTER TABLE users DROP COLUMN "Weight in kilograms"; \ No newline at end of file + ALTER TABLE + users DROP COLUMN "Weight in kilograms"; + +Permissions +=========== + +The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/rename_column.rst b/reference/sql/sql_statements/ddl_commands/rename_column.rst index 239d7c7f8..51e1e035a 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_column.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_column.rst @@ -1,34 +1,28 @@ .. _rename_column: -********************** +************* RENAME COLUMN -********************** +************* The ``RENAME COLUMN`` command can be used to rename columns in a table. Syntax -========== - -The following is the correct syntax for the ``RENAME_COLUMN`` command: +====== .. code-block:: postgres - alter_table_rename_column_statement ::= - ALTER TABLE [schema_name.]table_name RENAME COLUMN current_name TO new_name - ; + ALTER TABLE [schema_name.]table_name RENAME COLUMN current_name TO new_name - table_name ::= identifier - - schema_name ::= identifier + schema_name ::= identifier + + table_name ::= identifier - current_name ::= identifier + current_name ::= identifier - new_name ::= identifier + new_name ::= identifier Parameters -============ - -The following table describes the `RENAME_COLUMN`` parameters: +========== .. list-table:: :widths: auto @@ -37,43 +31,34 @@ The following table describes the `RENAME_COLUMN`` parameters: * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``table_name`` - - The table name to apply the change to. + - The table name to apply the change to * - ``current_name`` - - The column to rename. + - The column to rename * - ``new_name`` - - The new column name. + - The new column name Examples -=========== - -The **Examples** section includes the following examples: - -.. contents:: - :local: - :depth: 1 +======== Renaming a Column ------------------------------------------ - -The following is an example of renaming a column: +----------------- .. code-block:: postgres - -- Remove the 'weight' column - ALTER TABLE users RENAME COLUMN weight TO mass; + ALTER TABLE + users RENAME COLUMN weight TO mass; Renaming a Quoted Name --------------------------- - -The following is an example of renaming a quoted name: +---------------------- .. code-block:: postgres - ALTER TABLE users RENAME COLUMN "mass" TO "Mass" (Kilograms); + ALTER TABLE + users RENAME COLUMN "mass" TO "Mass" (Kilograms); Permissions -============= +=========== The role must have the ``DDL`` permission at the database or table level. \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/rename_table.rst b/reference/sql/sql_statements/ddl_commands/rename_table.rst index 96cc7102e..f426dfdc3 100644 --- a/reference/sql/sql_statements/ddl_commands/rename_table.rst +++ b/reference/sql/sql_statements/ddl_commands/rename_table.rst @@ -1,35 +1,28 @@ .. _rename_table: -********************** +************ RENAME TABLE -********************** +************ ``RENAME TABLE`` can be used to rename a table. .. warning:: Renaming a table can void existing views that use this table. See more about :ref:`recompiling views <recompile_view>`. -Permissions -============= - -The role must have the ``DDL`` permission at the database or table level. - Syntax -========== +====== .. code-block:: postgres - alter_table_rename_table_statement ::= - ALTER TABLE [schema_name.]current_name RENAME TO new_name - ; + ALTER TABLE [schema_name.]current_name RENAME TO new_name - current_name ::= identifier - - schema_name ::= identifier - - new_name ::= identifier + schema_name ::= identifier + + current_name ::= identifier + + new_name ::= identifier Parameters -============ +========== .. list-table:: :widths: auto @@ -38,20 +31,24 @@ Parameters * - Parameter - Description * - ``schema_name`` - - The schema name for the table. Defaults to ``public`` if not specified. + - The schema name for the table. Defaults to ``public`` if not specified * - ``current_name`` - - The table name to apply the change to. + - The table name to apply the change to * - ``new_name`` - - The new table name. + - The new table name Examples -=========== +======== -Renaming a table ------------------------------------------ +Renaming a Table +---------------- .. code-block:: postgres - ALTER TABLE public.users RENAME TO former_users; + ALTER TABLE + public.users RENAME TO former_users; +Permissions +=========== +The role must have the ``DDL`` permission at the database or table level. From 858bcb0ee3af2aeb134d9bd46d63594a3e3b5690 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jun 2024 11:37:31 +0300 Subject: [PATCH 1373/1892] Maintenance --- conf.py | 6 ++---- releases/4.4.rst | 2 -- .../configuring_your_instance_of_sqream.rst | 13 +++++++------ 3 files changed, 9 insertions(+), 12 deletions(-) diff --git a/conf.py b/conf.py index 122608702..293ced6d2 100644 --- a/conf.py +++ b/conf.py @@ -59,16 +59,14 @@ # a list of builtin themes. # html_theme = 'sphinx_rtd_theme' -html_favicon = "_static/images/favicon-light.png" + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -favicons = [ - "_static/images/favicon-light.png" -] + html_css_files = [ diff --git a/releases/4.4.rst b/releases/4.4.rst index 55dbe8de1..76d008789 100644 --- a/releases/4.4.rst +++ b/releases/4.4.rst @@ -40,8 +40,6 @@ New Features and Enhancements ► :ref:`denodo` may now be used for real-time data visualization of various sources. -► Introducing :ref:`select_data_read_metrics` utility function, facilitating easy monitoring of cluster data read within specified timeframes, ensuring adherence to license limits. - ► New :ref:`select_gpu_metrics` utility function now available, providing insights into cluster GPU usage over defined periods, crucial for maintaining compliance with license limits. Newly Released Connector Drivers diff --git a/sqream_studio/configuring_your_instance_of_sqream.rst b/sqream_studio/configuring_your_instance_of_sqream.rst index b5a26f2bb..17d9bc43c 100644 --- a/sqream_studio/configuring_your_instance_of_sqream.rst +++ b/sqream_studio/configuring_your_instance_of_sqream.rst @@ -1,15 +1,17 @@ .. _configuring_your_instance_of_sqream: -**************************** +************************************ Configuring Your Instance of SQreams -**************************** +************************************ + The **Configuration** section lets you edit parameters from one centralized location. While you can edit these parameters from the **worker configuration file (config.json)** or from your CLI, you can also modify them in Studio in an easy-to-use format. Configuring your instance of SQream in Studio is session-based, which enables you to edit parameters per session on your own device. Because session-based configurations are not persistent and are deleted when your session ends, you can edit your required parameters while avoiding conflicts between parameters edited on different devices at different points in time. Editing Your Parameters -------------------------------- +----------------------- + When configuring your instance of SQream in Studio you can edit session and cluster parameters only. Studio includes two types of parameters: toggle switches, such as **flipJoinOrder**, and text fields, such as **logSysLevel**. After editing a parameter, you can reset each one to its previous value or to its default value individually, or revert all parameters to their default setting simultaneously. Note that you must click **Save** to save your configurations. @@ -17,7 +19,6 @@ Studio includes two types of parameters: toggle switches, such as **flipJoinOrde You can hover over the **information** icon located on each parameter to read a short description of its behavior. Exporting and Importing Configuration Files -------------------------- -You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. +------------------------------------------- -For more information about configuring your instance of SQream, see :ref:`Configuration<configuration>`. \ No newline at end of file +You can also export and import your configuration settings into a .json file. This allows you to easily edit your parameters and to share this file with other users if required. \ No newline at end of file From 3ba12358fd72fe8a72b2f11bb8c1607f9dc74774 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jun 2024 12:53:07 +0300 Subject: [PATCH 1374/1892] Maintenance --- configuration_guides/graceful_shutdown.rst | 4 ++-- connecting_to_sqream/client_drivers/Spark/index.rst | 2 +- .../client_drivers/odbc/install_configure_odbc_windows.rst | 2 +- connecting_to_sqream/client_platforms/r.rst | 2 +- connecting_to_sqream/client_platforms/sql_workbench.rst | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configuration_guides/graceful_shutdown.rst b/configuration_guides/graceful_shutdown.rst index f461a5262..ba9c8a57f 100644 --- a/configuration_guides/graceful_shutdown.rst +++ b/configuration_guides/graceful_shutdown.rst @@ -12,10 +12,10 @@ The following describes the ``defaultGracefulShutdownTimeoutMinutes`` flag: * **Default value** - ``5`` * **Allowed values** - 1-4000000000 -For more information, see :ref:`shutdown_server`. +For more information, see :ref:`shutdown_server_command`. For related flags, see the folowing: * :ref:`is_healer_on` -* :ref:`healer_max_inactivity_hours` \ No newline at end of file +* :ref:`current_method_flag_types` \ No newline at end of file diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst index 5c616e437..03ef309c3 100644 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ b/connecting_to_sqream/client_drivers/Spark/index.rst @@ -18,7 +18,7 @@ To use Spark with SQreamDB, it is essential that you have the following installe * SQreamDB version 2022.1.8 or later * Spark version 3.3.1 or later * `SQreamDB Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ -* :ref:`JDBC<jdbc>` version 4.5.6 or later +* :ref:`JDBC<java_jdbc>` version 4.5.6 or later Configuration ============= diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst index 92a947e57..9dd0c3f22 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_windows.rst @@ -80,7 +80,7 @@ ODBC driver configurations are done via DSNs. Each DSN represents one SQream DB .. image:: /_static/images/odbc_windows_dsn_test.png -#. You can now use this DSN in ODBC applications like :ref:`Tableau <connect_to_tableau>`. + diff --git a/connecting_to_sqream/client_platforms/r.rst b/connecting_to_sqream/client_platforms/r.rst index a79015363..47fc680a2 100644 --- a/connecting_to_sqream/client_platforms/r.rst +++ b/connecting_to_sqream/client_platforms/r.rst @@ -44,7 +44,7 @@ JDBC > .jinit(classpath=cp) > drv <- JDBC("com.sqream.jdbc.SQDriver","C:\\Program Files\\SQream Technologies\\JDBC Driver\\2020.1-3.2.0\\sqream-jdbc-3.2.jar") #. - Open a connection with a :ref:`JDBC connection string<connection_string>` and run your first statement + Open a connection with a :ref:`JDBC connection string<java_jdbc>` and run your first statement .. code-block:: rconsole diff --git a/connecting_to_sqream/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst index cc3228892..8d983eed9 100644 --- a/connecting_to_sqream/client_platforms/sql_workbench.rst +++ b/connecting_to_sqream/client_platforms/sql_workbench.rst @@ -115,7 +115,7 @@ Create a New Connection Profile for Your Cluster #. Select the SQream Driver that was created in the previous screen -#. Type in your connection string. To find out more about your connection string (URL), see the :ref:`Connection string documentation <connection_string>`. +#. Type in your connection string. #. Text the connection details From 2a6f1a9d7b6734e9d4a24610b9ad4d94f93b7f21 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jun 2024 13:30:20 +0300 Subject: [PATCH 1375/1892] Maintenance --- data_ingestion/ingesting_data.rst | 2 +- data_ingestion/orc.rst | 2 +- data_ingestion/sqloader_as_a_service.rst | 2 +- feature_guides/python_functions.rst | 4 ++-- feature_guides/query_healer.rst | 8 +++++--- getting_started/inserting_rows.rst | 6 +++--- .../saving_query_results_to_a_csv_or_psv_file.rst | 4 ++-- operational_guides/monitoring_query_performance.rst | 2 +- 8 files changed, 16 insertions(+), 14 deletions(-) diff --git a/data_ingestion/ingesting_data.rst b/data_ingestion/ingesting_data.rst index 1a3200512..68d114e13 100644 --- a/data_ingestion/ingesting_data.rst +++ b/data_ingestion/ingesting_data.rst @@ -67,7 +67,7 @@ Like many RDBMSs, SQream recommends its own set of best practices for table desi * That you followed the table design best practices (:ref:`Optimization and Best Practices<sql_best_practices>`). -* That you've tested and verified that your applications work (such as :ref:`Tableau<connect_to_tableau>`). +* That you've tested and verified that your applications work. * That your data types have not been not over-provisioned. diff --git a/data_ingestion/orc.rst b/data_ingestion/orc.rst index d52ca002c..5be02eb72 100644 --- a/data_ingestion/orc.rst +++ b/data_ingestion/orc.rst @@ -4,7 +4,7 @@ ORC *** -This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE<external_tables>`. +This guide covers ingesting data from ORC files into SQream DB using :ref:`FOREIGN TABLE<foreign_tables>`. .. contents:: :local: diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index e407a9984..bc0f0d1de 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -62,7 +62,7 @@ Getting All Configuration and JAR Files Extract the ``.tar`` file using the following command: -.. code-block:: linux +.. code-block:: bash tar -xf sqloader_srv_v8.0.tar.gz diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 2aca0a035..8212fab98 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -134,8 +134,8 @@ You can write a function in Python to uppercase a text value using the :ref:`cre Let's break down this example: * ``CREATE FUNCTION my_upper`` - :ref:`Create a function<create_function>` called ``my_upper``. This name must be unique in the current database -* ``(x1 text)`` - the function accepts one argument named ``x1`` which is of the SQL type ``TEXT``. All :ref:`data types<data_types>` are supported. -* ``RETURNS text`` - the function returns the same type - ``TEXT``. All :ref:`data types<data_types>` are supported. +* ``(x1 text)`` - the function accepts one argument named ``x1`` which is of the SQL type ``TEXT``. All :ref:`data types<supported_data_types>` are supported. +* ``RETURNS text`` - the function returns the same type - ``TEXT``. All :ref:`data types<supported_data_types>` are supported. * ``AS $$`` - what follows is some code that we don't want to quote, so we use dollar-quoting (``$$``) instead of single quotes (``'``). * ``return x1.upper()`` - the Python function's body is the argument named ``x1``, uppercased. * ``$$ LANGUAGE PYTHON`` - this is the end of the function, and it's in the Python language. diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 84181dbbe..ba07d3f11 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -1,14 +1,15 @@ .. _query_healer: -*********************** +************ Query Healer -*********************** +************ The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding a defined time period. Configuration ------------- + The following worker flags are required to configure the Query Healer: .. list-table:: @@ -20,7 +21,7 @@ The following worker flags are required to configure the Query Healer: * - ``is_healer_on`` - The :ref:`is_healer_on` enables and disables the Query Healer. * - ``maxStatementInactivitySeconds`` - - The :ref:`healer_max_statement_inactivity_seconds` worker level flag defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The default setting is five hours. + - The :ref:`max_statement_inactivity_seconds` worker level flag defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The default setting is five hours. * - ``healerDetectionFrequencySeconds`` - The :ref:`healer_detection_frequency_seconds` worker level flag triggers the healer to examine the progress of running statements. The default setting is one hour. @@ -37,6 +38,7 @@ Once you identify the stuck worker, you can execute the ``shutdown_server`` util Activating a Graceful Shutdown ------------------------------ + You can activate a graceful shutdown if your log entry says ``Stuck query found``, as shown in the example above. You can do this by setting the **shutdown_server** utility function to ``select shutdown_server();``. **To activte a graceful shutdown:** diff --git a/getting_started/inserting_rows.rst b/getting_started/inserting_rows.rst index d52f133a5..aa2bcd534 100644 --- a/getting_started/inserting_rows.rst +++ b/getting_started/inserting_rows.rst @@ -1,8 +1,8 @@ .. _inserting_rows: -**************************** +************** Inserting Rows -**************************** +************** The **Inserting Rows** section describes the following: @@ -48,7 +48,7 @@ You can insert multiple rows using the ``INSERT`` statement by using sets of par (5, 'Rhinoceros', 2100); -.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`inserting_data`. +.. note:: You can load large data sets using bulk loading methods instead. For more information, see :ref:`ingesting_data`. .. _omitting_columns: diff --git a/getting_started/saving_query_results_to_a_csv_or_psv_file.rst b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst index c5da4d3ed..f51ddaa10 100644 --- a/getting_started/saving_query_results_to_a_csv_or_psv_file.rst +++ b/getting_started/saving_query_results_to_a_csv_or_psv_file.rst @@ -10,7 +10,7 @@ You can save query results to a CSV or PSV file using the ``sqream sql`` command $ sqream sql --username=mjordan --database=nba --host=localhost --port=5000 -c "SELECT * FROM nba LIMIT 5" --results-only --delimiter='|' > nba.psv $ cat nba.psv - Avery Bradley |Boston Celtics |0|PG|25|6-2 |180|Texas |7730337 + Avery Bradley |Boston Celtics |0|PG|25|6-2 |180|Texas |7730337 Jae Crowder |Boston Celtics |99|SF|25|6-6 |235|Marquette |6796117 John Holland |Boston Celtics |30|SG|27|6-5 |205|Boston University |\N R.J. Hunter |Boston Celtics |28|SG|22|6-5 |185|Georgia State |1148640 @@ -22,4 +22,4 @@ For more output options, see :ref:`Controlling the Client Output<controlling_out * Explore all of SQream DB's :ref:`SQL Syntax <sql_syntax>`. * See the full :ref:`SQream SQL CLI reference <sqream_sql_cli_reference>`. -* Connect a :ref:`third party tool <third_party_tools>` to start analyzing data. \ No newline at end of file +* Connect a :ref:`third party tool <client_platforms>` to start analyzing data. \ No newline at end of file diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index d80453e78..51552a921 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -271,7 +271,7 @@ Commonly Seen Nodes - Reads data from a standard table stored on disk * - ``Rechunk`` - - - Reorganize multiple small :ref:`chunks<chunks_and_extents>` into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY<high_selectivity>` is used + - Reorganize multiple small chunks into a full chunk. Commonly found after joins and when :ref:`HIGH_SELECTIVITY<high_selectivity>` is used * - ``Reduce`` - GPU - A reduction operation, such as a ``GROUP BY`` From a60145672828551c13b5dce0faf117b780ca8512 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 18 Jun 2024 14:45:03 +0300 Subject: [PATCH 1376/1892] Maintenance --- data_type_guides/sql_data_types_numeric.rst | 2 +- operational_guides/query_split.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data_type_guides/sql_data_types_numeric.rst b/data_type_guides/sql_data_types_numeric.rst index 6a7a7b6ec..e97528b63 100644 --- a/data_type_guides/sql_data_types_numeric.rst +++ b/data_type_guides/sql_data_types_numeric.rst @@ -4,7 +4,7 @@ Numeric ******* -The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point <floating_point>` is recommended. +The **Numeric** data type (also known as **Decimal**) is recommended for values that tend to occur as exact decimals, such as in Finance. While Numeric has a fixed precision of ``38``, higher than ``REAL`` (``9``) or ``DOUBLE`` (``17``), it runs calculations more slowly. For operations that require faster performance, using :ref:`Floating Point <sql_data_types_floating_point>` is recommended. The correct syntax for Numeric is ``numeric(p, s)``), where ``p`` is the total number of digits (``38`` maximum), and ``s`` is the total number of decimal digits. If no parameters are specified, Numeric defaults to ``numeric(38, 0)``. diff --git a/operational_guides/query_split.rst b/operational_guides/query_split.rst index 493775e41..239f9e7e7 100644 --- a/operational_guides/query_split.rst +++ b/operational_guides/query_split.rst @@ -255,7 +255,7 @@ Splitting the Query 3. Set the ``@@SplitQueryByNumber`` operator with the number of instances (splits) of your query (here based on an ``INTEGER`` column), and set the ``between ${from} and ${to}`` clause with the name of the column by which you wish to split your query (here the query is split by the ``age`` column. -.. code-block:: sql +.. code-block:: postgres @@SplitQueryByNumber instances = 4, from = minMax[0].min, to = minMax[0].max INSERT INTO FinalResult @@ -270,8 +270,8 @@ Splitting the Query SUM(CASE WHEN age BETWEEN 25 AND 30 THEN salary ELSE 0 END) AS total_salary_age_25_30 FROM MyTable - WHERE - age between ${from} and ${to} + WHERE + age between '${from}' and '${to}' AND salary > 55000 GROUP BY age From 64c50664998a0c213fd66901e42efa8de58b6f47 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 19 Jun 2024 08:06:52 +0300 Subject: [PATCH 1377/1892] Update create_foreign_table.rst --- .../sql/sql_statements/ddl_commands/create_foreign_table.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 3f91975f2..28f85a949 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -6,10 +6,6 @@ CREATE FOREIGN TABLE ``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. -Changes in the source data can result in corresponding modifications to the content of a foreign table. Consistent access to remote files might impact performance. - - - Syntax ====== From 9b0d1fcce7149f32d688d2a28921b85bc0401e39 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 19 Jun 2024 08:07:48 +0300 Subject: [PATCH 1378/1892] Update create_foreign_table.rst --- .../sql/sql_statements/ddl_commands/create_foreign_table.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 28f85a949..74eba0048 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -96,7 +96,7 @@ Using this feature the path you specify in the ``LOCATION`` option must point to .. note:: When using this feature, SQream assumes that all files in the path use the same schema. Examples -=========== +======== Creating a Tab-Delimited Table ------------------------------ From eaa94a5b82f94f6238c0fb8a7461f4611b6fce98 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 19 Jun 2024 09:40:28 +0300 Subject: [PATCH 1379/1892] Remove foreign table ddl resolution --- data_ingestion/json.rst | 2 +- ...automatic_foreign_table_ddl_resolution.rst | 47 ------------------- feature_guides/index.rst | 1 - .../ddl_commands/create_foreign_table.rst | 4 +- 4 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 feature_guides/automatic_foreign_table_ddl_resolution.rst diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index 1c273e614..eec94c891 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`Automatic Foreign Table DDL Resolution<automatic_foreign_table_ddl_resolution>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE nba WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY nba FROM WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY nba TO WRAPPER json_fdw OPTIONS (location = 's3://sqream-docs/nba.json'); When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t (id int not null) WRAPPER json_fdw OPTIONS (location = 'sqream-docs.json'); The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS (LOCATION = 'sqream-docs.json'); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`CREATE FOREIGN TABLE<create_foreign_table>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE nba WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY nba FROM WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY nba TO WRAPPER json_fdw OPTIONS (location = 's3://sqream-docs/nba.json'); When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t (id int not null) WRAPPER json_fdw OPTIONS (location = 'sqream-docs.json'); The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS (LOCATION = 'sqream-docs.json'); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/feature_guides/automatic_foreign_table_ddl_resolution.rst b/feature_guides/automatic_foreign_table_ddl_resolution.rst deleted file mode 100644 index 580acd87a..000000000 --- a/feature_guides/automatic_foreign_table_ddl_resolution.rst +++ /dev/null @@ -1,47 +0,0 @@ -.. _automatic_foreign_table_ddl_resolution: - -************************************** -Automatic Foreign Table DDL Resolution -************************************** - -SQream must be able to access a schema when reading and mapping external files to a foreign table. To facilitate this, you must specify the correct schema in the statement that creates the foreign table, which must also include the correct list of columns. To avoid human error related to this complex process SQream can now automatically identify the corresponding schema, saving you the time and effort required to build your schema manually. This is especially useful for particular file formats, such as Parquet, which include a built-in schema declaration. - -.. contents:: - :local: - :depth: 1 - -Usage Notes -=========== - -The automatic foreign table DDL resolution feature supports Parquet, ORC, JSON, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. - -Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. - -.. note:: When using this feature, SQream assumes that all files in the path use the same schema. - -Syntax -====== - -The following is the syntax for using the automatic foreign table DDL resolution feature: - -.. code-block:: sql - - CREATE FOREIGN TABLE table_name - [FOREIGN DATA] WRAPPER fdw_name - [OPTIONS (...)] - -Example -======= - -The following is an example of using the automatic foreign table DDL resolution feature: - -.. code-block:: sql - - create foreign table parquet_table - wrapper parquet_fdw - options (location = '/tmp/file.parquet'); - -Permissions -=========== - -The automatic foreign table DDL resolution feature requires **Read** permissions. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 8f0a2fe3f..672d7d423 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -10,7 +10,6 @@ The **Feature Guides** section describes background processes that SQreamDB uses :maxdepth: 1 :titlesonly: - automatic_foreign_table_ddl_resolution query_healer compression python_functions diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 74eba0048..1f6f5d76c 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -4,7 +4,7 @@ CREATE FOREIGN TABLE ******************** -``CREATE FOREIGN TABLE`` creates a new foreign table in an existing database. +The ``CREATE FOREIGN TABLE`` command creates a foreign table that references data stored outside of SQreamDB. Foreign tables are used for querying data stored in files on a file system, :ref:`external storage platforms<external_storage_platforms>`, or in other databases. Syntax ====== @@ -51,7 +51,7 @@ Syntax .. _cft_parameters: Parameters -============ +========== .. list-table:: :widths: auto From 18c336715ce6f2bc60e05896ce9e79170df4143c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:06:40 +0300 Subject: [PATCH 1380/1892] Foreign Tables --- feature_guides/.DS_Store | Bin 0 -> 6148 bytes operational_guides/foreign_tables.rst | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 11 deletions(-) create mode 100644 feature_guides/.DS_Store diff --git a/feature_guides/.DS_Store b/feature_guides/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**<q8>++&mCkOWA81W14cNZ<zv;LbK1Poaz?KmsK2CSc!( z0ynLxE!0092;Krf2c+FF_Fe*7ECH>lEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0<F0fCPF1$Cyrb|F7^5{eNG?83~ZUUlGt@xh*qZDeu<Z%US-OSsOPv j)R!Z4KLME7ReXlK;d!wEw5GODWMKRea10D2@KpjYNUI8I literal 0 HcmV?d00001 diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index c22156a1c..e5ae8df35 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -1,8 +1,8 @@ .. _foreign_tables: -*********************** +************** Foreign Tables -*********************** +************** Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. SQream DB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. @@ -16,7 +16,7 @@ Although foreign tables can be used without inserting data into SQream DB, one o :depth: 1 Supported Data Formats -===================================== +====================== SQream DB supports foreign tables over: @@ -27,7 +27,7 @@ SQream DB supports foreign tables over: * JSON Supported Data Staging -============================================ +====================== SQream can stage data from: @@ -36,12 +36,12 @@ SQream can stage data from: * :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) Using Foreign Tables -============================================== +==================== Use a foreign table to stage data before loading from CSV, Parquet or ORC files. Planning for Data Staging --------------------------------- +------------------------- For the following examples, we will interact with a CSV file. @@ -49,7 +49,7 @@ The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. Creating a Foreign Table ------------------------------ +------------------------ Based on the source file structure, we :ref:`create a foreign table<create_external_table>` with the appropriate structure, and point it to the file. @@ -78,7 +78,7 @@ The file format in this case is CSV, and it is stored as an :ref:`s3` object (if We also took note that the record delimiter was a DOS newline (``\r\n``). Querying Foreign Tables ------------------------------- +----------------------- Let's peek at the data from the foreign table: @@ -99,7 +99,7 @@ Let's peek at the data from the foreign table: Marcus Smart | Boston Celtics | 36 | PG | 22 | 6-4 | 220 | Oklahoma State | 3431040 Modifying Data from Staging -------------------------------- +--------------------------- One of the main reasons for staging data is to examine the content and modify it before loading. Assume we are unhappy with weight being in pounds because we want to use kilograms instead. We can apply the transformation as part of a query: @@ -126,7 +126,7 @@ Assume we are unhappy with weight being in pounds because we want to use kilogra Now, if we're happy with the results, we can convert the staged foreign table to a standard table Converting a Foreign Table to a Standard Database Table ---------------------------------------------------------------- +------------------------------------------------------- :ref:`create_table_as` can be used to materialize a foreign table into a regular table. @@ -150,7 +150,7 @@ Converting a Foreign Table to a Standard Database Table Andre Drummond | Detroit Pistons | 0 | C | 22 | 6-11 | 126.5306 | Connecticut | 3272091 Error Handling and Limitations -================================== +============================== * Error handling in foreign tables is limited. Any error that occurs during source data parsing will result in the statement aborting. From 21171977baf2e88eee32d5b3dd845d5f2fdae2a7 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:06:06 +0300 Subject: [PATCH 1381/1892] Foreign Table --- operational_guides/external_data.rst | 19 +++++++++-------- operational_guides/foreign_tables.rst | 30 ++++++++++++++------------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/operational_guides/external_data.rst b/operational_guides/external_data.rst index 858d4bf20..4134457a3 100644 --- a/operational_guides/external_data.rst +++ b/operational_guides/external_data.rst @@ -1,18 +1,19 @@ .. _external_data: -********************************** +************************** Working with External Data -********************************** +************************** -SQream supports the following external data sources: +SQreamDB supports the following external data sources: -.. toctree:: - :maxdepth: 1 - :titlesonly: +:ref:`s3` + +:ref:`hdfs` + +:ref:`gcp` + +:ref:`azure` - s3 - hdfs - For more information, see the following: :ref:`foreign_tables` diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index e5ae8df35..38b3affea 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -46,12 +46,12 @@ Planning for Data Staging For the following examples, we will interact with a CSV file. The file is stored on :ref:`s3`, at ``s3://sqream-demo-data/nba_players.csv``. -We will make note of the file structure, to create a matching ``CREATE_EXTERNAL_TABLE`` statement. +We will make note of the file structure, to create a matching ``CREATE FOREIGN TABLE`` statement. Creating a Foreign Table ------------------------ -Based on the source file structure, we :ref:`create a foreign table<create_external_table>` with the appropriate structure, and point it to the file. +Based on the source file structure, we :ref:`create a foreign table<create_foreign_table>` with the appropriate structure, and point it to the file. .. code-block:: postgres @@ -84,7 +84,8 @@ Let's peek at the data from the foreign table: .. code-block:: psql - t=> SELECT * FROM nba LIMIT 10; + SELECT * FROM nba LIMIT 10; + name | team | number | position | age | height | weight | college | salary --------------+----------------+--------+----------+-----+--------+--------+-------------------+--------- Avery Bradley | Boston Celtics | 0 | PG | 25 | 6-2 | 180 | Texas | 7730337 @@ -106,9 +107,9 @@ Assume we are unhappy with weight being in pounds because we want to use kilogra .. code-block:: psql - t=> SELECT name, team, number, position, age, height, (weight / 2.205) as weight, college, salary - . FROM nba - . ORDER BY weight; + SELECT name, team, number, position, age, height, (weight / 2.205) as weight, college, salary + FROM nba + ORDER BY weight; name | team | number | position | age | height | weight | college | salary -------------------------+------------------------+--------+----------+-----+--------+----------+-----------------------+--------- @@ -134,12 +135,12 @@ Converting a Foreign Table to a Standard Database Table .. code-block:: psql - t=> CREATE TABLE real_nba AS - . SELECT name, team, number, position, age, height, (weight / 2.205) as weight, college, salary - . FROM nba - . ORDER BY weight; - executed - t=> SELECT * FROM real_nba LIMIT 5; + CREATE TABLE real_nba AS + SELECT name, team, number, position, age, height, (weight / 2.205) as weight, college, salary + FROM nba + ORDER BY weight; + + SELECT * FROM real_nba LIMIT 5; name | team | number | position | age | height | weight | college | salary -----------------+------------------------+--------+----------+-----+--------+----------+-------------+--------- @@ -160,7 +161,8 @@ Error Handling and Limitations .. code-block:: psql - t=> SELECT * FROM nba; - master=> select * from nba; + SELECT * FROM nba; + + SELECT * FROM nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv * Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. From 173b926bff72f011c1127be14ec55a5d0337c6ea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:01:29 +0300 Subject: [PATCH 1382/1892] Delete index.rst --- .../client_drivers/Spark/index.rst | 274 ------------------ 1 file changed, 274 deletions(-) delete mode 100644 connecting_to_sqream/client_drivers/Spark/index.rst diff --git a/connecting_to_sqream/client_drivers/Spark/index.rst b/connecting_to_sqream/client_drivers/Spark/index.rst deleted file mode 100644 index 03ef309c3..000000000 --- a/connecting_to_sqream/client_drivers/Spark/index.rst +++ /dev/null @@ -1,274 +0,0 @@ -.. _spark: - -***** -Spark -***** - -The Spark connector enables reading and writing data to and from SQreamDB and may be used for large-scale data processing. - -.. contents:: - :local: - :depth: 1 - -Before You Begin -================= - -To use Spark with SQreamDB, it is essential that you have the following installed: - -* SQreamDB version 2022.1.8 or later -* Spark version 3.3.1 or later -* `SQreamDB Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ -* :ref:`JDBC<java_jdbc>` version 4.5.6 or later - -Configuration -============= - -The Spark JDBC connection properties empower you to customize your Spark connection. These properties facilitate various aspects, including database access, query execution, and result retrieval. Additionally, they provide options for authentication, encryption, and connection pooling. - -The following Spark connection properties are supported by SQreamDB: - -.. list-table:: - :widths: auto - :header-rows: 1 - - - * - Parameter - - Default - - Description - * - ``url`` - - - - The JDBC URL to connect to the database. - * - ``dbtable`` - - - - The JDBC URL to connect to the database. - * - ``query`` - - - - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. - * - ``driver`` - - - - The fully qualified class name of the JDBC driver to use when connecting to a relational database. - * - ``numPartitions`` - - - - The number of partitions to use when reading data from a data source. - * - ``queryTimeout`` - - 0 - - The maximum time in seconds for a JDBC query to execute before timing out. - * - ``fetchsize`` - - 0 - - The number of rows to fetch in a single JDBC fetch operation. - * - ``batchsize`` - - 1000000 - - The number of rows to write in a single JDBC batch operation when writing to a database. - * - ``sessionInitStatement`` - - - - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. - * - ``truncate`` - - ``false`` - - A boolean value indicating whether to truncate an existing table before writing data to it. - * - ``cascadeTruncate`` - - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect - - A boolean value indicating whether to recursively truncate child tables when truncating a table. - * - ``createTableOptions`` - - - - Additional options to include when creating a new table in a relational database. - * - ``createTableColumnTypes`` - - - - A map of column names to column data types to use when creating a new table in a relational database. - * - ``customSchema`` - - - - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. - * - ``pushDownPredicate`` - - ``true`` - - A boolean value indicating whether to push down filters to the data source. - * - ``pushDownAggregate`` - - ``false`` - - A boolean value indicating whether to push down aggregations to the data source. - * - ``pushDownLimit`` - - ``false`` - - A boolean value indicating whether to push down limits to the data source. - * - ``pushDownTableSample`` - - ``false`` - - Used to optimize the performance of SQL queries on large tables by pushing down the sampling operation closer to the data source, reducing the amount of data that needs to be processed. - * - ``connectionProvider`` - - - - A fully qualified class name of a custom connection provider to use when connecting to a data source. - * - ``c`` - - ``false`` - - A shorthand for specifying connection properties in the JDBC data source. - -Connecting Spark to SQreamDB ----------------------------- - -DataFrames, as Spark objects, play a crucial role in transferring data between different sources. The SQreamDB-Spark Connector facilitates the seamless integration of DataFrames, allowing the insertion of DataFrames into SQreamDB tables. Furthermore, it enables the export of tables or queries as DataFrames, providing compatibility with Spark for versatile data processing. - -1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: - -.. code-block:: console - - ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} - - - //Example: - - ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar - -2. To create a SQreamDB session, run the following commands in the Spark Shell: - -.. code-block:: console - - import scala.collection.JavaConverters.mapAsJavaMapConverter - val config = Map("spark.master"->"local").asJava - import com.sqream.driver.SqreamSession; - val sqreamSession=SqreamSession.getSession(config) - -Transferring Data -=================== - -Transferring Data From SQreamDB to Spark ------------------------------------------- - -1. Create a mapping of Spark options: - -.. code-block:: console - - val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava - -2. Create a Spark DataFrame: - -.. code-block:: console - - val df=sqreamSession.read(options) - -Transferring Data From Spark to SQreamDB ------------------------------------------- - -1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): - -.. code-block:: console - - val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava - -2. Create a Spark DataFrame: - -.. code-block:: console - - import org.apache.spark.sql.SaveMode - val df=sqreamSession.write(df, options, SaveMode.Overwrite) - -Data Types and Mapping -======================== - -SQreamDB data types mapped to Spark - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - SQreamDB - - Spark - * - ``BIGINT`` - - ``LONGINT`` - * - ``BOOL`` - - ``BooleanType`` - * - ``DATE`` - - ``DateType`` - * - ``DOUBLE`` - - ``DoubleType`` - * - ``REAL`` - - ``FloateType`` - * - ``DECIMAL`` - - ``DeciamlType`` - * - ``INT`` - - ``Integer`` - * - ``SMALLINT`` - - ``ShortType`` - * - ``TINYINT`` - - ``ShortType`` - * - ``DATETIME`` - - ``TimestampType`` - -Spark data types mapped to SQreamDB - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Spark - - SQreamDB - * - ``BooleanType`` - - ``BOOL`` - * - ``ByteType`` - - ``SMALLINT`` - * - ``DateType`` - - ``DATE`` - * - ``DecimalType`` - - ``DECIMAL`` - * - ``DoubleType`` - - ``DOUBLE`` - * - ``FloatType`` - - ``REAL`` - * - ``IntegerType`` - - ``INT`` - * - ``LongType`` - - ``BIGINT`` - * - ``ShortType`` - - ``SMALLINT`` - * - ``StringType`` - - ``TEXT`` - * - ``TimestampType`` - - ``DATETIME`` - - -Example -======== - -JAVA - -.. code-block:: java - - import com.sqream.driver.SqreamSession; - import org.apache.spark.sql.Dataset; - import org.apache.spark.sql.Row; - import org.apache.spark.sql.SaveMode; - - import java.util.HashMap; - - public class main { - public static void main(String[] args) { - HashMap<String, String> config = new HashMap<>(); - //spark configuration - //optional configuration here: https://spark.apache.org/docs/latest/configuration.html - config.put("spark.master", "spark://localhost:7077"); - config.put("spark.dynamicAllocation.enabled", "false"); - - config.put("spark.driver.port", "7077"); - config.put("spark.driver.host", "192.168.0.157"); - config.put("spark.driver.bindAddress", "192.168.0.157"); - - SqreamSession sqreamSession = SqreamSession.getSession(config); - - //spark properties - //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html - HashMap<String, String> props = new HashMap<>(); - - props.put("url", "jdbc:Sqream://192.168.0.157:3108/master;user=sqream;password=1234;cluster=true;"); - - //spark partition// - props.put("dbtable", "public.test_table"); - props.put("partitionColumn","sr_date_sk"); - props.put("numPartitions","2"); - props.put("lowerBound","2450820"); - props.put("upperBound","2452822"); - - - /*Read from sqream table*/ - Dataset<Row> dataFrame = sqreamSession.read(props); - dataFrame.show();/*By default, show() displays only the first 20 rows of the DataFrame. - This can be insufficient when working with large datasets. You can customize the number of rows displayed by passing an argument to show(n).*// - - - /*Add to sqream table*/ - sqreamSession.write(dataFrame, props, SaveMode.Append); - - } - } \ No newline at end of file From 189e3d459d328003a240edf6c629c342b68d7127 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:02:45 +0300 Subject: [PATCH 1383/1892] Create index.rst --- .../client_drivers/spark/index.rst | 274 ++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 connecting_to_sqream/client_drivers/spark/index.rst diff --git a/connecting_to_sqream/client_drivers/spark/index.rst b/connecting_to_sqream/client_drivers/spark/index.rst new file mode 100644 index 000000000..03ef309c3 --- /dev/null +++ b/connecting_to_sqream/client_drivers/spark/index.rst @@ -0,0 +1,274 @@ +.. _spark: + +***** +Spark +***** + +The Spark connector enables reading and writing data to and from SQreamDB and may be used for large-scale data processing. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================= + +To use Spark with SQreamDB, it is essential that you have the following installed: + +* SQreamDB version 2022.1.8 or later +* Spark version 3.3.1 or later +* `SQreamDB Spark Connector 5.0.0 <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ +* :ref:`JDBC<java_jdbc>` version 4.5.6 or later + +Configuration +============= + +The Spark JDBC connection properties empower you to customize your Spark connection. These properties facilitate various aspects, including database access, query execution, and result retrieval. Additionally, they provide options for authentication, encryption, and connection pooling. + +The following Spark connection properties are supported by SQreamDB: + +.. list-table:: + :widths: auto + :header-rows: 1 + + + * - Parameter + - Default + - Description + * - ``url`` + - + - The JDBC URL to connect to the database. + * - ``dbtable`` + - + - The JDBC URL to connect to the database. + * - ``query`` + - + - The SQL query to be executed when using the JDBC data source, instead of specifying a table or view name with the dbtable property. + * - ``driver`` + - + - The fully qualified class name of the JDBC driver to use when connecting to a relational database. + * - ``numPartitions`` + - + - The number of partitions to use when reading data from a data source. + * - ``queryTimeout`` + - 0 + - The maximum time in seconds for a JDBC query to execute before timing out. + * - ``fetchsize`` + - 0 + - The number of rows to fetch in a single JDBC fetch operation. + * - ``batchsize`` + - 1000000 + - The number of rows to write in a single JDBC batch operation when writing to a database. + * - ``sessionInitStatement`` + - + - A SQL statement to be executed once at the beginning of a JDBC session, such as to set session-level properties. + * - ``truncate`` + - ``false`` + - A boolean value indicating whether to truncate an existing table before writing data to it. + * - ``cascadeTruncate`` + - the default cascading truncate behaviour of the JDBC database in question, specified in the ``isCascadeTruncate`` in each JDBCDialect + - A boolean value indicating whether to recursively truncate child tables when truncating a table. + * - ``createTableOptions`` + - + - Additional options to include when creating a new table in a relational database. + * - ``createTableColumnTypes`` + - + - A map of column names to column data types to use when creating a new table in a relational database. + * - ``customSchema`` + - + - A custom schema to use when reading data from a file format that does not support schema inference, such as CSV or JSON. + * - ``pushDownPredicate`` + - ``true`` + - A boolean value indicating whether to push down filters to the data source. + * - ``pushDownAggregate`` + - ``false`` + - A boolean value indicating whether to push down aggregations to the data source. + * - ``pushDownLimit`` + - ``false`` + - A boolean value indicating whether to push down limits to the data source. + * - ``pushDownTableSample`` + - ``false`` + - Used to optimize the performance of SQL queries on large tables by pushing down the sampling operation closer to the data source, reducing the amount of data that needs to be processed. + * - ``connectionProvider`` + - + - A fully qualified class name of a custom connection provider to use when connecting to a data source. + * - ``c`` + - ``false`` + - A shorthand for specifying connection properties in the JDBC data source. + +Connecting Spark to SQreamDB +---------------------------- + +DataFrames, as Spark objects, play a crucial role in transferring data between different sources. The SQreamDB-Spark Connector facilitates the seamless integration of DataFrames, allowing the insertion of DataFrames into SQreamDB tables. Furthermore, it enables the export of tables or queries as DataFrames, providing compatibility with Spark for versatile data processing. + +1. To open the Spark Shell, run the following command under the ``Spark/bin`` directory: + +.. code-block:: console + + ./spark-shell --driver-class-path {driver path} --jars {Spark-Sqream-Connector.jar path} + + + //Example: + + ./spark-shell --driver-class-path /home/sqream/sqream-jdbc-4.5.6.jar --jars Spark-Sqream-Connector-1.0.jar + +2. To create a SQreamDB session, run the following commands in the Spark Shell: + +.. code-block:: console + + import scala.collection.JavaConverters.mapAsJavaMapConverter + val config = Map("spark.master"->"local").asJava + import com.sqream.driver.SqreamSession; + val sqreamSession=SqreamSession.getSession(config) + +Transferring Data +=================== + +Transferring Data From SQreamDB to Spark +------------------------------------------ + +1. Create a mapping of Spark options: + +.. code-block:: console + + val options = Map("query"->"select * from <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava + +2. Create a Spark DataFrame: + +.. code-block:: console + + val df=sqreamSession.read(options) + +Transferring Data From Spark to SQreamDB +------------------------------------------ + +1. Create a mapping of Spark options, using the ``dbtable`` Spark option (``query`` is not allowed for writing): + +.. code-block:: console + + val options = Map("dbtable"-> <table_name>", "url"->"jdbc:<jdbc_path>/master;user=<username>;password=<password>;cluster=false").asJava + +2. Create a Spark DataFrame: + +.. code-block:: console + + import org.apache.spark.sql.SaveMode + val df=sqreamSession.write(df, options, SaveMode.Overwrite) + +Data Types and Mapping +======================== + +SQreamDB data types mapped to Spark + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SQreamDB + - Spark + * - ``BIGINT`` + - ``LONGINT`` + * - ``BOOL`` + - ``BooleanType`` + * - ``DATE`` + - ``DateType`` + * - ``DOUBLE`` + - ``DoubleType`` + * - ``REAL`` + - ``FloateType`` + * - ``DECIMAL`` + - ``DeciamlType`` + * - ``INT`` + - ``Integer`` + * - ``SMALLINT`` + - ``ShortType`` + * - ``TINYINT`` + - ``ShortType`` + * - ``DATETIME`` + - ``TimestampType`` + +Spark data types mapped to SQreamDB + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Spark + - SQreamDB + * - ``BooleanType`` + - ``BOOL`` + * - ``ByteType`` + - ``SMALLINT`` + * - ``DateType`` + - ``DATE`` + * - ``DecimalType`` + - ``DECIMAL`` + * - ``DoubleType`` + - ``DOUBLE`` + * - ``FloatType`` + - ``REAL`` + * - ``IntegerType`` + - ``INT`` + * - ``LongType`` + - ``BIGINT`` + * - ``ShortType`` + - ``SMALLINT`` + * - ``StringType`` + - ``TEXT`` + * - ``TimestampType`` + - ``DATETIME`` + + +Example +======== + +JAVA + +.. code-block:: java + + import com.sqream.driver.SqreamSession; + import org.apache.spark.sql.Dataset; + import org.apache.spark.sql.Row; + import org.apache.spark.sql.SaveMode; + + import java.util.HashMap; + + public class main { + public static void main(String[] args) { + HashMap<String, String> config = new HashMap<>(); + //spark configuration + //optional configuration here: https://spark.apache.org/docs/latest/configuration.html + config.put("spark.master", "spark://localhost:7077"); + config.put("spark.dynamicAllocation.enabled", "false"); + + config.put("spark.driver.port", "7077"); + config.put("spark.driver.host", "192.168.0.157"); + config.put("spark.driver.bindAddress", "192.168.0.157"); + + SqreamSession sqreamSession = SqreamSession.getSession(config); + + //spark properties + //optional properties here: https://spark.apache.org/docs/latest/sql-data-sources-jdbc.html + HashMap<String, String> props = new HashMap<>(); + + props.put("url", "jdbc:Sqream://192.168.0.157:3108/master;user=sqream;password=1234;cluster=true;"); + + //spark partition// + props.put("dbtable", "public.test_table"); + props.put("partitionColumn","sr_date_sk"); + props.put("numPartitions","2"); + props.put("lowerBound","2450820"); + props.put("upperBound","2452822"); + + + /*Read from sqream table*/ + Dataset<Row> dataFrame = sqreamSession.read(props); + dataFrame.show();/*By default, show() displays only the first 20 rows of the DataFrame. + This can be insufficient when working with large datasets. You can customize the number of rows displayed by passing an argument to show(n).*// + + + /*Add to sqream table*/ + sqreamSession.write(dataFrame, props, SaveMode.Append); + + } + } \ No newline at end of file From 7d35a3b46993b7a0c9eace823313879680e0fd95 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:06:59 +0300 Subject: [PATCH 1384/1892] Update index.rst --- connecting_to_sqream/client_platforms/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 5ff6a0582..37451c115 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -67,7 +67,7 @@ Data Analysis and Programming Languages tableau talend tibco_spotfire - trino + From 66b6a437d418931495c880bffd2eff418c6e9c57 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:17:33 +0300 Subject: [PATCH 1385/1892] Maintenance --- releases/4.0.rst | 20 ++++++++--------- ...ing_and_managing_roles_and_permissions.rst | 22 +++++++++---------- sqream_studio/viewing_logs.rst | 20 +++++++++++------ 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/releases/4.0.rst b/releases/4.0.rst index a8354496b..1c499e9ea 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -42,10 +42,11 @@ SQream Studio Updates and Improvements Known Issues ------------ + :ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 4.0 resolved Issues ------------------------------ +---------------------------- +-----------------+---------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -77,14 +78,17 @@ Version 4.0 resolved Issues Configuration Changes --------------------- + No configuration changes were made. Naming Changes -------------- + No relevant naming changes were made. Deprecated Features ------------------- + SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). @@ -93,11 +97,13 @@ TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR End of Support ---------------- +-------------- + No End of Support changes were made. Upgrading to version 4.0 -------------------- +------------------------ + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -110,20 +116,12 @@ Upgrading to version 4.0 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst b/sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst index 6f0e43ef3..8a0fdc006 100644 --- a/sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst +++ b/sqream_studio/creating_assigning_and_managing_roles_and_permissions.rst @@ -2,10 +2,9 @@ .. _roles_5.4.7: -**************************** +******************************************************* Creating, Assigning, and Managing Roles and Permissions -**************************** - +******************************************************* In the **Roles** area you can create and assign roles and manage user permissions. @@ -30,16 +29,13 @@ The **Type** column displays one of the following assigned role types: Viewing Information About a Role --------------------- +-------------------------------- + Clicking a role in the roles table displays the following information: * **Parent Roles** - displays the parent roles of the selected role. Roles inherit all roles assigned to the parent. - - :: * **Members** - displays all members that the role has been assigned to. The arrow indicates the roles that the role has inherited. Hovering over a member displays the roles that the role is inherited from. - - :: * **Permissions** - displays the role's permissions. The arrow indicates the permissions that the role has inherited. Hovering over a permission displays the roles that the permission is inherited from. @@ -47,9 +43,9 @@ Clicking a role in the roles table displays the following information: Creating a New Role --------------------- -You can create a new role by clicking **New Role**. +------------------- +You can create a new role by clicking **New Role**. An admin creates a **user** by granting login permissions and a password to a role. Each role is defined by a set of permissions. An admin can also group several roles together to form a **group** to manage them simultaneously. For example, permissions can be granted to or revoked on a group level. @@ -70,7 +66,8 @@ When adding a new role, you must select the **Enable login for this role** and * :ref:`Back to Creating, Assigning, and Managing Roles and Permissions<roles_5.4.7>` Editing a Role --------------------- +-------------- + Once you've created a role, clicking the **Edit Role** button lets you do the following: * Edit role name @@ -86,7 +83,8 @@ From the Edit Role panel you view directly and indirectly (or inherited) granted :ref:`Back to Creating, Assigning, and Managing Roles and Permissions<roles_5.4.7>` Deleting a Role ------------------ +--------------- + Clicking the **delete** icon displays a confirmation message with the amount of users and groups that will be impacted by deleting the role. :ref:`Back to Creating, Assigning, and Managing Roles and Permissions<roles_5.4.7>` \ No newline at end of file diff --git a/sqream_studio/viewing_logs.rst b/sqream_studio/viewing_logs.rst index c4e4b73a3..8ca1a6186 100644 --- a/sqream_studio/viewing_logs.rst +++ b/sqream_studio/viewing_logs.rst @@ -2,9 +2,10 @@ .. _logs_top_5.4.7: -**************************** +************ Viewing Logs -**************************** +************ + The **Logs** screen is used for viewing logs and includes the following elements: .. list-table:: @@ -28,7 +29,8 @@ The **Logs** screen is used for viewing logs and includes the following elements .. _filter_5.4.7: Filtering Table Data -------------- +-------------------- + From the Logs tab, from the **FILTERS** area you can also apply the **TIMESPAN**, **ONLY ERRORS**, and additional filters (**Add**). The **Timespan** filter lets you select a timespan. The **Only Errors** toggle button lets you show all queries, or only queries that generated errors. The **Add** button lets you add additional filters to the data shown in the table. The **Filter** button applies the selected filter(s). Other filters require you to select an item from a dropdown menu: @@ -47,7 +49,8 @@ You can also export a record of all of your currently filtered logs in Excel for Viewing Query Logs ----------- +------------------ + The **QUERIES** log area shows basic query information, such as query number and the time the query was run. The number next to the title indicates the amount of queries that have been run. From the Queries area you can see and sort by the following: @@ -67,7 +70,8 @@ In the Queries table, you can click on the **Statement ID** and **Query** items .. _sessions_5.4.7: Viewing Session Logs ----------- +-------------------- + The **SESSIONS** tab shows the sessions log table and is used for viewing activity that has occurred during your sessions. The number at the top indicates the amount of sessions that have occurred. From here you can see and sort by the following: @@ -87,7 +91,8 @@ In the Sessions table, you can click on the **Timestamp**, **Connection ID**, an .. _system_5.4.7: Viewing System Logs ----------- +------------------- + The **SYSTEM** tab shows the system log table and is used for viewing all system logs. The number at the top indicates the amount of sessions that have occurred. Because system logs occur less frequently than queries and sessions, you may need to increase the filter timespan for the table to display any system logs. From here you can see and sort by the following: @@ -103,7 +108,8 @@ In the Systems table, you can click on the **Timestamp** and **Log type** items .. _log_lines_5.4.7: Viewing All Log Lines ----------- +--------------------- + The **LOG LINES** tab is used for viewing the total amount of log lines in a table. From here users can view a more granular breakdown of log information collected by Studio. The other tabs (QUERIES, SESSIONS, and SYSTEM) show a filtered form of the raw log lines. For example, the QUERIES tab shows an aggregation of several log lines. From here you can see and sort by the following: From a2fb798038fa1254739321aab6de91d7b91ed091 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:34:53 +0300 Subject: [PATCH 1386/1892] Update 4.0.rst --- releases/4.0.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/releases/4.0.rst b/releases/4.0.rst index 1c499e9ea..75467d013 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -17,13 +17,9 @@ New Features * Re-enabling an enhanced version of the :ref:`License Storage Capacity<monitoring_workers_and_services_from_the_dashboard>` feature - :: - * :ref:`Lightweight Directory Access Protocol(LDAP)<ldap>` may be used to authenticate SQream roles - :: - - * :ref:`Physical deletion performance enhancement<delete>` by supporting file systems with parallelism capabilities + * :ref:`Physical deletion performance enhancement<delete_guide>` by supporting file systems with parallelism capabilities Storage Version --------------- From 247a85f773e6822d2a5afc2493fd948063ca99fa Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:36:40 +0300 Subject: [PATCH 1387/1892] Update 4.0.rst --- releases/4.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.0.rst b/releases/4.0.rst index 75467d013..44ed49163 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -26,7 +26,7 @@ Storage Version The storage version presently in effect is version 45. - + SQream Studio Updates and Improvements -------------------------------------- From 91c6db05dd6f0a1df74aec35363718757e48710d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:54:56 +0300 Subject: [PATCH 1388/1892] Maintenance --- .../client_drivers/dataiku/index.rst | 1 + .../client_platforms/microstrategy.rst | 37 ------------- .../client_platforms/sas_viya.rst | 44 ++++----------- .../client_platforms/talend.rst | 22 -------- .../client_platforms/tibco_spotfire.rst | 53 ------------------- data_ingestion/ingesting_from_databases.rst | 10 ++-- 6 files changed, 15 insertions(+), 152 deletions(-) diff --git a/connecting_to_sqream/client_drivers/dataiku/index.rst b/connecting_to_sqream/client_drivers/dataiku/index.rst index 72b6fd8d8..a04ef9d31 100644 --- a/connecting_to_sqream/client_drivers/dataiku/index.rst +++ b/connecting_to_sqream/client_drivers/dataiku/index.rst @@ -49,6 +49,7 @@ In your Dataiku web interface: #. Assign a name for the output dataset stored in your SQreamDB connection. #. Provide AWS Access Key and Secret Key by either: + a. Filling in the values in the Plugin form b. Set the Project Variables or set the Global Variables when DSS Variables are used diff --git a/connecting_to_sqream/client_platforms/microstrategy.rst b/connecting_to_sqream/client_platforms/microstrategy.rst index 6c0aca4e6..87f688a7b 100644 --- a/connecting_to_sqream/client_platforms/microstrategy.rst +++ b/connecting_to_sqream/client_platforms/microstrategy.rst @@ -1,6 +1,5 @@ .. _micro_strategy: - ************* MicroStrategy ************* @@ -49,62 +48,38 @@ Connecting a Data Source ======================== 1. Activate the **MicroStrategy Desktop** app. The app displays the Dossiers panel to the right. - - :: 2. Download the most current version of the `SQream JDBC driver <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/index.html>`_. - :: - 3. Click **Dossiers** and **New Dossier**. The **Untitled Dossier** panel is displayed. - - :: 4. Click **New Data**. - - :: 5. From the **Data Sources** panel, select **Databases** to access data from tables. The **Select Import Options** panel is displayed. - - :: 6. Select one of the following: * Build a Query * Type a Query * Select Tables - - :: 7. Click **Next**. - - :: 8. In the Data Source panel, do the following: 1. From the **Database** dropdown menu, select **Generic**. The **Host Name**, **Port Number**, and **Database Name** fields are removed from the panel. - - :: 2. In the **Version** dropdown menu, verify that **Generic DBMS** is selected. - - :: 3. Click **Show Connection String**. - - :: 4. Select the **Edit connection string** checkbox. - - :: 5. From the **Driver** dropdown menu, select a driver for one of the following connectors: * **JDBC** - The SQream driver is not integrated with MicroStrategy and does not appear in the dropdown menu. However, to proceed, you must select an item, and in the next step you must specify the path to the SQream driver that you installed on your machine. * **ODBC** - SQreamDB ODBC - :: - 6. In the **Connection String** text box, type the relevant connection string and path to the JDBC jar file using the following syntax: .. code-block:: console @@ -126,32 +101,20 @@ Connecting a Data Source For more information about the available **connection parameters** and other examples, see :ref:`Connection Parameters <java_jdbc>`. 7. In the **User** and **Password** fields, fill out your user name and password. - - :: 8. In the **Data Source Name** field, type **SQreamDB**. - - :: 9. Click **Save**. The SQreamDB that you picked in the Data Source panel is displayed. 9. In the **Namespace** menu, select a namespace. The tables files are displayed. - :: - 10. Drag and drop the tables into the panel on the right in your required order. - :: - 11. **Recommended** - Click **Prepare Data** to customize your data for analysis. - :: - 12. Click **Finish**. - :: - 13. From the **Data Access Mode** dialog box, select one of the following: diff --git a/connecting_to_sqream/client_platforms/sas_viya.rst b/connecting_to_sqream/client_platforms/sas_viya.rst index 310aa9a3c..7fc3cd912 100644 --- a/connecting_to_sqream/client_platforms/sas_viya.rst +++ b/connecting_to_sqream/client_platforms/sas_viya.rst @@ -23,7 +23,7 @@ Integrating with SQreamDB has been tested with SAS Viya v.03.05 and newer. To download SAS Viya, see `SAS Viya <https://www.sas.com/en_us/software/viya.html>`_. Installing the JDBC Driver ----------------------------- +-------------------------- The SQreamDB JDBC driver is required for establishing a connection between SAS Viya and SQreamDB. @@ -38,7 +38,7 @@ The SQreamDB JDBC driver is required for establishing a connection between SAS V SQreamDB recommends creating the directory ``/opt/sqream`` on the SAS Viya server. Configuring SAS Viya -====================== +==================== After installing the JDBC driver, you must configure the JDBC driver from the SAS Studio so that it can be used with SQreamDB BStudio. @@ -46,11 +46,7 @@ After installing the JDBC driver, you must configure the JDBC driver from the SA #. Sign in to the SAS Studio. - :: - #. From the **New** menu, click **SAS Program**. - - :: #. Configure the SQreamDB JDBC connector by adding the following rows: @@ -58,12 +54,12 @@ After installing the JDBC driver, you must configure the JDBC driver from the SA :language: php Operating SAS Viya -=================== +================== The **Operating SAS Viya** section describes the following: Using SAS Viya Visual Analytics ------------------------------------ +------------------------------- This section describes how to use SAS Viya Visual Analytics. @@ -71,36 +67,20 @@ This section describes how to use SAS Viya Visual Analytics. #. Log in to SAS Viya Visual Analytics using your credentials: - :: - 2. Click **New Report**. - :: - 3. Click **Data**. - :: - 4. Click **Data Sources**. - :: - 5. Click the **Connect** icon. - :: - 6. From the **Type** menu, select **Database**. - :: - 7. Provide the required information and select **Persist this connection beyond the current session**. - :: - 8. Click **Advanced** and provide the required information. - :: - 9. Add the following additional parameters by clicking **Add Parameters**: .. list-table:: @@ -122,20 +102,18 @@ This section describes how to use SAS Viya Visual Analytics. 10. Click **Test Connection**. - :: - 11. If the connection is successful, click **Save**. .. _troubleshooting_sas_viya: Troubleshooting SAS Viya -========================== +======================== The **Best Practices and Troubleshooting** section describes the following best practices and troubleshooting procedures when connecting to SQreamDB using SAS Viya: Inserting Only Required Data -------------------------------- +---------------------------- When using SAS Viya, SQreamDB recommends using only data that you need, as described below: @@ -146,12 +124,12 @@ When using SAS Viya, SQreamDB recommends using only data that you need, as descr * To increase query performance, add filters before analyzing. Every modification you make while analyzing data queries the SQreamDB database, sometimes several times. Adding filters to the datasource before exploring limits the amount of data analyzed and increases query performance. Creating a Separate Service for SAS Viya ------------------------------------------- +---------------------------------------- SQreamDB recommends creating a separate service for SAS Viya with the DWLM. This reduces the impact that Tableau has on other applications and processes, such as ETL. In addition, this works in conjunction with the load balancer to ensure good performance. Locating the SQreamDB JDBC Driver ----------------------------------- +--------------------------------- In some cases, SAS Viya cannot locate the SQreamDB JDBC driver, generating the following error message: @@ -163,17 +141,13 @@ In some cases, SAS Viya cannot locate the SQreamDB JDBC driver, generating the f 1. Verify that you have placed the JDBC driver in a directory that SAS Viya can access. - :: - 2. Verify that the classpath in your SAS program is correct, and that SAS Viya can access the file that it references. - :: - 3. Restart SAS Viya. For more troubleshooting assistance, see the `SQreamDB Support Portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Supporting TEXT ------------------ +--------------- In SAS Viya versions lower than 4.0, casting ``TEXT`` to ``CHAR`` changes the size to 1,024, such as when creating a table including a ``TEXT`` column. This is resolved by casting ``TEXT`` into ``CHAR`` when using the JDBC driver. \ No newline at end of file diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index cdfeed1ea..c37350ee6 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -21,29 +21,19 @@ Creating a New Metadata JDBC DB Connection **To create a new metadata JDBC DB connection:** 1. In the **Repository** panel, nagivate to **Metadata** and right-click **Db connections**. - - :: 2. Select **Create connection**. - - :: 3. In the **Name** field, type a name. - :: - Note that the name cannot contain spaces. 4. In the **Purpose** field, type a purpose and click **Next**. Note that you cannot continue to the next step until you define both a Name and a Purpose. - :: - 5. In the **DB Type** field, select **JDBC**. - :: - 6. In the **JDBC URL** field, type the relevant connection string. For connection string examples, see `Connection Strings <https://docs.sqream.com/en/v2022.1/connecting_to_sqream/client_drivers/jdbc/index.html#connection-string-examples>`_. @@ -58,28 +48,20 @@ Creating a New Metadata JDBC DB Connection 9. From the Module window, select **Artifact repository(local m2/nexus)** and select **Install a new module**. - :: - 10. Click the ellipsis. Your hard drive is displayed. 11. Navigate to a **JDBC jar file** (such as **sqream-jdbc-4.5.3.jar**)and click **Open**. - :: - 12. Click **Detect the module install status**. - :: - 13. Click **OK**. The JDBC that you selected is displayed in the **Driver** field. 14. Click **Select class name**. - :: - 15. Click **Test connection**. If a driver class is not found (for example, you didn't select a JDBC jar file), the following error message is displayed: @@ -87,12 +69,8 @@ Creating a New Metadata JDBC DB Connection After creating a new metadata JDBC DB connection, you can do the following: * Use your new metadata connection. - - :: * Drag it to the **job** screen. - - :: * Build Talend components. diff --git a/connecting_to_sqream/client_platforms/tibco_spotfire.rst b/connecting_to_sqream/client_platforms/tibco_spotfire.rst index 2420da40a..e4d1eec3a 100644 --- a/connecting_to_sqream/client_platforms/tibco_spotfire.rst +++ b/connecting_to_sqream/client_platforms/tibco_spotfire.rst @@ -50,8 +50,6 @@ Creating an ODBC Connection #. Launch the TIBCO Spotfire application. - :: - #. From the **File** menu click **Add Data Tables**. The **Add Database Tables** window is displayed. @@ -66,20 +64,14 @@ Creating an ODBC Connection #. Select **System or user data source** and from the drop-down menu select the DSN of your data source (SQreamDB). - :: - #. Provide your database username and password and click **OK**. - :: - #. In the **Open Database** window, click **OK**. The **Specify Tables and Columns** window is displayed. #. In the **Specify Tables and Columns** window, select the checkboxes corresponding to the tables and columns that you want to include in your SQL statement. - :: - #. In the **Data source name** field, set your data source name and click **OK**. Your data source is displayed in the **Data tables** area. @@ -108,13 +100,9 @@ After creating a connection, you can create your SQream data source template. * Override an existing template: 1. In the template text field, select an existing template. - - :: 2. Copy and paste your data source template text. - :: - * Create a new template: 1. Click **New**. @@ -124,8 +112,6 @@ After creating a connection, you can create your SQream data source template. .. _creating_sqream_data_source_template: 2. In the **Name** field, define your template name. - - :: 3. In the **Data Source Template** text field, copy and paste your data source template text. @@ -183,8 +169,6 @@ After creating a connection, you can create your SQream data source template. </jdbc-type-settings> 4. Click **Save configuration**. - - :: 5. Close and restart your Spotfire server. @@ -197,37 +181,23 @@ After creating the SQream data source template, you can create a data source. 1. Launch the TIBCO Spotfire application. - :: - #. From the **Tools** menu, select **Information Designer**. The **Information Designer** window is displayed. - - :: #. From the **New** menu, click **Data Source**. The **Data Source** tab is displayed. - - :: #. Provide the following information: * **Name** - define a unique name. - - :: * **Type** - use the same type template name you used while configuring your template. See **Step 3** in :ref:`Creating the SQream Data Source Template<creating_sqream_data_source_template>`. - - :: * **Connection URL** - use the standard JDBC connection string, ``<ip>:<port>/database``. - - :: * **No. of connections** - define a number between **1** and **100**. SQream recommends setting your number of connections to **100**. - - :: * **Username and Password** - define your SQream username and password. @@ -242,8 +212,6 @@ After creating a data source, you can create an information link. The **Information Designer** window is displayed. - :: - #. From the **New** menu, click **Information Link**. The **Information link** tab is displayed. @@ -255,8 +223,6 @@ After creating a data source, you can create an information link. Note the following: * You can select procedures from the Elements region. - - :: * You can remove an element by selecting an element and clicking **Remove**. @@ -266,13 +232,9 @@ After creating a data source, you can create an information link. 5. *Optional* - In the **Description** region, type the description of the information link. - :: - #. *Optional* - To filter your data, expand the **Filters** section and do the following: 1. From the **Information Link** region, select the element you added in Step 3 above. - - :: 2. Click **Add**. @@ -283,8 +245,6 @@ After creating a data source, you can create an information link. The selected column is added to the Filters list. 4. Repeat steps 2 and 3 to add filters to additional columns. - - :: 5. For each column, from the **Filter Type** drop-down list, select **range** or **values**. @@ -309,8 +269,6 @@ After creating a data source, you can create an information link. The selected column is added to the Prompts list. #. Repeat **Step 1** to add prompts to additional columns. - - :: #. Do the following for each column: @@ -330,29 +288,18 @@ After creating a data source, you can create an information link. 9. *Optional* - Expand the **Parameters** section and define your parameters. - :: - 10. *Optional* - Expand the **Properties** section and define your properties. - :: - 11. *Optional* - Expand the **Caching** section and enable or disable whether your information link can be cached. - :: - 12. Click **Save**. The **Save As** window is displayed. 13. In the tree, select where you want to save the information link. - :: - 14. In the **Name** field, type a name and description for the information link. - :: - - 15. Click **Save**. The new information link is added to the library and can be accessed by other users. diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index cb24cbf42..653043277 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -22,7 +22,7 @@ It is essential that you have the following: * SQLoader.jar file Minimum Hardware Requirements ------------------------------- +----------------------------- .. list-table:: :widths: auto @@ -38,14 +38,14 @@ Minimum Hardware Requirements .. _sqloader_thread_sizing_guidelines: Sizing Guidelines ------------------- +----------------- The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. --------------------------------- Installation and Connection -============================ +=========================== Getting the SQLoader Configuration and JAR Files ------------------------------------------------ @@ -107,8 +107,8 @@ The ``sqload-jdbc.properties`` file contains a connection string that must be co * - ``ssl`` - Specifies SSL for this connection -.. literalinclude:: connection_string.java - :language: java +.. literalinclude:: connection_string.ini + :language: ini :caption: Properties File Sample :linenos: From c24c2cbc42c60c3ce7f3d6aa1c376deb31a6f650 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 08:59:17 +0300 Subject: [PATCH 1389/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index bc0f0d1de..98ffd0a3c 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -364,7 +364,7 @@ SQLoader Service Interface ========================== Supported HTTP Requests -^^^^^^^^^^^^^^^^^^^^^^^ +----------------------- .. list-table:: :widths: auto From a6fe3a238fd387696f7071feb3dec829be16ca5f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:01:39 +0300 Subject: [PATCH 1390/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 0fb9ab93e..60fb7262a 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -730,7 +730,7 @@ After configuring your operating system, you must install the NVIDIA CUDA driver .. warning:: If your Linux GUI runs on the server, it must be stopped before installing the CUDA drivers. Before You Begin -^^^^^^^^^^^^^^^^^ +---------------- 1. Verify that the NVIDIA card has been installed and is detected by the system: @@ -751,7 +751,7 @@ Before You Begin sudo yum install -y gcc Updating the Kernel Headers -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +--------------------------- 1. Update the kernel headers on RHEL or CentOS: @@ -768,7 +768,7 @@ Updating the Kernel Headers rpm -qa |grep kernel-headers-$(uname -r) Disabling Nouveau -^^^^^^^^^^^^^^^^^^^ +----------------- Disable Nouveau, which is the default operating system driver. @@ -804,7 +804,7 @@ Disable Nouveau, which is the default operating system driver. sudo reboot Installing the CUDA Driver ----------------------------- +-------------------------- .. contents:: :local: @@ -898,7 +898,7 @@ Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. Tuning Up NVIDIA Performance -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The following procedures exclusively relate to Intel. @@ -909,7 +909,7 @@ The following procedures exclusively relate to Intel. .. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. Tune Up NVIDIA Performance when Driver Installed from the Repository -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1. Check the service status: @@ -952,7 +952,7 @@ Tune Up NVIDIA Performance when Driver Installed from the Repository Tune Up NVIDIA Performance when Driver Installed from the Runfile -"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" 1. Change the permissions on the ``rc.local`` file to ``executable``: @@ -1000,7 +1000,7 @@ Tune Up NVIDIA Performance when Driver Installed from the Runfile Enabling Core Dumps -==================== +=================== While this procedure is optional, SQreamDB recommends that core dumps be enabled. Note that the default ``abrt`` format is not ``gdb`` compatible, and that for SQreamDB support to be able to analyze your core dumps, they must be ``gdb`` compatible. @@ -1009,7 +1009,7 @@ While this procedure is optional, SQreamDB recommends that core dumps be enabled :depth: 1 Checking the ``abrtd`` Status ----------------------------- +----------------------------- 1. Check if ``abrtd`` is running: @@ -1024,7 +1024,7 @@ Checking the ``abrtd`` Status for i in abrt-ccpp.service abrtd.service abrt-oops.service abrt-pstoreoops.service abrt-vmcore.service abrt-xorg.service ; do sudo systemctl disable $i; sudo systemctl stop $i; done Setting the Limits --------------------- +------------------ 1. Set the limits: @@ -1042,7 +1042,7 @@ Setting the Limits 3. To apply the limit changes, log out and log back in. Creating the Core Dump Directory ------------------------------------ +-------------------------------- Because the core dump file may be the size of total RAM on the server, verify that you have sufficient disk space. In the example above, the core dump is configured to the ``/tmp/core_dumps`` directory. If necessary, replace path according to your own environment and disk space. @@ -1101,7 +1101,7 @@ Setting the Output Directory on the ``/etc/sysctl.conf`` File /tmp/core_dumps/core-%e-%s-%u-%g-%p-%t Verifying that the Core Dumps Work ---------------------------------------------------- +---------------------------------- You can verify that the core dumps work only after installing and running SQreamDB. This causes the server to crash and a new ``core.xxx`` file to be included in the folder that is written in ``/etc/sysctl.conf``. From 25f23ccdf5d6cd64c272767607c53dcc43449a5a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 20 Jun 2024 11:18:47 +0300 Subject: [PATCH 1391/1892] Maintenance --- reference/cli/multi_platform_cli.rst | 2 +- reference/cli/server_picker.rst | 2 +- reference/cli/sqream_sql.rst | 6 +++--- reference/sql/sql_syntax/literals.rst | 2 +- releases/2022.1.1.rst | 7 ++----- releases/2022.1.2.rst | 7 ++----- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/reference/cli/multi_platform_cli.rst b/reference/cli/multi_platform_cli.rst index 09dde7d4f..702c9fad4 100644 --- a/reference/cli/multi_platform_cli.rst +++ b/reference/cli/multi_platform_cli.rst @@ -411,7 +411,7 @@ Basic Commands -------------- .. list-table:: - :widths: 20 30 50 + :widths: auto :header-rows: 1 * - Command diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index ecbeffe1c..47688a2ae 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -45,7 +45,7 @@ Parameters - Used to display a help message or documentation for a particular program or command * - ``--log_path`` - ``./server_picker_logs`` - - Configures the default location for the log file + - Configures the default location for the log file Example --------- diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index b514d0051..cddedcb08 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -245,7 +245,7 @@ Executing SQL Statements from the Command Line 1 row time: 0.095941s -.. _controlling_output: + Controlling the Client Output ----------------------------- @@ -390,7 +390,7 @@ Command Line Arguments .. tip:: Run ``$ sqream sql --help`` to see a full list of arguments -.. _supported_record_delimiters: + Supported Record Delimiters ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -431,7 +431,7 @@ Basic Commands -------------- .. list-table:: - :widths: 20 30 50 + :widths: auto :header-rows: 1 * - Command diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index dce24684a..8891c303a 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -55,7 +55,7 @@ Examples .. note:: The actual data type of the value changes based on context, the format used, and the value itself. For example, any number containing the decimal point will be considered ``FLOAT`` by default. - Any whole number will considered ``INT``, unless the value is larger than the :ref:`maximum value<data_types>`, in which case the type will become a ``BIGINT``. + Any whole number will considered ``INT``, unless the value is larger than the :ref:`maximum value<data_type_guides>`, in which case the type will become a ``BIGINT``. .. note:: A numeric literal that contains neither a decimal point nor an exponent is considered ``INT`` by default if its value fits in type ``INT`` (32 bits). If not, it is considered ``BIGINT`` by default if its value fits in type ``BIGINT`` (64 bits). If neither are true, it is considered ``FLOAT``. Literals that contain decimal points and/or exponents are always considered ``FLOAT``. diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst index 662b38ed7..2690139bf 100644 --- a/releases/2022.1.1.rst +++ b/releases/2022.1.1.rst @@ -33,7 +33,8 @@ The 2022.1.1 Release Notes include the following new features: :depth: 1 Password Security Compliance -************ +**************************** + In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. For more information, see :ref:`Password Policy <access_control_password_policy>`. @@ -95,19 +96,15 @@ Upgrading to v2022.1.1 2. Shut down all SQream services. - :: 3. Extract the recently created back-up file. - :: 4. Replace your current metadata with the metadata you stored in the back-up file. - :: 5. Navigate to the new SQream package bin folder. - :: 6. Run the following command: diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 529d35248..8b65a56e2 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -36,7 +36,8 @@ The 2022.1.2 Release Notes include the following new features: :depth: 1 Parquet Read Optimization -************ +************************* + Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. Resolved Issues @@ -87,19 +88,15 @@ Upgrading to v2022.1.2 2. Shut down all SQream services. - :: 3. Extract the recently created back-up file. - :: 4. Replace your current metadata with the metadata you stored in the back-up file. - :: 5. Navigate to the new SQream package bin folder. - :: 6. Run the following command: From e42a048eb7b935a2bea287d490c73b3c4bfaa8a2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:37:37 +0300 Subject: [PATCH 1392/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index ca799223d..5ec0c3022 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. + ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. ► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning cloud storage but also helps conserve storage space. diff --git a/releases/4.7.rst b/releases/4.7.rst index b2b5f518f..3adf166ac 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,7 +35,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. + ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` From 4efc3cdbefff73b3d8f364bdfb3e03f0b4309e2b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:44:03 +0300 Subject: [PATCH 1393/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 5ec0c3022..3e1c6120c 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. + ► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. diff --git a/releases/4.7.rst b/releases/4.7.rst index 3adf166ac..6fb4c74d2 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -43,7 +43,7 @@ New Features and Enhancements ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. -► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. + ► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: From 48e4fd468099cba33644ad018a8a9651898f127f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:51:08 +0300 Subject: [PATCH 1394/1892] 4.6 RN --- releases/4.6.rst | 5 +++++ releases/4.7.rst | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 3e1c6120c..7c67d01b2 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,11 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: + +* :ref:`is_table_exists` +* :ref:`is_view_exists` + ► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. ► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. diff --git a/releases/4.7.rst b/releases/4.7.rst index 6fb4c74d2..9a92463c6 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -45,10 +45,7 @@ New Features and Enhancements -► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: -* :ref:`is_table_exists` -* :ref:`is_view_exists` ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. From bb86c5f5e2bcab7b327123b6c82da6802eefaa08 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 08:55:47 +0300 Subject: [PATCH 1395/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 7c67d01b2..505c566bd 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + ► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: * :ref:`is_table_exists` diff --git a/releases/4.7.rst b/releases/4.7.rst index 9a92463c6..43f62aa4d 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -39,7 +39,7 @@ New Features and Enhancements ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` -► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. From 216c9a3395471779b869c9471de28db172951d55 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:02:43 +0300 Subject: [PATCH 1396/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 505c566bd..2696d936d 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` + ► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. ► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: diff --git a/releases/4.7.rst b/releases/4.7.rst index 43f62aa4d..a57fb0c4a 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -37,7 +37,7 @@ New Features and Enhancements -► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` + From 6a09ff0cac3f4c02141e2ec32cd1f9f8fc493480 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:06:31 +0300 Subject: [PATCH 1397/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 2696d936d..db6702063 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. + ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` ► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. diff --git a/releases/4.7.rst b/releases/4.7.rst index a57fb0c4a..3a4e3964e 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -47,7 +47,7 @@ New Features and Enhancements -► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. + ► Multi-platform CLI From fd12e0d89f894898ea07722325522fca980468a4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:10:34 +0300 Subject: [PATCH 1398/1892] Update 4.7.rst --- releases/4.7.rst | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 3a4e3964e..509e3a724 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,20 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- - - - - - - ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. - - - - - - ► Multi-platform CLI ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. From 7f381b9e8795fa0821632fc79f85b558a5a7a2cd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:18:50 +0300 Subject: [PATCH 1399/1892] 4.6 RN --- releases/4.6.rst | 38 +++++++++++++++++++++++--------------- releases/4.7.rst | 6 ------ 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index db6702063..6fb0f80d7 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -72,21 +72,29 @@ Known Issues Version 4.6 resolved Issues --------------------------- -+--------------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+====================+================================================================================================+ -| SQ-12872 | Fixed unexpected Worker behavior caused by ``DROP TABLE`` statement | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12873 | Improved the time it takes to delete metadata keys | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-12965 | Fixed ``ReadParquet`` chunk producer output | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-13057 | Fixed ``DOUBLE`` casting into ``TEXT`` issue | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | -+--------------------+------------------------------------------------------------------------------------------------+ -| SQ-15828 | Fixed slow query runtime due to ``VIEW`` unexpected behavior | -+--------------------+------------------------------------------------------------------------------------------------+ ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++====================+=====================================================================================================================+ +| SQ-12872 | Fixed unexpected Worker behavior caused by ``DROP TABLE`` statement | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-12873 | Improved the time it takes to delete metadata keys | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-12965 | Fixed ``ReadParquet`` chunk producer output | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-13057 | Fixed ``DOUBLE`` casting into ``TEXT`` issue | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-15828 | Fixed slow query runtime due to ``VIEW`` unexpected behavior | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16397 | Fixed database tree UI rendering issue | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16531 | Resolved the error encountered when trying to create a ``VIEW`` using a table that requires a cleanup operation | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16592 | Fixed a discrepancy issue following ``OR`` condition execution | ++--------------------+---------------------------------------------------------------------------------------------------------------------+ + + Deprecations diff --git a/releases/4.7.rst b/releases/4.7.rst index 509e3a724..dd4b3b86f 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -90,12 +90,6 @@ Version 4.7 resolved Issues +--------------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +====================+=====================================================================================================================+ -| SQ-16592 | Fixed a discrepancy issue following ``OR`` condition execution | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16531 | Resolved the error encountered when trying to create a ``VIEW`` using a table that requires a cleanup operation | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16397 | Fixed database tree UI rendering issue | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | +--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-15690 | **Not fixed yet** - JDBC connector connectivity issue resulting in stuck queries | From a89eda10f75b2e3f74d1df644fc9d83af85f481e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:31:35 +0300 Subject: [PATCH 1400/1892] 4.6 RN --- releases/4.6.rst | 2 ++ releases/4.7.rst | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 6fb0f80d7..12f3a22ab 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` diff --git a/releases/4.7.rst b/releases/4.7.rst index dd4b3b86f..baab76d2e 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,7 +35,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + ► Multi-platform CLI From 9c7d1626c4825fe3f87b7b5e49b4c028ad366fde Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 09:52:41 +0300 Subject: [PATCH 1401/1892] 4.6 RN --- releases/4.6.rst | 6 ++++++ releases/4.7.rst | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 12f3a22ab..4357fbccf 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -102,10 +102,16 @@ Version 4.6 resolved Issues Deprecations ------------------- +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. + ► **CentOS Linux 7.x** * As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +* REHL 8.x is now officially supported. + Upgrading to Version 4.6 ------------------------- diff --git a/releases/4.7.rst b/releases/4.7.rst index baab76d2e..a12d8b28a 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -105,7 +105,9 @@ Starting October 2024, support for the Haskell CLI will be discontinued, and it ► **CentOS Linux 7.x** -As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +* REHL 8.x is now officially supported. Upgrading to Version 4.7 ------------------------- From 9418c6d90496dcccb6fa4ac338a9002f01186820 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 10:10:33 +0300 Subject: [PATCH 1402/1892] Update 4.6.rst --- releases/4.6.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/releases/4.6.rst b/releases/4.6.rst index 4357fbccf..2fd3161d3 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -66,6 +66,18 @@ New Features and Enhancements ► Our :ref:`Pysqream<sqlalchemy>` connector now support SQLAlchemy version 2.0.27. +► For any new SQreamDB installation or upgrade, your default :ref:`legacy configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` will include the following cluster flags: + +.. code-block:: json + + { + + "useLogMaxFileSize": false, + "logMaxFileSizeMB": 20, + "logFileRotateTimeFrequency": "daily", + + } + Known Issues ------------ From 635e09cd49c9a55876cfccdfad2086382ef8ef27 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:51:54 +0300 Subject: [PATCH 1403/1892] Update 4.6.rst --- releases/4.6.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 2fd3161d3..dc9d2aa29 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. @@ -58,8 +60,6 @@ New Features and Enhancements ► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. - ► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using keyword arguments. ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. From 961bd8a27683dcadbd5a1dc09c8ef8c87a22e761 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:59:34 +0300 Subject: [PATCH 1404/1892] Update 4.6.rst --- releases/4.6.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index dc9d2aa29..1dd4ed988 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -4,7 +4,7 @@ Release Notes 4.6 ***************** -The 4.6 release notes were released on February 19, 2024 +The 4.6 release notes were released on xxxxx xx, 2024 .. contents:: :local: @@ -112,7 +112,7 @@ Version 4.6 resolved Issues Deprecations -------------------- +------------ ► **Haskell CLI** From c1c8f958c1f4be41bc840e1bc55dfde440311145 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 13:55:39 +0300 Subject: [PATCH 1405/1892] Maintenance --- .../aggregate_functions/count.rst | 26 ++++--- .../aggregate_functions/index.rst | 10 ++- .../aggregate_functions/mode.rst | 76 +++++++++++-------- .../scalar_functions/string/octet_length.rst | 19 +++-- .../user_defined_functions/index.rst | 4 +- .../sql_statements/dml_commands/delete.rst | 43 ++++++----- .../sql_statements/dml_commands/update.rst | 29 ++++--- reference/sql/sql_syntax/joins.rst | 41 ++++++---- .../core_dumping_related_issues.rst | 4 +- 9 files changed, 154 insertions(+), 98 deletions(-) diff --git a/reference/sql/sql_functions/aggregate_functions/count.rst b/reference/sql/sql_functions/aggregate_functions/count.rst index 133d658f4..15e4de46a 100644 --- a/reference/sql/sql_functions/aggregate_functions/count.rst +++ b/reference/sql/sql_functions/aggregate_functions/count.rst @@ -1,13 +1,14 @@ .. _count: -************************** +***** COUNT -************************** +***** The ``COUNT`` function returns the count of numeric values, or only the distinct values. Syntax -========== +====== + The following is the correct syntax for using the ``COUNT`` function as an **aggregate**: .. code-block:: postgres @@ -25,7 +26,8 @@ The following is the correct syntax for using the ``COUNT`` function as a **wind ) Arguments -============ +========= + The following table describes the ``COUNT`` arguments: .. list-table:: @@ -42,12 +44,14 @@ The following table describes the ``COUNT`` arguments: - Specifies that the operation should operate only on unique values Returns -============ +======= + * The ``COUNT`` function returns ``BIGINT``. Notes -======= +===== + The following notes apply to the ``COUNT`` function: * When all rows contain ``NULL`` values, the function returns ``NULL``. @@ -60,7 +64,8 @@ The following notes apply to the ``COUNT`` function: Examples -=========== +======== + The examples in this section are based on a table named ``nba``, structured as follows: .. code-block:: postgres @@ -92,7 +97,8 @@ This section includes the following examples: :depth: 1 Counting Rows in a Table ---------------------------- +------------------------ + This example shows how to count rows in a table: .. code-block:: psql @@ -103,7 +109,8 @@ This example shows how to count rows in a table: 457 Counting Distinct Values in a Table ----------------------------------- +----------------------------------- + This example shows how to count distinct values in a table: The following structures generate the same result: @@ -125,6 +132,7 @@ The following structures generate the same result: Combining COUNT with Other Aggregates ------------------------------------- + This example shows how to combine the ``COUNT`` function with other aggregates: .. code-block:: psql diff --git a/reference/sql/sql_functions/aggregate_functions/index.rst b/reference/sql/sql_functions/aggregate_functions/index.rst index 5d3dfc125..ffd41b538 100644 --- a/reference/sql/sql_functions/aggregate_functions/index.rst +++ b/reference/sql/sql_functions/aggregate_functions/index.rst @@ -1,15 +1,17 @@ .. _aggregate_functions: -******************** +******************* Aggregate Functions -******************** +******************* Overview -=========== +======== + Aggregate functions perform calculations based on a set of values and return a single value. Most aggregate functions ignore null values. Aggregate functions are often used with the ``GROUP BY`` clause of the :ref:`select` statement. Available Aggregate Functions -=============== +============================= + The following list shows the available aggregate functions: .. hlist:: diff --git a/reference/sql/sql_functions/aggregate_functions/mode.rst b/reference/sql/sql_functions/aggregate_functions/mode.rst index a4675b659..b57186a41 100644 --- a/reference/sql/sql_functions/aggregate_functions/mode.rst +++ b/reference/sql/sql_functions/aggregate_functions/mode.rst @@ -1,8 +1,9 @@ .. _mode: -************************** +**** MODE -************************** +**** + The **MODE** function returns the most common value in the selected column. If there are no repeating values, or if there is the same frequency of multiple values, this function returns the top value based on the ``ORDER BY`` clause. The **MODE** function is commonly used with the following functions: @@ -11,7 +12,8 @@ The **MODE** function is commonly used with the following functions: * `PERCENTILE_DISC <https://docs.sqream.com/en/latest/reference/sql/sql_functions/aggregate_functions/percentile_disc.html>`_ function Syntax -======== +====== + The following is the correct syntax for the ``MODE`` function: .. code-block:: postgres @@ -19,38 +21,50 @@ The following is the correct syntax for the ``MODE`` function: MODE() WITHIN GROUP (ORDER BY column) Example -======== +======= + The example in this section is based on the ``players`` table below: .. list-table:: - :widths: 33 33 33 + :widths: auto :header-rows: 1 - -+-----------------+----------+-----------+ -| **Player_Name** | **Team** | **Score** | -+-----------------+----------+-----------+ -| T_Tock | Blue | 13 | -+-----------------+----------+-----------+ -| N_Stein | Blue | 20 | -+-----------------+----------+-----------+ -| F_Dirk | Blue | 20 | -+-----------------+----------+-----------+ -| Y_Hyung | Blue | 10 | -+-----------------+----------+-----------+ -| A_Rodrick | Blue | 13 | -+-----------------+----------+-----------+ -| R_Evans | Red | 55 | -+-----------------+----------+-----------+ -| C_Johnston | Red | 20 | -+-----------------+----------+-----------+ -| K_Stoll | Red | 25 | -+-----------------+----------+-----------+ -| J_Loftus | Red | 22 | -+-----------------+----------+-----------+ -| L_Ellis | Red | 7 | -+-----------------+----------+-----------+ -| G_Elroy | Red | 23 | -+-----------------+----------+-----------+ + + * - Player_Name + - Team + - Score + * - T_Tock + - Blue + - 13 + * - N_Stein + - Blue + - 20 + * - F_Dirk + - Blue + - 20 + * - Y_Hyung + - Blue + - 10 + * - A_Rodrick + - Blue + - 13 + * - R_Evans + - Red + - 55 + * - C_Johnston + - Red + - 20 + * - K_Stoll + - Red + - 25 + * - J_Loftus + - Red + - 22 + * - L_Ellis + - Red + - 7 + * - G_Elroy + - Red + - 23 The following is an example of the ``MODE`` function: diff --git a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst index 0836b4685..061b008c4 100644 --- a/reference/sql/sql_functions/scalar_functions/string/octet_length.rst +++ b/reference/sql/sql_functions/scalar_functions/string/octet_length.rst @@ -1,8 +1,8 @@ .. _octet_length: -************************** +************ OCTET_LENGTH -************************** +************ Calculates the number of bytes in a string. @@ -11,7 +11,8 @@ Calculates the number of bytes in a string. * To get the length in bytes, see :ref:`octet_length`. Syntax -========== +====== + The following is the correct syntax for the ``OCTET_LENGTH`` function: .. code-block:: postgres @@ -19,7 +20,8 @@ The following is the correct syntax for the ``OCTET_LENGTH`` function: OCTET_LEN( text_expr ) --> INT Arguments -============ +========= + The following table describes the ``OCTET_LENGTH`` arguments: .. list-table:: @@ -32,11 +34,13 @@ The following table describes the ``OCTET_LENGTH`` arguments: - ``TEXT`` expression Returns -============ +======= + The ``OCTET_LENGTH`` function returns an integer containing the number of bytes in the string. Notes -======= +===== + The following notes are applicable to the ``OCTET_LENGTH`` function: * To get the length in characters, see :ref:`char_length` @@ -44,7 +48,8 @@ The following notes are applicable to the ``OCTET_LENGTH`` function: * If the value is NULL, the result is NULL. Length in Characters and Bytes of Strings -=========== +========================================= + The **Length in characters and bytes of strings** example is based on the following table and contents: .. code-block:: postgres diff --git a/reference/sql/sql_functions/user_defined_functions/index.rst b/reference/sql/sql_functions/user_defined_functions/index.rst index b3c52022b..af3e5c281 100644 --- a/reference/sql/sql_functions/user_defined_functions/index.rst +++ b/reference/sql/sql_functions/user_defined_functions/index.rst @@ -1,8 +1,8 @@ .. _user_defined_functions_index: -******************** +********************** User-Defined Functions -******************** +********************** The following user-defined functions are functions that can be defined and configured by users. diff --git a/reference/sql/sql_statements/dml_commands/delete.rst b/reference/sql/sql_statements/dml_commands/delete.rst index b561eaf78..94d65ed57 100644 --- a/reference/sql/sql_statements/dml_commands/delete.rst +++ b/reference/sql/sql_statements/dml_commands/delete.rst @@ -1,18 +1,17 @@ .. _delete: -********************** +****** DELETE -********************** +****** Overview -================== +======== + The ``DELETE`` statement is used to remove specific rows from a table. SQream deletes data in the following steps: 1. The designated rows are marked as deleted, but remain on-disk until the user initiates a clean-up process. - - :: #. The user initiates a clean-up process is initiated to delete the rows. @@ -22,8 +21,6 @@ Note the following: * The :ref:`ALTER TABLE<alter_table>` and other `DDL operations <https://docs.sqream.com/en/latest/reference/sql/sql_statements/index.html#data-definition-commands-ddl>`_ are blocked on tables that require clean-up. - - * The value expression for deletion cannot be the result of a sub-query or join. * SQream may abort delete processes exceeding a pre-defined time threshold. If the estimated time exceeds the threshold, an error message is displayed with an description for overriding the threshold and continuing with the delete. @@ -35,7 +32,7 @@ For more information about SQream's delete methodology, see the :ref:`delete_gui * To delete columns, see :ref:`DROP COLUMN<drop_column>`. Permissions -============= +=========== To execute the ``DELETE`` statement, the ``DELETE`` and ``SELECT`` permissions must be assigned to the role at the table level. @@ -43,7 +40,8 @@ For more information about assigning permissions to roles, see `Creating, Assign Syntax -========== +====== + The following is the correct syntax for executing the ``DELETE`` statement: .. code-block:: postgres @@ -81,7 +79,8 @@ For systems with delete parallelism capabilities, use the following syntax to en .. note:: You may configure up to 10 threads. Parameters -============ +========== + The following table describes the parameters used for executing the ``DELETE`` statement: .. list-table:: @@ -101,7 +100,8 @@ The following table describes the parameters used for executing the ``DELETE`` s Examples -=========== +======== + The **Examples** section shows the following examples: * :ref:`Deleting values from a table<deleting_values_from_a_table>` @@ -111,7 +111,8 @@ The **Examples** section shows the following examples: .. _deleting_values_from_a_table: Deleting Values from a Table ------------------------------- +---------------------------- + The following shows an example of deleting values from a table: .. code-block:: psql @@ -140,7 +141,8 @@ The following shows an example of deleting values from a table: .. _deleting_values_based_on_more_complex_predicates: Deleting Values Based on More Complex Predicates ---------------------------------------------------- +------------------------------------------------ + The following shows an example of deleting values based on more complex predicates: .. code-block:: psql @@ -167,7 +169,8 @@ The following shows an example of deleting values based on more complex predicat 4 rows Deleting Values that Contain Multi-Table Conditions ------------------ +--------------------------------------------------- + The following shows an example of deleting values that contain multi-table conditions. The example is based on the following tables: .. image:: /_static/images/delete_optimization.png @@ -190,7 +193,8 @@ The statement below uses the ``EXISTS`` subquery to delete all bands based in Sw .. _identifying_and_cleaning_up_tables: Identifying and Cleaning Up Tables ---------------------------------------- +---------------------------------- + The following section shows examples of each phase required for cleaning up tables: * :ref:`Listing tables that require clean-up<listing_tables_that_require_cleanup>` @@ -200,7 +204,8 @@ The following section shows examples of each phase required for cleaning up tabl .. _listing_tables_that_require_cleanup: Listing Tables that Require Clean-Up -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following shows an example of listing tables that require clean-up: .. code-block:: psql @@ -216,7 +221,8 @@ The following shows an example of listing tables that require clean-up: .. _identifying_cleanup_predicates: Identify Clean-Up Predicates -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + The following shows an example of listing the clean-up predicates: .. code-block:: psql @@ -232,7 +238,8 @@ The following shows an example of listing the clean-up predicates: .. _triggering_a_cleanup: Triggering a Clean-Up -^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ + The following shows an example of triggering a clean-up: .. code-block:: psql diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index 3bbeceeef..ad2c149c8 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -1,8 +1,9 @@ .. _update: -********************** +****** UPDATE -********************** +****** + The **UPDATE** statement page describes the following: .. |icon-new_2022.1| image:: /_static/images/new_2022.1.png @@ -14,7 +15,8 @@ The **UPDATE** statement page describes the following: :depth: 1 Overview -========== +======== + The ``UPDATE`` statement is used to modify the value of certain columns in existing rows without creating a table. It can be used to do the following: @@ -30,7 +32,8 @@ It can be used to do the following: The ``UPDATE`` statement cannot be used to reference other tables in the ``WHERE`` or ``SET`` clauses. Syntax -========== +====== + The following is the correct syntax for the ``UPDATE`` command: .. code-block:: postgres @@ -43,7 +46,8 @@ The following is the correct syntax for the ``UPDATE`` command: Parameters -============ +========== + The following table describes the ``UPDATE`` parameters: .. list-table:: @@ -62,7 +66,7 @@ The following table describes the ``UPDATE`` parameters: - Specifies the condition for updating the data. Examples -=========== +======== The examples section shows how to modify the value of certain columns in existing rows without creating a table. @@ -117,7 +121,7 @@ To be able to follow the examples, create these two tables: :depth: 1 Updating an Entire Table ------------------ +------------------------ Two different ``UPDATE`` methods for updating an entire table. @@ -131,7 +135,8 @@ Two different ``UPDATE`` methods for updating an entire table. Performing Simple Updates ------------------ +------------------------- + The following is an example of performing a simple update: .. code-block:: postgres @@ -139,7 +144,8 @@ The following is an example of performing a simple update: UPDATE countries SET records_sold = records_sold + 1 WHERE name = 'Israel'; Updating Tables that Contain Multi-Table Conditions ------------------ +--------------------------------------------------- + The following shows an example of updating tables that contain multi-table conditions: .. code-block:: postgres @@ -155,6 +161,7 @@ The following shows an example of updating tables that contain multi-table condi Updating Tables that Contain Multi-Table Expressions ---------------------------------------------------- + The following shows an example of updating tables that contain multi-table expressions: .. code-block:: postgres @@ -169,7 +176,7 @@ The following shows an example of updating tables that contain multi-table expre ; Triggering a Cleanup ---------------------- +-------------------- When an ``UPDATE`` statement is executed, it creates a new table that contains the updated data, while the original table remains intact. As a result, residual data may be left behind, and a cleanup operation is necessary to ensure the database remains in a consistent state. @@ -184,6 +191,7 @@ The following is the syntax for triggering a cleanup: Permissions =========== + Executing an ``UPDATE`` statement requires the following permissions: * Both ``UPDATE`` and ``SELECT`` permissions on the target table. @@ -191,4 +199,5 @@ Executing an ``UPDATE`` statement requires the following permissions: Locking and Concurrency ======================= + Executing the ``UPDATE`` statement obtains an exclusive UPDATE lock on the target table, but does not lock the destination tables. \ No newline at end of file diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index b9d04c589..94f61291a 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -1,8 +1,8 @@ .. _joins: -*************************** +***** Joins -*************************** +***** The ``JOIN`` clause combines results from two or more table expressions (tables, external tables, views) based on a related column or other condition. Performing a join outputs a new result set. For example, two tables containing one or more columns in common can be joined to match or correlate with rows from another table. @@ -10,7 +10,8 @@ The ``JOIN`` clause combines results from two or more table expressions (tables, Syntax -========== +====== + The following shows the correct syntax for creating a **join**: .. code-block:: postgres @@ -30,7 +31,8 @@ The following shows the correct syntax for creating a **join**: MERGE | LOOP Join Types -------------- +---------- + The **Join Types** section describes the following join types: * :ref:`Inner joins<inner_joins>` @@ -41,7 +43,8 @@ The **Join Types** section describes the following join types: .. _inner_joins: Inner Joins -^^^^^^^^^^^^ +^^^^^^^^^^^ + The following shows the correct syntax for creating an **inner join**: .. code-block:: postgres @@ -70,7 +73,8 @@ For an inner join example, see :ref:`Inner Join Example<inner_join_example>`. .. _left_outer_joins: Left Outer Joins -^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^ + The following shows the correct syntax for creating an **left outer join**: .. code-block:: postgres @@ -85,7 +89,8 @@ For a left inner join example, see :ref:`Left Join Example<left_join_example>`. .. _right_outer_joins: Right Outer Joins -^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^ + The following shows the correct syntax for creating an **right outer join**: .. code-block:: postgres @@ -100,7 +105,8 @@ For a right outer join example, see :ref:`Right Join Example<right_join_example> .. _cross_joins: Cross Joins -^^^^^^^^^^^^^ +^^^^^^^^^^^ + The following shows the correct syntax for creating an **cross join**: .. code-block:: postgres @@ -145,7 +151,7 @@ For a cross join example, see :ref:`Cross Join Example<cross_join_example>`. The ON Condition -------------- +---------------- The ``ON`` condition is a value expression that generates a Boolean output to identify whether rows match. @@ -161,7 +167,8 @@ The ``ON`` clause is optional for ``LEFT`` and ``RIGHT`` joins. However, excludi Join Type Examples -============= +================== + The examples in this section are based on a pair of tables with the following structure and content: .. code-block:: postgres @@ -175,7 +182,8 @@ The examples in this section are based on a pair of tables with the following st .. _inner_join_example: Inner Join Example ------------- +------------------ + The following is an example of an inner join. .. code-block:: psql @@ -193,7 +201,8 @@ Notice in the example above that values with no matching conditions do not appea .. _left_join_example: Left Join Example ------------- +----------------- + The following is an example of a left join: .. code-block:: psql @@ -212,7 +221,8 @@ The following is an example of a left join: .. _right_join_example: Right Join Example ------------- +------------------ + The following is an example of a right join: .. code-block:: psql @@ -232,7 +242,8 @@ The following is an example of a right join: .. _cross_join_example: Cross Join Example -------------- +------------------ + The following is an example of a cross join: .. code-block:: psql @@ -297,7 +308,7 @@ Specifying multiple comma-separated tables is equivalent to a cross join, which 5 | 5 Join Hints -------------- +---------- **Join hints** can be used to override the query compiler and choose a particular join algorithm. The available algorithms are ``LOOP`` (corresponding to non-indexed nested loop join algorithm), and ``MERGE`` (corresponding to sort merge join algorithm). If no algorithm is specified, a loop join is performed by default. diff --git a/troubleshooting/core_dumping_related_issues.rst b/troubleshooting/core_dumping_related_issues.rst index ace7c8787..a4d71b9b0 100644 --- a/troubleshooting/core_dumping_related_issues.rst +++ b/troubleshooting/core_dumping_related_issues.rst @@ -1,8 +1,8 @@ .. _core_dumping_related_issues: -*********************** +*************************** Core Dumping Related Issues -*********************** +*************************** The **Core Dumping Related Issues** page describes the troubleshooting procedure to be followed if all parameters have been configured correctly, but the cores have not been created. From 24f0c4758a22f73ac3e65083aa09c2b53c59c50b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:02:26 +0300 Subject: [PATCH 1406/1892] Maintenance --- connecting_to_sqream/client_platforms/r.rst | 4 ++-- connecting_to_sqream/client_platforms/tableau.rst | 6 ------ connecting_to_sqream/client_platforms/talend.rst | 4 ---- 3 files changed, 2 insertions(+), 12 deletions(-) diff --git a/connecting_to_sqream/client_platforms/r.rst b/connecting_to_sqream/client_platforms/r.rst index 47fc680a2..074baf5ff 100644 --- a/connecting_to_sqream/client_platforms/r.rst +++ b/connecting_to_sqream/client_platforms/r.rst @@ -1,8 +1,8 @@ .. _r: -* +** R -* +** You can use R to interact with a SQream DB cluster. diff --git a/connecting_to_sqream/client_platforms/tableau.rst b/connecting_to_sqream/client_platforms/tableau.rst index 08119a29d..7b1efbb39 100644 --- a/connecting_to_sqream/client_platforms/tableau.rst +++ b/connecting_to_sqream/client_platforms/tableau.rst @@ -68,20 +68,14 @@ Connecting to SQream #. Start Tableau Desktop. - - :: #. In the **Connect** menu, under the **To a Server** option , click **More**. Additional connection options are displayed. - - :: #. Select **SQream DB by SQream Technologies**. A connection dialog box is displayed. - - :: #. In the connection dialog box, fill in the following fields: diff --git a/connecting_to_sqream/client_platforms/talend.rst b/connecting_to_sqream/client_platforms/talend.rst index c37350ee6..1b66c0086 100644 --- a/connecting_to_sqream/client_platforms/talend.rst +++ b/connecting_to_sqream/client_platforms/talend.rst @@ -82,8 +82,6 @@ Supported SQream Drivers The following list shows the supported SQream drivers and versions: * **JDBC** - Version 4.3.3 and higher. - - :: * **ODBC** - Version 4.0.0. This version requires a Bridge to connect. For more information on the required Bridge, see `Connecting Talend on Windows to an ODBC Database <https://www.easysoft.com/blog/talend.html>`_. @@ -94,8 +92,6 @@ Talend Cloud connectors let you create reusable connections with a wide variety * **Connections:** Connections are environments or systems for storing datasets, including databases, file systems, distributed systems and platforms. Because these systems are reusable, you only need to establish connectivity with them once. - :: - * **Datasets:** Datasets include database tables, file names, topics (Kafka), queues (JMS) and file paths (HDFS). For more information on the complete list of connectors and datasets that Talend supports, see `Introducing Talend Connectors <https://help.talend.com/r/vqIZei8ynfi_BaDCg3d~_g/M0qzU1kTnL0bPou7OuxJfw>`_. Known Issues From d79b899358bf5bca130fef2fdd8ddbae1bb106b8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:23:27 +0300 Subject: [PATCH 1407/1892] Maintenance --- reference/cli/multi_platform_cli.rst | 6 +- reference/cli/sqream_cli.rst | 72 +++++++++++---------- reference/cli/sqream_console.rst | 94 ++++++++++++++-------------- 3 files changed, 83 insertions(+), 89 deletions(-) diff --git a/reference/cli/multi_platform_cli.rst b/reference/cli/multi_platform_cli.rst index 702c9fad4..223c81871 100644 --- a/reference/cli/multi_platform_cli.rst +++ b/reference/cli/multi_platform_cli.rst @@ -1,13 +1,11 @@ .. _multi_platform_cli: -********************************* +************************* Multi-Platform Sqream SQL -********************************* +************************* SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. -This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. - .. contents:: :local: :depth: 1 diff --git a/reference/cli/sqream_cli.rst b/reference/cli/sqream_cli.rst index 76eabae72..7d9b709f8 100644 --- a/reference/cli/sqream_cli.rst +++ b/reference/cli/sqream_cli.rst @@ -1,8 +1,8 @@ .. _sqream_cli: -********************************* +************ SQreamDB CLI -********************************* +************ ``sqream-console`` is an interactive shell designed to help manage a dockerized SQream DB installation. @@ -13,7 +13,7 @@ The console itself is a dockerized application. :depth: 1 Starting the console -====================== +==================== ``sqream-console`` can be found in your SQream DB installation, under the name ``sqream-console``. @@ -63,10 +63,10 @@ All SQream DB-specific commands start with the keyword ``sqream``. Operations and flag reference -=============================== +============================= Commands ------------------------ +-------- .. list-table:: :widths: auto @@ -88,12 +88,12 @@ Commands .. _master_node: Master ------------- +------ The master node contains the :ref:`metadata server<metadata_server_cli_reference>` and the :ref:`load balancer<server_picker_cli_reference>`. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -122,10 +122,10 @@ Syntax - Sets the port for the metadata server. Defaults to ``3105`` Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start master node -******************** +***************** .. code-block:: console @@ -134,7 +134,7 @@ Start master node sqream_single_host_master is up and listening on ports: 3105,3108 Start master node on different ports -******************************************* +************************************ .. code-block:: console @@ -143,7 +143,7 @@ Start master node on different ports sqream_single_host_master is up and listening on ports: 4105,4108 Listing active master nodes and workers -*************************************************** +*************************************** .. code-block:: console @@ -153,7 +153,7 @@ Listing active master nodes and workers container name: sqream_single_host_master, container id: ea7eef80e038 Stopping all SQream DB workers and master -********************************************* +***************************************** .. code-block:: console @@ -167,12 +167,12 @@ Stopping all SQream DB workers and master .. _workers: Workers ------------- +------- Workers are :ref:`SQream DB daemons<sqreamd_cli_reference>`, that connect to the master node. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -217,10 +217,10 @@ Start options are specified consecutively, separated by spaces. - For testing only: Starts a worker without connecting to the master node. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start 2 workers -******************** +*************** After starting the master node, start workers: @@ -231,7 +231,7 @@ After starting the master node, start workers: started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 Stop a single worker -******************************************* +******************** To stop a single worker, find its name first: @@ -250,7 +250,7 @@ Then, issue a stop command: stopped sqream_single_host_worker_1 Start workers with a different spool size -********************************************** +***************************************** If no spool size is specified, the RAM is equally distributed among workers. Sometimes a system engineer may wish to specify the spool size manually. @@ -262,7 +262,7 @@ This example starts two workers, with a spool size of 50GB per node: sqream-console> sqream worker --start 2 -m 50 Starting multiple workers on non-dedicated GPUs -**************************************************** +*********************************************** By default, SQream DB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. @@ -278,7 +278,7 @@ This example starts 4 workers on 2 GPUs, with 50GB spool each: started sqream_single_host_worker_3 on port 5003, allocated gpu: 1 Overriding default configuration files -******************************************* +************************************** It is possible to override default configuration settings by listing a configuration file for every worker. @@ -289,14 +289,12 @@ This example starts 2 workers on the same GPU, with modified configuration files sqream-console> sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json Client ------------- +------ The client operation runs :ref:`sqream sql<sqream_sql_cli_reference>` in interactive mode. -.. note:: The dockerized client is useful for testing and experimentation. It is not the recommended method for executing analytic queries. See more about connecting a :ref:`third party tool to SQream DB <third_party_tools>` for data analysis. - Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -324,10 +322,10 @@ Syntax - Specifies the database name for the connection. Defaults to ``master``. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start a client -******************** +************** Connect to default ``master`` database through the load balancer: @@ -340,7 +338,7 @@ Connect to default ``master`` database through the load balancer: master=> _ Start a client to a specific worker -************************************** +*********************************** Connect to database ``raviga`` directly to a worker on port 5000: @@ -353,7 +351,7 @@ Connect to database ``raviga`` directly to a worker on port 5000: raviga=> _ Start master node on different ports -******************************************* +************************************ .. code-block:: console @@ -362,7 +360,7 @@ Start master node on different ports sqream_single_host_master is up and listening on ports: 4105,4108 Listing active master nodes and worker nodes -*************************************************** +******************************************** .. code-block:: console @@ -374,14 +372,14 @@ Listing active master nodes and worker nodes .. _start_editor: Editor ------------- +------ -The editor operation runs the web UI for the :ref:`SQream DB Statement Editor<statement_editor>`. +The editor operation runs the web UI for the SQreamDB Statement Editor. The editor can be used to run queries from a browser. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -401,10 +399,10 @@ Syntax - Specify a different port for the editor. Defaults to ``3000``. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start the editor UI -********************** +******************* .. code-block:: console @@ -412,7 +410,7 @@ Start the editor UI access sqream statement editor through Chrome http://192.168.0.100:3000 Stop the editor UI -********************** +****************** .. code-block:: console @@ -421,12 +419,12 @@ Stop the editor UI Using the console to start SQream DB -============================================ +==================================== The console is used to start and stop SQream DB components in a dockerized environment. Starting a SQream DB cluster for the first time -------------------------------------------------------- +----------------------------------------------- To start a SQream DB cluster, start the master node, followed by workers. diff --git a/reference/cli/sqream_console.rst b/reference/cli/sqream_console.rst index ba1849475..280ab0b14 100644 --- a/reference/cli/sqream_console.rst +++ b/reference/cli/sqream_console.rst @@ -1,8 +1,8 @@ .. _sqream_console_cli_reference: -********************************* +**************** SqreamDB Console -********************************* +**************** ``sqream-console`` is an interactive shell designed to help manage a dockerized SQreamDB installation. @@ -13,7 +13,7 @@ The console itself is a dockerized application. :depth: 1 Starting the console -====================== +==================== ``sqream-console`` can be found in your SQreamDB installation, under the name ``sqream-console``. @@ -59,14 +59,14 @@ The console is now waiting for commands. The console is a wrapper around a standard linux shell. It supports commands like ``ls``, ``cp``, etc. -All SQream DB-specific commands start with the keyword ``sqream``. +All SQreamDB-specific commands start with the keyword ``sqream``. Operations and flag reference -=============================== +============================= Commands ------------------------ +-------- .. list-table:: :widths: auto @@ -88,12 +88,12 @@ Commands .. _master_node: Master ------------- +------ The master node contains the :ref:`metadata server<metadata_server_cli_reference>` and the :ref:`load balancer<server_picker_cli_reference>`. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -113,7 +113,7 @@ Syntax * - ``--stop [ --all ]`` - Stops the master node and all connected :ref:`workers<workers>`. - The ``--all`` modifier instructs the ``--stop`` command to stop all running services related to SQream DB + The ``--all`` modifier instructs the ``--stop`` command to stop all running services related to SQreamDB * - ``--list`` - Shows a list of all active master nodes and their workers * - ``-p <port>`` @@ -122,10 +122,10 @@ Syntax - Sets the port for the metadata server. Defaults to ``3105`` Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start master node -******************** +***************** .. code-block:: console @@ -134,7 +134,7 @@ Start master node sqream_single_host_master is up and listening on ports: 3105,3108 Start master node on different ports -******************************************* +************************************ .. code-block:: console @@ -143,7 +143,7 @@ Start master node on different ports sqream_single_host_master is up and listening on ports: 4105,4108 Listing active master nodes and workers -*************************************************** +*************************************** .. code-block:: console @@ -152,8 +152,8 @@ Listing active master nodes and workers container name: sqream_single_host_worker_0, container id: c919e8fb78c8 container name: sqream_single_host_master, container id: ea7eef80e038 -Stopping all SQream DB workers and master -********************************************* +Stopping all SQreamDB workers and master +***************************************** .. code-block:: console @@ -167,12 +167,12 @@ Stopping all SQream DB workers and master .. _workers: Workers ------------- +------- -Workers are :ref:`SQream DB daemons<sqreamd_cli_reference>`, that connect to the master node. +Workers are :ref:`SQreamDB daemons<sqreamd_cli_reference>`, that connect to the master node. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -217,10 +217,10 @@ Start options are specified consecutively, separated by spaces. - For testing only: Starts a worker without connecting to the master node. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start 2 workers -******************** +*************** After starting the master node, start workers: @@ -231,7 +231,7 @@ After starting the master node, start workers: started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 Stop a single worker -******************************************* +******************** To stop a single worker, find its name first: @@ -250,7 +250,7 @@ Then, issue a stop command: stopped sqream_single_host_worker_1 Start workers with a different spool size -********************************************** +***************************************** If no spool size is specified, the RAM is equally distributed among workers. Sometimes a system engineer may wish to specify the spool size manually. @@ -262,9 +262,9 @@ This example starts two workers, with a spool size of 50GB per node: sqream-console> sqream worker --start 2 -m 50 Starting multiple workers on non-dedicated GPUs -**************************************************** +*********************************************** -By default, SQream DB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. +By default, SQreamDB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. This example starts 4 workers on 2 GPUs, with 50GB spool each: @@ -278,7 +278,7 @@ This example starts 4 workers on 2 GPUs, with 50GB spool each: started sqream_single_host_worker_3 on port 5003, allocated gpu: 1 Overriding default configuration files -******************************************* +************************************** It is possible to override default configuration settings by listing a configuration file for every worker. @@ -289,14 +289,12 @@ This example starts 2 workers on the same GPU, with modified configuration files sqream-console> sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json Client ------------- +------ The client operation runs :ref:`sqream sql<sqream_sql_cli_reference>` in interactive mode. -.. note:: The dockerized client is useful for testing and experimentation. It is not the recommended method for executing analytic queries. See more about connecting a :ref:`third party tool to SQream DB <third_party_tools>` for data analysis. - Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -324,10 +322,10 @@ Syntax - Specifies the database name for the connection. Defaults to ``master``. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start a client -******************** +************** Connect to default ``master`` database through the load balancer: @@ -340,7 +338,7 @@ Connect to default ``master`` database through the load balancer: master=> _ Start a client to a specific worker -************************************** +*********************************** Connect to database ``raviga`` directly to a worker on port 5000: @@ -353,7 +351,7 @@ Connect to database ``raviga`` directly to a worker on port 5000: raviga=> _ Start master node on different ports -******************************************* +************************************ .. code-block:: console @@ -362,7 +360,7 @@ Start master node on different ports sqream_single_host_master is up and listening on ports: 4105,4108 Listing active master nodes and worker nodes -*************************************************** +******************************************** .. code-block:: console @@ -374,14 +372,14 @@ Listing active master nodes and worker nodes .. _start_editor: Editor ------------- +------ -The editor operation runs the web UI for the :ref:`SQream DB Statement Editor<statement_editor>`. +The editor operation runs the web UI for the SQreamDB Statement Editor. The editor can be used to run queries from a browser. Syntax -^^^^^^^^^^ +^^^^^^ .. code-block:: console @@ -401,10 +399,10 @@ Syntax - Specify a different port for the editor. Defaults to ``3000``. Common usage -^^^^^^^^^^^^^^^ +^^^^^^^^^^^^ Start the editor UI -********************** +******************* .. code-block:: console @@ -412,7 +410,7 @@ Start the editor UI access sqream statement editor through Chrome http://192.168.0.100:3000 Stop the editor UI -********************** +****************** .. code-block:: console @@ -420,15 +418,15 @@ Stop the editor UI sqream_editor stopped -Using the console to start SQream DB -============================================ +Using the console to start SQreamDB +=================================== -The console is used to start and stop SQream DB components in a dockerized environment. +The console is used to start and stop SQreamDB components in a dockerized environment. -Starting a SQream DB cluster for the first time -------------------------------------------------------- +Starting a SQreamDB cluster for the first time +---------------------------------------------- -To start a SQream DB cluster, start the master node, followed by workers. +To start a SQreamDB cluster, start the master node, followed by workers. The example below starts 2 workers, running on 2 dedicated GPUs. @@ -445,6 +443,6 @@ The example below starts 2 workers, running on 2 dedicated GPUs. sqream-console> sqream editor --start access sqream statement editor through Chrome http://192.168.0.100:3000 -SQream DB is now listening on port 3108 for any incoming statements. +SQreamDB is now listening on port 3108 for any incoming statements. -A user can also access the web editor (running on port ``3000`` on the SQream DB machine) to connect and run queries. \ No newline at end of file +A user can also access the web editor (running on port ``3000`` on the SQreamDB machine) to connect and run queries. \ No newline at end of file From 9c9fa89949655581d47db0f4dce56fa7421f51e3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 14:41:39 +0300 Subject: [PATCH 1408/1892] Maintenance --- releases/2022.1.2.rst | 2 -- releases/2022.1.3.rst | 14 -------------- releases/2022.1.4.rst | 10 ---------- releases/2022.1.5.rst | 14 -------------- releases/2022.1.6.rst | 10 ---------- releases/2022.1.7.rst | 12 ------------ releases/4.0.rst | 4 +--- releases/4.1.rst | 24 +++++++----------------- releases/4.2.rst | 19 +++---------------- 9 files changed, 11 insertions(+), 98 deletions(-) diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst index 8b65a56e2..b45f10af5 100644 --- a/releases/2022.1.2.rst +++ b/releases/2022.1.2.rst @@ -17,8 +17,6 @@ The 2022.1.2 Release Notes describes the following: * Automatic schema identification. - :: - * Optimized queries on external Parquet tables. Storage Version diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst index d1de10668..1c073760b 100644 --- a/releases/2022.1.3.rst +++ b/releases/2022.1.3.rst @@ -17,16 +17,10 @@ The 2022.1.3 Release Notes describes the following: * Optimize the delete operation by removing redundant calls. - :: - * Support LIKE condition for filtering metadata. - :: - * Migration tool for converting VARCHAR columns into TEXT columns. - :: - * Support sub-queries in the UPDATE condition. Storage Version @@ -113,20 +107,12 @@ Upgrading to v2022.1.3 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst index 9b0ce45fe..d4fa19783 100644 --- a/releases/2022.1.4.rst +++ b/releases/2022.1.4.rst @@ -17,8 +17,6 @@ The 2022.1.4 Release Notes describes the following: * Security enhancement - Disable Python UDFs by default. - :: - Storage Version --------------- @@ -93,20 +91,12 @@ Upgrading to v2022.1.4 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst index e6324e9cb..7a26cf30a 100644 --- a/releases/2022.1.5.rst +++ b/releases/2022.1.5.rst @@ -17,16 +17,10 @@ The 2022.1.5 Release Notes include the following new features: * ``keys_evaluate`` utility function enhancement - add problematic chunk ID to the function's output report - :: - * Automatically close database client connections that have been open for 24 hours without any active statements - :: - * ``release_defunct_locks`` utility function enhancement to receive new optional input parameter to specify timeout - for more details see :ref:`Lock Related Issues <lock_related_issues>`. - :: - * Metadata scale up process improvement through RocksDB configuration improvements Storage Version @@ -113,20 +107,12 @@ Upgrading to v2022.1.5 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst index 0f9c13336..6734ef097 100644 --- a/releases/2022.1.6.rst +++ b/releases/2022.1.6.rst @@ -15,8 +15,6 @@ New Features * :ref:`.Net Driver<net>` now supports .NET version 6 or newer. - :: - Storage Version --------------- @@ -92,20 +90,12 @@ Upgrading to v2022.1.6 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst index cd24a1e62..a8a61202f 100644 --- a/releases/2022.1.7.rst +++ b/releases/2022.1.7.rst @@ -15,12 +15,8 @@ New Features * Ingesting data from :ref:`JSON<json>` files. - :: - * ZLIB compression performance enhancements. - :: - Storage Version --------------- @@ -84,20 +80,12 @@ Upgrading to v2022.1.7 2. Shut down all SQream services. - :: - 3. Extract the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/4.0.rst b/releases/4.0.rst index 44ed49163..f69d01f5e 100644 --- a/releases/4.0.rst +++ b/releases/4.0.rst @@ -31,8 +31,6 @@ SQream Studio Updates and Improvements -------------------------------------- * When creating a **New Role**, you may now create a group role by selecting **Set as a group role**. - - :: * When editing an **Existing Role**, you are no longer obligated to update the role's password. @@ -42,7 +40,7 @@ Known Issues :ref:`Percentile<percentile_disc>` is not supported for Window functions. Version 4.0 resolved Issues ----------------------------- +--------------------------- +-----------------+---------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | diff --git a/releases/4.1.rst b/releases/4.1.rst index 2e4dd0ae4..0b88617bb 100644 --- a/releases/4.1.rst +++ b/releases/4.1.rst @@ -1,8 +1,8 @@ .. _4.1: -************************** +***************** Release Notes 4.1 -************************** +***************** SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. @@ -16,8 +16,6 @@ New Features ------------ * :ref:`Lightweight Directory Access Protocol (LDAP)<ldap>` management enhancement - - :: * A new brute-force attack protection mechanism locks out user accounts for 15 minutes following 5 consecutive failed login attempts @@ -36,8 +34,6 @@ SQream Studio Updates and Improvements SQream Studio v5.5.4 has been released. - :: - Known Issues ------------ @@ -45,7 +41,7 @@ Known Issues Version 4.1 resolved Issues ------------------------------ +--------------------------- +------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -98,11 +94,13 @@ The ``VARCHAR`` data type is deprecated to improve the core functionalities of t End of Support ---------------- +-------------- + No End of Support changes were made. Upgrading to v4.1 -------------------- +----------------- + 1. Generate a back-up of the metadata by running the following command: .. code-block:: console @@ -115,20 +113,12 @@ Upgrading to v4.1 2. Shut down all SQream services. - :: - 3. Copy the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console diff --git a/releases/4.2.rst b/releases/4.2.rst index 87f266740..203afa04a 100644 --- a/releases/4.2.rst +++ b/releases/4.2.rst @@ -1,8 +1,8 @@ .. _4.2: -************************** +***************** Release Notes 4.2 -************************** +***************** SQream is introducing a new version release system that follows the more commonly used Major.Minor.Patch versioning schema. The newly released **4.0 version** is a minor version upgrade and does not require considerable preparation. @@ -17,8 +17,6 @@ New Features :ref:`Apache Spark<spark>` may now be used for large-scale data processing. - - :: :ref:`Physical deletion<delete_guide>` performance enhancement by supporting file systems with parallelism capabilities @@ -70,8 +68,6 @@ SQream Studio Updates and Improvements SQream Studio v5.5.4 has been released. - :: - Known Issues ------------ @@ -80,9 +76,8 @@ Known Issues * Performance degradation when using ``VARCHAR`` partition key in a :ref:`Window Functions<window_functions>` expression - Version 4.2 Resolved Issues ------------------------------ +--------------------------- +------------------------+------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | @@ -152,20 +147,12 @@ Upgrading to v4.2 2. Shut down all SQream services. - :: - 3. Copy the recently created back-up file. - :: - 4. Replace your current metadata with the metadata you stored in the back-up file. - :: - 5. Navigate to the new SQream package bin folder. - :: - 6. Run the following command: .. code-block:: console From e8b5567bdf922ec4533442f79904aa972318c210 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:24:57 +0300 Subject: [PATCH 1409/1892] Metalanguage scripting --- reference/sql/sql_syntax/index.rst | 2 + reference/sql/sql_syntax/sqream_scripting.rst | 125 ++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 reference/sql/sql_syntax/sqream_scripting.rst diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 55792fa8c..49c1ee58b 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -30,6 +30,8 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Subqueries are nested queries that are embedded within a larger query to retrieve data, perform calculations, or filter results based on the outcome of the inner query. * - :ref:`null_handling` - Null handling involves managing and evaluating the presence of null values, representing unknown or undefined data, to avoid unexpected results in queries and expressions. + * - :ref:`sqream_scripting` + - diff --git a/reference/sql/sql_syntax/sqream_scripting.rst b/reference/sql/sql_syntax/sqream_scripting.rst new file mode 100644 index 000000000..cd1ba7213 --- /dev/null +++ b/reference/sql/sql_syntax/sqream_scripting.rst @@ -0,0 +1,125 @@ +.. _sqream_scripting: + +**************** +SQream Scripting +**************** + +The Java- based SQreamDB scripting enhances your interaction with SQL by providing conventions which allow dynamic generation, management, and automation of SQL code and database operations. + +Syntax +====== + +.. code-block:: postgres + + -- Parallel: + + @@ Parallel $$ ... $$ + + -- Declare: + + @@ Declare <my_parameter> = <value> + + -- SetResults: + + @@ SetResults <result_variable> + + -- SplitQueryByDateTime + + @@ SplitQueryByDateTime instances = <value>, from = <value>, to = <value> + + -- SplitQueryByDate + + @@ SplitQueryByDate instances = <value>, from = <value>, to = <value> + + -- SplitQueryByNumber + + @@ SplitQueryByNumber instances = <value>, from = <value>, to = <value> + + -- ${ ... } + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``Parallel`` + - Runs specified queries in parallel + * - ``Declare`` + - Declares a variable value + * - ``SetResults`` + - Saves specified query results as a variable + * - ``SplitQueryByDateTime`` + - Splits query execution by a predefined number of instances and by specific ``DATETIME`` column values + * - ``SplitQueryByDate`` + - Splits query execution by a predefined number of instances and by specific ``DATE`` column values + * - ``SplitQueryByNumber`` + - Splits query execution by a predefined number of instances and by specific ``NUMERIC`` column values + +Usage Notes +=========== + +.. glossary:: + + **Execution** + Metalanguage scripting is available only through the SQreamDB web interface and cannot be used via the CLI. + +Examples +======== + +``Parallel`` +------------ + +.. code-block:: console + + @@ Parallel + $$ + SELECT * FROM my_table; + SELECT * FROM our_table; + SELECT * FROM that_table; + $$; + +``Declare`` +----------- + +.. code-block:: console + + @@ Declare myVar = 3; + SELECT ${myVar}; + +``SetResults`` +-------------- + +.. code-block:: console + + @@ SetResults tableAverage + SELECT AVG(col1) AS avg_salary FROM my_table; + + SELECT col1 FROM my_table WHERE col1 > ${tableAverage[0].avg_salary}; + + +``SplitQueryByDateTime`` +------------------------ + +.. code-block:: console + + @@ SplitQueryByDateTime instances = 4, from = '2021-01-01 00:00:00', to = '2022-01-01 00:00:00' + SELECT ${from}, ${to}; + + +``SplitQueryByDate`` +-------------------- + +.. code-block:: console + + @@ SplitQueryByDateTime instances = 4, from = '2021-01-01', to = '2022-01-01' + SELECT ${from}, ${to}; + + +``SplitQueryByNumber`` +---------------------- + +.. code-block:: console + + @@ SplitQueryByDateTime instances = 4, from = 0, to = 100 + SELECT ${from}, ${to}; From 67b8bb6399be3a443c8001d3b718104fc29e5cf0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 15:27:36 +0300 Subject: [PATCH 1410/1892] Update index.rst --- reference/sql/sql_syntax/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 49c1ee58b..77586250b 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -31,7 +31,7 @@ SQreamDB supports SQL from the ANSI 92 syntax. * - :ref:`null_handling` - Null handling involves managing and evaluating the presence of null values, representing unknown or undefined data, to avoid unexpected results in queries and expressions. * - :ref:`sqream_scripting` - - + - Metalanguage scripting enhances your interaction with SQL by providing conventions which allow dynamic generation, management, and automation of SQL code. From cd53dac5feef8b014a15b8f51935e4e124b5dc9e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:01:20 +0300 Subject: [PATCH 1411/1892] Update sqream_scripting.rst --- reference/sql/sql_syntax/sqream_scripting.rst | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_syntax/sqream_scripting.rst b/reference/sql/sql_syntax/sqream_scripting.rst index cd1ba7213..72a274cee 100644 --- a/reference/sql/sql_syntax/sqream_scripting.rst +++ b/reference/sql/sql_syntax/sqream_scripting.rst @@ -11,13 +11,17 @@ Syntax .. code-block:: postgres + -- Double curly brackets + + {{ … }} + -- Parallel: @@ Parallel $$ ... $$ -- Declare: - @@ Declare <my_parameter> = <value> + @@ Declare '<my_parameter>' = <value> -- SetResults: @@ -43,6 +47,8 @@ Syntax * - Parameter - Description + * - ``{{ … }}`` + - Double brackets can contain JavaScript code to be executed through the Editor * - ``Parallel`` - Runs specified queries in parallel * - ``Declare`` @@ -67,6 +73,15 @@ Usage Notes Examples ======== +Double Curly Brackets +--------------------- + +.. code-block:: console + + {{ + return 1; + }} + ``Parallel`` ------------ @@ -85,7 +100,7 @@ Examples .. code-block:: console @@ Declare myVar = 3; - SELECT ${myVar}; + SELECT '${myVar}'; ``SetResults`` -------------- From e85fc9615566d7ee908a45b235c70eb1edcdacde Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:22:04 +0300 Subject: [PATCH 1412/1892] Update 4.6.rst --- releases/4.6.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 1dd4ed988..ce59d52c8 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -35,6 +35,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► REHL 8.x is now officially supported. + ► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. @@ -120,9 +122,9 @@ Starting October 2024, support for the Haskell CLI will be discontinued, and it ► **CentOS Linux 7.x** -* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +CentOS Linux 7.x has reached its end of life and is not supported by SQreamDB. + -* REHL 8.x is now officially supported. Upgrading to Version 4.6 ------------------------- From 69350502bae9f5ff9788c074db5ef6f7396941c1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:23:21 +0300 Subject: [PATCH 1413/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index ce59d52c8..863dbc1f8 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -118,7 +118,7 @@ Deprecations ► **Haskell CLI** -Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. +Starting February 2025, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. ► **CentOS Linux 7.x** From 38bfea3015882c24155c15d9844c097bb3a400a7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:29:04 +0300 Subject: [PATCH 1414/1892] 4.6 RN --- .../sql_functions/scalar_functions/conversion/is_castable.rst | 2 +- releases/4.6.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst index 577bf4a52..8e54c4c0a 100644 --- a/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst +++ b/reference/sql/sql_functions/scalar_functions/conversion/is_castable.rst @@ -8,7 +8,7 @@ The ``IsCastable`` function checks whether a data type cast operation is support .. tip:: - See BLUE :ref:`supported casts table <supported_casts>` + See :ref:`supported casts table <supported_casts>` Syntax ====== diff --git a/releases/4.6.rst b/releases/4.6.rst index 863dbc1f8..fd8af4ffa 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -54,11 +54,11 @@ New Features and Enhancements ► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. -► Sing in to SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. +► Sign into SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. -► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning cloud storage but also helps conserve storage space. +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. ► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. From a880f698a6be4261779d1bfa47f005b25e43eeea Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 07:52:17 +0300 Subject: [PATCH 1415/1892] Update 4.6.rst --- releases/4.6.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index fd8af4ffa..6469fe370 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -16,10 +16,9 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x / 8.x | +| Supported OS | * RHEL - 7.x / 8.x | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +| supported Nvidia driver | CUDA version from 10.1 up to 11.4 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ From 83d35902bdcd2e032f2e1753ee5d6501a3720fd0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:53:04 +0300 Subject: [PATCH 1416/1892] Update installing_nginx_proxy_over_secure_connection.rst --- ...ing_nginx_proxy_over_secure_connection.rst | 56 ++++++------------- 1 file changed, 17 insertions(+), 39 deletions(-) diff --git a/installation_guides/installing_nginx_proxy_over_secure_connection.rst b/installation_guides/installing_nginx_proxy_over_secure_connection.rst index b13c01427..e4290b6fc 100644 --- a/installation_guides/installing_nginx_proxy_over_secure_connection.rst +++ b/installation_guides/installing_nginx_proxy_over_secure_connection.rst @@ -6,19 +6,18 @@ Installing an NGINX Proxy Over a Secure Connection Configuring your NGINX server to use a strong encryption for client connections provides you with secure servers requests, preventing outside parties from gaining access to your traffic. -.. contents:: - :local: - :depth: 1 +The Node.js platform that SQreamDB uses with our Studio user interface is susceptible to web exposure. This page describes how to implement HTTPS access on your proxy server to establish a secure connection. -The Node.js platform that SQream uses with our Studio user interface is susceptible to web exposure. This page describes how to implement HTTPS access on your proxy server to establish a secure connection. - -**TLS (Transport Layer Security)**, and its predecessor **SSL (Secure Sockets Layer)**, are standard web protocols used for wrapping normal traffic in a protected, encrypted wrapper. This technology prevents the interception of server-client traffic. It also uses a certificate system for helping users verify the identity of sites they visit. The **Installing an NGINX Proxy Over a Secure Connection** guide describes how to set up a self-signed SSL certificate for use with an NGINX web server on a CentOS 7 server. +**TLS (Transport Layer Security)**, and its predecessor **SSL (Secure Sockets Layer)**, are standard web protocols used for wrapping normal traffic in a protected, encrypted wrapper. This technology prevents the interception of server-client traffic. It also uses a certificate system for helping users verify the identity of sites they visit. The **Installing an NGINX Proxy Over a Secure Connection** guide describes how to set up a self-signed SSL certificate for use with an NGINX web server on a RHEL server. .. note:: A self-signed certificate encrypts communication between your server and any clients. However, because it is not signed by trusted certificate authorities included with web browsers, you cannot use the certificate to automatically validate the identity of your server. -A self-signed certificate may be appropriate if your domain name is not associated with your server, and in cases where your encrypted web interface is not user-facing. If you do have a domain name, using a CA-signed certificate is generally preferrable. +A self-signed certificate may be appropriate if your domain name is not associated with your server, and in cases where your encrypted web interface is not user-facing. If you do have a domain name, using a CA-signed certificate is generally preferable. -For more information on setting up a free trusted certificate, see `How To Secure Nginx with Let's Encrypt on CentOS 7 <https://www.digitalocean.com/community/tutorials/how-to-secure-nginx-with-let-s-encrypt-on-centos-7>`_. + +.. contents:: + :local: + :depth: 1 Prerequisites ============= @@ -26,17 +25,15 @@ Prerequisites The following prerequisites are required for installing an NGINX proxy over a secure connection: * Super user privileges - - :: * A domain name to create a certificate for Installing NGINX and Adjusting the Firewall =========================================== -After verifying that you have the above preriquisites, you must verify that the NGINX web server has been installed on your machine. +After verifying that you have the above prerequisites, you must verify that the NGINX web server has been installed on your machine. -Though NGINX is not available in the default CentOS repositories, it is available from the **EPEL (Extra Packages for Enterprise Linux)** repository. +Though NGINX is not available in the default RHEL repositories, it is available from the **EPEL (Extra Packages for Enterprise Linux)** repository. **To install NGINX and adjust the firewall:** @@ -72,10 +69,6 @@ Though NGINX is not available in the default CentOS repositories, it is availabl Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago - . . . - - Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. - 5. Enable NGINX to start when your server boots up: .. code-block:: console @@ -84,21 +77,19 @@ Though NGINX is not available in the default CentOS repositories, it is availabl 6. Verify that access to **ports 80 and 443** are not blocked by a firewall. - :: 7. Do one of the following: * If you are not using a firewall, skip to :ref:`Creating Your SSL Certificate<creating_your_ssl_certificate>`. - :: * If you have a running firewall, open ports 80 and 443: .. code-block:: console - sudo firewall-cmd --add-service=http - sudo firewall-cmd --add-service=https - sudo firewall-cmd --runtime-to-permanent + sudo firewall-cmd --add-service=http + sudo firewall-cmd --add-service=https + sudo firewall-cmd --runtime-to-permanent 8. If you have a running **iptables firewall**, for a basic rule set, add HTTP and HTTPS access: @@ -140,32 +131,24 @@ This section describes how to create your **/etc/ssl/private directory**, used f The following list describes the elements in the command above: * **openssl** - The basic command line tool used for creating and managing OpenSSL certificates, keys, and other files. - - :: + * **req** - A subcommand for using the X.509 **Certificate Signing Request (CSR)** management. A public key infrastructure standard, SSL and TLS adhere X.509 key and certificate management regulations. - :: * **-x509** - Used for modifying the previous subcommand by overriding the default functionality of generating a certificate signing request with making a self-signed certificate. - :: * **-nodes** - Sets **OpenSSL** to skip the option of securing our certificate with a passphrase, letting NGINX read the file without user intervention when the server is activated. If you don't use **-nodes** you must enter your passphrase after every restart. - :: - * **-days 365** - Sets the certificate's validation duration to one year. - :: * **-newkey rsa:2048** - Simultaneously generates a new certificate and new key. Because the key required to sign the certificate was not created in the previous step, it must be created along with the certificate. The **rsa:2048** generates an RSA 2048 bits long. - :: * **-keyout** - Determines the location of the generated private key file. - :: * **-out** - Determines the location of the certificate. @@ -189,7 +172,7 @@ This section describes how to create your **/etc/ssl/private directory**, used f Both files you create are stored in their own subdirectories of the **/etc/ssl** directory. - Although SQream uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. + Although SQreamDB uses OpenSSL, in addition we recommend creating a strong **Diffie-Hellman** group, used for negotiating **Perfect Forward Secrecy** with clients. 4. Create a strong Diffie-Hellman group: @@ -204,9 +187,9 @@ Configuring NGINX to use SSL After creating your SSL certificate, you must configure NGINX to use SSL. -The default CentOS NGINX configuration is fairly unstructured, with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. +The default RHEL NGINX configuration is fairly unstructured, with the default HTTP server block located in the main configuration file. NGINX checks for files ending in **.conf** in the **/etc/nginx/conf.d** directory for additional configuration. -SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a server block. This block serves content using the certificate files we generated. In addition, the default server block can be optionally configured to redirect HTTP requests to HTTPS. +SQreamDB creates a new file in the **/etc/nginx/conf.d** directory to configure a server block. This block serves content using the certificate files we generated. In addition, the default server block can be optionally configured to redirect HTTP requests to HTTPS. .. note:: The example on this page uses the IP address **127.0.0.1**, which you should replace with your machine's IP address. @@ -222,11 +205,9 @@ SQream creates a new file in the **/etc/nginx/conf.d** directory to configure a 1. Listen to **port 443**, which is the TLS/SSL default port. - :: 2. Set the ``server_name`` to the server’s domain name or IP address you used as the Common Name when generating your certificate. - - :: + 3. Use the ``ssl_certificate``, ``ssl_certificate_key``, and ``ssl_dhparam`` directives to set the location of the SSL files you generated, as shown in the **/etc/nginx/conf.d/ssl.conf** file below: @@ -386,9 +367,6 @@ After activating your NGINX configuration, you must verify that NGINX is running Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled) Active: active (running) since Fri 2017-01-06 17:27:50 UTC; 28s ago - . . . - - Jan 06 17:27:50 centos-512mb-nyc3-01 systemd[1]: Started The nginx HTTP and reverse proxy server. 2. Run the following command: From 0f723ff609327581014f96edba46e1603ddb47ed Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:53:25 +0300 Subject: [PATCH 1417/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 60fb7262a..f7d8d9536 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -82,10 +82,10 @@ If any doubt arises, consult the documentation for your server or your hardware - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. Installing the Operating System -================================ +=============================== Before You Begin -------------------- +---------------- * Your system must have at least 200 gigabytes of free space on the root ``/`` mount. @@ -93,12 +93,12 @@ Before You Begin * Once the BIOS settings have been set, you must install the operating system. -* A typical SQreamDB installation requires RHEL7.9/CentOS 7.9 or RHEL8.X (RHEL8.8 recommended) +* A typical SQreamDB installation requires RHEL7.9 or RHEL8.X (RHEL8.8 recommended) * Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. Installation ----------------- +------------ #. Select a language (English recommended). #. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. @@ -127,12 +127,12 @@ Installation The OS shell is booted up. Configuring the Operating System -================================== +================================ When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Creating a ``sqream`` User ----------------------------- +-------------------------- **The sqream user must have the same UID and GID across all servers in your cluster.** @@ -744,7 +744,7 @@ Before You Begin gcc --version -3. If ``gcc`` has not been installed, install it for RHEL or CentOS: +3. If ``gcc`` has not been installed, install it for RHEL: .. code-block:: console @@ -753,7 +753,7 @@ Before You Begin Updating the Kernel Headers --------------------------- -1. Update the kernel headers on RHEL or CentOS: +1. Update the kernel headers on RHEL: .. code-block:: console @@ -838,12 +838,6 @@ Installing the CUDA driver from the Repository is the recommended installation m .. code-block:: console sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - - * For CentOS: - - .. code-block:: console - - sudo yum install epel-release 2. (Optional) Install the CUDA dependencies from the ``epel`` repository: From b46a9a7b0faf51bd29255312502670123b4328a4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:57:28 +0300 Subject: [PATCH 1418/1892] Update installing_studio_on_stand_alone_server.rst --- .../installing_studio_on_stand_alone_server.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/installation_guides/installing_studio_on_stand_alone_server.rst b/installation_guides/installing_studio_on_stand_alone_server.rst index a18122ef1..1e069cbdc 100644 --- a/installation_guides/installing_studio_on_stand_alone_server.rst +++ b/installation_guides/installing_studio_on_stand_alone_server.rst @@ -1,7 +1,5 @@ .. _installing_studio_on_stand_alone_server: -.. _install_studio_top: - ***************************************** Installing Studio on a Stand-Alone Server ***************************************** @@ -20,9 +18,9 @@ It is essential you have :ref:`NodeJS 16 installed <installing_nodejs>`. Installing Studio ================= -1. Copy the SQream Studio package from SQream Artifactory into the target server. +1. Copy the SQreamDB Studio package from SQreamDB Artifactory into the target server. - For access to the Sqream Studio package, contact `SQream Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. + For access to the SQreamDB Studio package, contact `SQreamDB Support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. 2. Extract the package: @@ -38,7 +36,7 @@ Installing Studio .. _add_parameter: -4. Build the configuration file to set up Sqream Studio. You can use IP address **127.0.0.1** on a single server. +4. Build the configuration file to set up SQreamDB Studio. You can use IP address **127.0.0.1** on a single server. .. code-block:: console @@ -84,7 +82,7 @@ Installing Studio Note that for the ``host`` value, it is essential that you use the IP address of your SQreamDB machine. -6. If you have installed Studio on a server where SQream is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: +6. If you have installed Studio on a server where SQreamDB is already installed, move the **sqream-admin-config.json** file to **/etc/sqream/**: .. code-block:: console @@ -151,7 +149,7 @@ The following output is displayed: a. Access Studio from your browser (``http://<IP_Address>:8080``) - b. Log in to SQream + b. Log in to SQreamDB 6. Save the configuration to run on boot: @@ -190,7 +188,7 @@ If port 8080 is blocked by the server firewall, you can unblock it by running th Maintaining Studio with the Process Manager (PM2) ------------------------------------------------- -SQream uses the **Process Manager (PM2)** to maintain Studio. +SQreamDB uses the **Process Manager (PM2)** to maintain Studio. You can use PM2 to do one of the following: From 25791b2582573950683026e329afec9710328692 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:57:54 +0300 Subject: [PATCH 1419/1892] Update install_configure_odbc_linux.rst --- .../odbc/install_configure_odbc_linux.rst | 26 +++++++------------ 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst index dedfdfe0e..2a10908bb 100644 --- a/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst +++ b/connecting_to_sqream/client_drivers/odbc/install_configure_odbc_linux.rst @@ -1,8 +1,8 @@ .. _install_odbc_linux: -**************************************** +*********************************** Install and configure ODBC on Linux -**************************************** +*********************************** .. toctree:: :maxdepth: 1 @@ -24,9 +24,9 @@ Prerequisites .. _unixODBC: unixODBC ------------- +-------- -The ODBC driver requires a driver manager to manage the DSNs. SQream DB's driver is built for unixODBC. +The ODBC driver requires a driver manager to manage the DSNs. SQreamDB's driver is built for unixODBC. Verify unixODBC is installed by running: @@ -48,21 +48,13 @@ Take note of the location of ``.odbc.ini`` and ``.odbcinst.ini``. In this case, :local: :depth: 1 -Install unixODBC on RHEL 7 / CentOS 7 -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Install unixODBC on RHEL +^^^^^^^^^^^^^^^^^^^^^^^^ .. code-block:: console $ yum install -y unixODBC unixODBC-devel -Install unixODBC on Ubuntu -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. code-block:: console - - $ sudo apt-get install odbcinst1debian2 libodbc1 odbcinst unixodbc - - Install the ODBC driver with a script ======================================= @@ -218,10 +210,10 @@ ODBC DSN Parameters - Specifices :ref:`service queue<workload_manager>` to use. For example, ``Service="etl"``. Leave blank (``Service=""``) for default service ``sqream``. * - Server - None - - Hostname of the SQream DB worker. For example, ``Server="127.0.0.1"`` or ``Server="sqream.mynetwork.co"`` + - Hostname of the SQreamDB worker. For example, ``Server="127.0.0.1"`` or ``Server="sqream.mynetwork.co"`` * - Port - None - - TCP port of the SQream DB worker. For example, ``Port="5000"`` or ``Port="3108"`` for the load balancer + - TCP port of the SQreamDB worker. For example, ``Port="5000"`` or ``Port="3108"`` for the load balancer * - Cluster - ``false`` - Connect via load balancer (use only if exists, and check port). For example, ``Cluster=true`` @@ -236,7 +228,7 @@ ODBC DSN Parameters - Location where the driver was installed. For example, ``ErrorMessagePath=/home/rhendricks/sqream_odbc64/ErrorMessages``. * - LogLevel - 0 - - Set to 0-6 for logging. Use this setting when instructed to by SQream Support. For example, ``LogLevel=1`` + - Set to 0-6 for logging. Use this setting when instructed to by SQreamDB Support. For example, ``LogLevel=1`` .. hlist:: :columns: 3 From 450fbe0cb675245c097fba4d5363cc4ad76a9d28 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:58:25 +0300 Subject: [PATCH 1420/1892] Update installing_monit.rst --- installation_guides/installing_monit.rst | 143 +++-------------------- 1 file changed, 18 insertions(+), 125 deletions(-) diff --git a/installation_guides/installing_monit.rst b/installation_guides/installing_monit.rst index ab49164f6..7f2568e25 100644 --- a/installation_guides/installing_monit.rst +++ b/installation_guides/installing_monit.rst @@ -1,79 +1,40 @@ .. _installing_monit: -********************************************* +**************** Installing Monit -********************************************* - -Getting Started -============================== - -Before installing SQream with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations <recommended_pre-installation_configurations>`. - -The procedures in the **Installing Monit** guide must be performed on each SQream cluster node. - -.. _back_to_top: - -Overview -============================== - +**************** Monit is a free open source supervision utility for managing and monitoring Unix and Linux. Monit lets you view system status directly from the command line or from a native HTTP web server. Monit can be used to conduct automatic maintenance and repair, such as executing meaningful causal actions in error situations. -SQream uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. +SQreamDB uses Monit as a watchdog utility, but you can use any other utility that provides the same or similar functionality. The **Installing Monit** procedures describes how to install, configure, and start Monit. You can install Monit in one of the following ways: -* :ref:`Installing Monit on CentOS <installing-monit-on-centos>` -* :ref:`Installing Monit on CentOS offline <installing-monit-on-centos-offline>` -* :ref:`Installing Monit on Ubuntu <installing-monit-on-ubuntu>` -* :ref:`Installing Monit on Ubuntu offline <installing-monit-on-ubuntu-offline>` - - - - - - - -.. _installing-monit-on-centos: - -Installing Monit on CentOS: ------------------------------------- +Getting Started +=============== +Before installing SQreamDB with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations <recommended_pre-installation_configurations>`. +The procedures in the **Installing Monit** guide must be performed on each SQreamDB cluster node. -**To install Monit on CentOS:** +Installing Monit on RHEL: +========================= -1. Install Monit as a superuser on CentOS: +1. Install Monit as a superuser: .. code-block:: console $ sudo yum install monit - -.. _installing-monit-on-centos-offline: - - - -Installing Monit on CentOS Offline: ------------------------------------- - - -Installing Monit on CentOS offline can be done in either of the following ways: - -* :ref:`Building Monit from Source Code <building_monit_from_source_code>` -* :ref:`Building Monit from Pre-Built Binaries <building_monit_from_pre_built_binaries>` - - - - .. _building_monit_from_source_code: -Building Monit from Source Code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +Building Monit +============== +Building Monit from Source Code +------------------------------- **To build Monit from source code:** @@ -113,22 +74,17 @@ The following are the default storage directories: .. _**Comment - I took this line directly from the external online documentation. Is the "prefix option" referrin gto the "--help" in Step 3? URL: https://mmonit.com/wiki/Monit/Installation** -6. **Optional** - Create an RPM package for CentOS directly from the source code: +6. **Optional** - Create an RPM package for RHEL directly from the source code: .. code-block:: console $ rpmbuild -tb monit-x.y.z.tar.gz -.. - _**Comment - Is this an optional or mandatory step?** - - - .. _building_monit_from_pre_built_binaries: Building Monit from Pre-Built Binaries -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------------------- **To build Monit from pre-built binaries:** @@ -161,72 +117,9 @@ Building Monit from Pre-Built Binaries For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries<https://mmonit.com/monit/#download>`. -:ref:`Back to top <back_to_top>` - - - -.. _installing-monit-on-ubuntu: - - - -Installing Monit on Ubuntu: ------------------------------------- - - -**To install Monit on Ubuntu:** - -1. Install Monit as a superuser on Ubuntu: - - .. code-block:: console - - $ sudo apt-get install monit - -:ref:`Back to top <back_to_top>` - - - -.. _installing-monit-on-ubuntu-offline: - - -Installing Monit on Ubuntu Offline: -------------------------------------- - - -You can install Monit on Ubuntu when you do not have an internet connection. - -**To install Monit on Ubuntu offline:** - -1. Compress the required file: - - .. code-block:: console - - $ tar zxvf monit-<x.y.z>-linux-x64.tar.gz - - **NOTICE:** *<x.y.z>* denotes the version number. - -2. Navigate to the directory where you want to save the file: - - .. code-block:: console - - $ cd monit-x.y.z - -3. Copy the **bin/monit** directory into the **/usr/local/bin/** directory: - - .. code-block:: console - - $ cp bin/monit /usr/local/bin/ - -4. Copy the **conf/monitrc** directory into the **/etc/** directory: - - .. code-block:: console - - $ cp conf/monitrc /etc/ - -:ref:`Back to top <back_to_top>` - Configuring Monit -==================================== +================= When the installation is complete, you can configure Monit. You configure Monit by modifying the Monit configuration file, called **monitrc**. This file contains blocks for each service that you want to monitor. @@ -290,7 +183,7 @@ For servers that don't run the **metadataserver** and **serverpicker** commands, $ sudo ln -s /etc/monit.d/monitrc monitrc Starting Monit -==================================== +============== After configuring Monit, you can start it. From 2d5389be6eb41ee4afea513858aff4263a7c2273 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:58:52 +0300 Subject: [PATCH 1421/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index c76b5b6c4..27d94856b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -9,7 +9,7 @@ Release Notes * * -:ref:`Version 4.6 - February 19, 2024<4.6>` +:ref:`Version 4.6 - XXXXX XX, 2024<4.6>` * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. * Safely cast data types with the new :ref:`IsCastable<is_castable>` function. From f98dae9bdb847d616fa18702fe28d345c9836e5b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:59:18 +0300 Subject: [PATCH 1422/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 2ce7c9db3..6aefc4600 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -12,7 +12,7 @@ ODBC install_configure_odbc_windows install_configure_odbc_linux -SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. +SQreamDB has an ODBC driver to connect to SQreamDB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. .. list-table:: :widths: auto @@ -31,18 +31,15 @@ SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to in * Windows Server 2019 * - Linux - - * Red Hat Enterprise Linux (RHEL) 7 - * CentOS 7 - * Ubuntu 16.04 - * Ubuntu 18.04 + - * Red Hat Enterprise Linux (RHEL) 7/8 -Other distributions may also work, but are not officially supported by SQream. +Other distributions may also work, but are not officially supported by SQreamDB. Getting the ODBC driver ======================= -The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQream account manager to get the driver. +The SQreamDB ODBC driver is distributed by your SQreamDB account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQreamDB Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQreamDB account manager to get the driver. The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: From dc66c64a8d5b29a0bc5d9c03197bbb4e685385f9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:59:58 +0300 Subject: [PATCH 1423/1892] Update sqream_sql.rst --- reference/cli/sqream_sql.rst | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index cddedcb08..fd96eef2b 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -1,12 +1,12 @@ .. _sqream_sql_cli_reference: ************************ -Linux Sqream SQL +Sqream SQL CLI Reference ************************ SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. -This page serves as a reference for the options and parameters. Learn more about using SQream DB SQL with the CLI by visiting the :ref:`first_steps` tutorial. +This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. .. contents:: In this topic: :local: @@ -15,16 +15,23 @@ Installing Sqream SQL ===================== If you have a SQreamDB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQreamDB installation, under the name ``sqream``. + + + +.. versionchanged:: 2020.1 + As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. + To run ``sqream sql`` on any other Linux host: +#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. #. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` #. Start the client: .. code-block:: psql - cd sqream-sql-<xxxx.x.x>_stable.x86_64 - ./sqream sql --port=5000 --username=<jdoe> --databasename=master + $ cd sqream-sql-v2020.1.1_stable.x86_64 + $ ./sqream sql --port=5000 --username=jdoe --databasename=master Password: Interactive client mode @@ -38,19 +45,8 @@ Troubleshooting Sqream SQL Installation Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. - -* Ubuntu: - - #. Install ``libtinfo``: - ``$ sudo apt-get install -y libtinfo`` - #. Depending on your Ubuntu version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/lib/x86_64-linux-gnu/libtinfo.so.6.2``: - - ``$ sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.6.2 /lib/x86_64-linux-gnu/libtinfo.so.5`` - -* CentOS / RHEL: +* RHEL: #. Install ``ncurses``: @@ -61,8 +57,8 @@ Solving this error requires installing the ncruses or libtinfo libraries, depend ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` -Using Sqream SQL -================ +Using SQreamDB SQL +================== By default, sqream sql runs in interactive mode. You can issue commands or SQL statements. @@ -245,7 +241,7 @@ Executing SQL Statements from the Command Line 1 row time: 0.095941s - +.. _controlling_output: Controlling the Client Output ----------------------------- @@ -390,7 +386,7 @@ Command Line Arguments .. tip:: Run ``$ sqream sql --help`` to see a full list of arguments - +.. _supported_record_delimiters: Supported Record Delimiters ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From c383f0c26679b6f0479009a9a21bb3421a9072a3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:00:33 +0300 Subject: [PATCH 1424/1892] Update index.rst --- .../client_drivers/python/index.rst | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 436dbd469..ddafd8d75 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -4,7 +4,7 @@ Python (pysqream) ***************** -The current Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQream DB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. +The current Pysqream connector supports Python version 3.9 and newer. It includes a set of packages that allows Python programs to connect to SQreamDB. The base ``pysqream`` package conforms to Python DB-API specifications `PEP-249 <https://www.python.org/dev/peps/pep-0249/>`_. ``pysqream`` is a pure Python connector that can be installed with ``pip`` on any operating system, including Linux, Windows, and macOS. ``pysqream-sqlalchemy`` is a SQLAlchemy dialect for ``pysqream``. @@ -66,21 +66,14 @@ To verify that you have the latest version, run the following command: OpenSSL for Linux ~~~~~~~~~~~~~~~~~ -The Python connector relies on OpenSSL for secure connections to SQream DB. Some distributions of Python do not include OpenSSL. +The Python connector relies on OpenSSL for secure connections to SQreamDB. Some distributions of Python do not include OpenSSL. -To install OpenSSL on RHEL/CentOS, run the following command: +To install OpenSSL on RHEL, run the following command: .. code-block:: console $ sudo yum install -y libffi-devel openssl-devel -To install OpenSSL on Ubuntu, run the following command: - - .. code-block:: console - - $ sudo apt-get install libssl-dev libffi-dev -y - - Installing via PIP with an internet connection ---------------------------------------------- @@ -99,7 +92,7 @@ To install ``pysqream`` and ``pysqream-sqlalchemy`` with the ``--user`` flag, ru Installing via PIP without an internet connection ------------------------------------------------- -#. To get the ``.whl`` package file, contact you SQream support representative. +#. To get the ``.whl`` package file, contact you SQreamDB support representative. #. Run the following command: @@ -321,9 +314,9 @@ You can fetch a list of column names by iterating over the ``description`` list: Loading Data into a Table ------------------------- -This example shows how to load 10,000 rows of dummy data to an instance of SQream. +This example shows how to load 10,000 rows of dummy data to an instance of SQreamDB. -**To load data 10,000 rows of dummy data to an instance of SQream:** +**To load data 10,000 rows of dummy data to an instance of SQreamDB:** 1. Run the following: @@ -443,7 +436,7 @@ This section shows how to use the ORM to create and populate tables from Python sa.Column('salary', sa.Float) ) - The ``create_all()`` function uses the SQream engine object. + The ``create_all()`` function uses the SQreamDB engine object. 4. Create all the defined table objects: From fe587bdc0cbee799721eeab992eb7cf84f40a25e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:00:46 +0300 Subject: [PATCH 1425/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 6469fe370..0ac23e286 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -36,7 +36,7 @@ New Features and Enhancements ► REHL 8.x is now officially supported. -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes flag<current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. From 83b16f70f06a933678ada39cd1adb9368cf57ef3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:42:52 +0300 Subject: [PATCH 1426/1892] Update current_method_configuration_levels.rst --- .../current_method_configuration_levels.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 5c627b2ef..e2d8b9bc8 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -7,10 +7,10 @@ Cluster and Session When configuring your SQreamDB environment, you have the option to use flags that apply to either the entire cluster or a specific session. Cluster configuration involve metadata and is persistent. Persistent modifications refer to changes made to a system or component that are saved and retained even after the system is restarted or shut down, allowing the modifications to persist over time. Session flags only apply to a specific session and are not persistent. Changes made using session flags are not visible to other users, and once the session ends, the flags return to their default values. Setting the flags -================== +================= Syntax -------- +------ You may set both cluster and session flags using the following syntax on SQreamDB Acceleration Studio and Console: @@ -27,7 +27,7 @@ Session flag syntax: SET <flagName> Configuration file -------------------- +------------------ You may set session flags within your :ref:`Legacy Configuration File<modifying_your_configuration_using_a_legacy_configuration_file>`. From 1fd2b49d63464ed309c71afe657890e397bffc5e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:07:57 +0300 Subject: [PATCH 1427/1892] Delete examining_logs.rst --- troubleshooting/examining_logs.rst | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 troubleshooting/examining_logs.rst diff --git a/troubleshooting/examining_logs.rst b/troubleshooting/examining_logs.rst deleted file mode 100644 index 9b5a5fb79..000000000 --- a/troubleshooting/examining_logs.rst +++ /dev/null @@ -1,6 +0,0 @@ -.. _examining_logs: - -*********************** -Examining Logs -*********************** -See the :ref:`collecting_logs` section of the :ref:`information_for_support` guide for information about collecting logs for support. \ No newline at end of file From 0a591dffcc8edf7182814e3afe62e788e0b94db7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:04:11 +0300 Subject: [PATCH 1428/1892] Update index.rst --- reference/sql/sql_syntax/index.rst | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 77586250b..1f706db1b 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -34,7 +34,25 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Metalanguage scripting enhances your interaction with SQL by providing conventions which allow dynamic generation, management, and automation of SQL code. - +.. toctree:: + :caption: + :glob: + :maxdepth: 6 + :titlesonly: + :hidden: + + keywords_and_identifiers + literals + scalar_expressions + cross_database_query + joins + common_table_expressions + window_functions + subqueries + null_handling + sqream_scripting + + From bec51a67be43c4c4c49117cbcfbdf4350d160075 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:23:46 +0300 Subject: [PATCH 1429/1892] Update current_method_configuration_levels.rst --- configuration_guides/current_method_configuration_levels.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index e2d8b9bc8..3f3f85c28 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -325,6 +325,6 @@ Flag List * - ``QueryTimeoutMinutes`` - Anyone - Session - - The flag is intended to identify and address situations where queries have been in the queue for extended durations, suggesting potential irrelevance or a need for unavailable resources. If a query surpasses the defined time limit, which ranges from ``1`` to ``4320`` minutes (72 hours), the system automatically terminates the query. + - Terminates queries that have exceeded a predefined execution time limit, ranging from ``1`` to ``4,320`` minutes (72 hours). - integer - ``0`` (no query timeout) From 6678b581ccb370acd36da84978871ef5c0075407 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:35:36 +0300 Subject: [PATCH 1430/1892] Delete querying_data.rst --- getting_started/querying_data.rst | 53 ------------------------------- 1 file changed, 53 deletions(-) delete mode 100644 getting_started/querying_data.rst diff --git a/getting_started/querying_data.rst b/getting_started/querying_data.rst deleted file mode 100644 index 6ac28db4c..000000000 --- a/getting_started/querying_data.rst +++ /dev/null @@ -1,53 +0,0 @@ -.. _querying_data: - -**************************** -Querying Data -**************************** - -One of the most basic operations when using SQream is querying data. - -To begin familiarizing yourself with querying data, you can create the following table using the ``CREATE TABLE`` statement: - -.. code-block:: postgres - - CREATE TABLE nba - ( - Name text(40), - Team text(40), - Number tinyint, - Position text(2), - Age tinyint, - Height text(4), - Weight real, - College text(40), - Salary float - ); - - -You can down download the above (:download:`nba.csv table </_static/samples/nba.csv>`) if needed, shown below: - -.. csv-table:: nba.csv - :file: nba-t10.csv - :widths: auto - :header-rows: 1 - -The above query gets the following from the table above, limited to showing the first ten results: - -* Name -* Team name -* Age - -.. code-block:: psql - - SELECT Name, Team, Age FROM nba LIMIT 10; - - Avery Bradley,Boston Celtics,25 - Jae Crowder,Boston Celtics,25 - John Holland,Boston Celtics,27 - R.J. Hunter,Boston Celtics,22 - Jonas Jerebko,Boston Celtics,29 - Amir Johnson,Boston Celtics,29 - Jordan Mickey,Boston Celtics,21 - Kelly Olynyk,Boston Celtics,25 - Terry Rozier,Boston Celtics,22 - Marcus Smart,Boston Celtics,22 \ No newline at end of file From c8ed651ca1df8deff2837d25291b04776a45503b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:05:06 +0300 Subject: [PATCH 1431/1892] RCA --- .../current_method_flag_types.rst | 7 ++- operational_guides/index.rst | 1 + operational_guides/logging.rst | 6 ++- operational_guides/root_cause_analysis.rst | 28 ++++++++++ reference/sql/sql_statements/index.rst | 4 ++ .../export_open_snapshots.rst | 38 ++++++++++++++ .../utility_commands/get_open_snapshots.rst | 52 +++++++++++++++++++ .../utility_commands/show_locks.rst | 45 ++++++++-------- 8 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 operational_guides/root_cause_analysis.rst create mode 100644 reference/sql/sql_statements/utility_commands/export_open_snapshots.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_open_snapshots.rst diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index d5b1987c5..d0b72b6a2 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -62,7 +62,12 @@ It is worth noting that the worker configuration file is not subject to frequent - SUPERUSER - Activates the machineIP (``TRUE``). Setting this flag to ``FALSE`` ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - boolean - - ``FALSE`` + - ``FALSE`` + * - ``logFormat`` + - SUPERUSER + - Determines the file format of the log files. Format may by ``csv``, ``json``, or both (all logs will be written saved both as ``csv`` and ``json`` files) + - string + - ``csv`` diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 82df793f0..eb736d827 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -17,6 +17,7 @@ This section summarizes the following operational guides: creating_or_cloning_a_storage_cluster external_data foreign_tables + root_cause_analysis delete_guide logging query_split diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index e22a89632..c607078ec 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -26,7 +26,9 @@ The worker logs contain information messages, warnings, and errors pertaining to Log Structure and Contents -------------------------- -The log is a CSV, with several fields. +By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. + +For effective :ref:`Root Cause Analysis (RCA)<root_cause_analysis>`, it's essential that logs are saved in ``JSON`` format, as RCA does not support ``CSV`` files. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. .. list-table:: Log fields :widths: auto @@ -348,7 +350,7 @@ Troubleshooting with Logs Loading Logs with Foreign Tables -------------------------------- -Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`external_tables` concept through SQream DB. +Assuming logs are stored at ``/home/rhendricks/sqream_storage/logs/``, a database administrator can access the logs using the :ref:`foreign_tables` concept through SQreamDB. .. code-block:: postgres diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/root_cause_analysis.rst new file mode 100644 index 000000000..40fd29ba0 --- /dev/null +++ b/operational_guides/root_cause_analysis.rst @@ -0,0 +1,28 @@ +.. _root_cause_analysis: + +******************* +Root Cause Analysis +******************* + +The Root Cause Analysis (RCA) service enhances observability, enabling shorter investigation times and facilitating both high-level and detailed drill-downs. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following configured: + +* Log files must be saved as ``JSON`` files + +Usage Notes +=========== + +By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. + +Utility Functions +================= + +The RCA executes the :ref:`export_open_snapshots` and :ref:`get_open_snapshots` utility functions. \ No newline at end of file diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 033aecd1c..b368e8399 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -121,6 +121,8 @@ The following table shows the Utility commands: - Executes a previously saved query * - :ref:`EXPLAIN<explain>` - Returns a static query plan, which can be used to debug query plans + * - :ref:`export_open_snapshots` + - Lists and saves information about all currently open snapshots to a specified file * - :ref:`GET DDL<get_ddl>` - View the ``CREATE TABLE`` statement for a table * - :ref:`GET FUNCTION DDL<get_function_ddl>` @@ -129,6 +131,8 @@ The following table shows the Utility commands: - View a user's license information * - :ref:`GPU METRICS<select_gpu_metrics>` - Monitor license quota usage by reviewing monthly or daily GPU usage + * - :ref:`get_open_snapshots` + - Lists information about all currently open snapshots * - :ref:`GET TOTAL CHUNKS SIZE<get_total_chunks_size>` - Returns the total size of all data chunks saved in the system * - :ref:`GET VIEW DDL<get_view_ddl>` diff --git a/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst b/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst new file mode 100644 index 000000000..368b6f233 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst @@ -0,0 +1,38 @@ +.. _export_open_snapshots: + +********************* +EXPORT OPEN SNAPSHOTS +********************* + +The ``EXPORT_OPEN_SNAPSHOTS`` utility function lists and saves information about all currently open snapshots to a specified file. + +Syntax +====== + +.. code-block:: postgres + + SELECT EXPORT_OPEN_SNAPSHOTS('<file_path.txt>') + +Parameter +========= + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``file_path.txt`` + - The path to where you wish to export information about currently open snapshots + +Example +======= + +.. code-block:: postgres + + SELECT EXPORT_OPEN_SNAPSHOTS('./a.txt'); + +Permissions +=========== + +This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst new file mode 100644 index 000000000..6e79345a2 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst @@ -0,0 +1,52 @@ +.. _get_open_snapshots: + +****************** +GET_OPEN_SNAPSHOTS +****************** + +The ``GET_OPEN_SNAPSHOTS`` utility function lists information about all currently open snapshots. + +Syntax +====== + +.. code-block:: postgres + + SELECT GET_OPEN_SNAPSHOTS() + +Output +====== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - + * - ``reason`` + - + * - ``open_time`` + - + * - ``database_version`` + - + * - ``snapshot_id`` + - + * - ``statement_id`` + - + * - ``current_time`` + - + * - ``is_statement_active`` + - + +Example +======= + +.. code-block:: postgres + + SELECT GET_OPEN_SNAPSHOTS(); + +Permissions +=========== + +This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index bc814c9dc..15eb50525 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -1,8 +1,8 @@ .. _show_locks: -******************** -SHOW_LOCKS -******************** +********** +SHOW LOCKS +********** ``SHOW_LOCKS`` returns a list of locks from across the cluster. @@ -13,18 +13,19 @@ Syntax .. code-block:: postgres - show_locks_statement ::= SELECT SHOW_LOCKS() -Returns -========= +Output +====== This function returns a list of active locks. If no locks are active in the cluster, the result set will be empty. -.. list-table:: Result columns +.. list-table:: :widths: auto :header-rows: 1 - + + * - Parameter + - Description * - ``stmt_id`` - Statement ID that caused the lock. * - ``stmt_string`` @@ -43,31 +44,29 @@ This function returns a list of active locks. If no locks are active in the clus - Timestamp the statement started * - ``lock_start_time`` - Timestamp the lock was obtained + * - ``is_statement_active`` + - Is the statement causing the lock running or not + * - ``is_snapshot_active`` + - Is the snapshot of the metadata keys, created by the statement, still active or not Examples -=========== - -Using ``SHOW_LOCKS`` to see active locks ---------------------------------------------------- - -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE``). Thus, SQreamDB applies locks during the table creation process to prevent the table from being altered during it's creation. - +======== .. code-block:: postgres SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 +Output: + +.. code-block:: console + + statement id |statement string |username |server |port |locked object |lock mode |statement start time |lock start time |is_statement_active |is_snapshot_active + -------------+----------------------------------+---------+---------+-----+---------------+----------+---------------------+-------------------+--------------------+------------------ + 2 |create or replace table t (x int);|sqream |127.0.0.1|5000 |database$master|Inclusive |04-07-2024 15:07:02 |2024-07-04 15:07:02|1 |1 Permissions -============= +=========== This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file From 85aa3994f188f8db3f6d3a00d13c50a1a9667c4a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:33:08 +0300 Subject: [PATCH 1432/1892] RCA --- .../current_method_modification_methods.rst | 1 + operational_guides/root_cause_analysis.rst | 4 ++++ .../utility_commands/get_open_snapshots.rst | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index 4442c4dce..cf413a117 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -32,6 +32,7 @@ The following is an example of the default worker configuration file: "portSsl": 5100, "initialSubscribedServices": "sqream", "useConfigIP": true + "logFormat": "csv","json" } You can access the legacy configuration file from the ``legacyConfigFilePath`` parameter shown above. If all (or most) of your workers require the same flag settings, you can set the ``legacyConfigFilePath`` attribute to the same legacy file. diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/root_cause_analysis.rst index 40fd29ba0..cea101442 100644 --- a/operational_guides/root_cause_analysis.rst +++ b/operational_guides/root_cause_analysis.rst @@ -22,6 +22,10 @@ Usage Notes By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. +.. note: + + The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file + Utility Functions ================= diff --git a/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst index 6e79345a2..32de6c151 100644 --- a/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst +++ b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst @@ -46,6 +46,15 @@ Example SELECT GET_OPEN_SNAPSHOTS(); +Output: + +.. code-block:: console + + database_name |reason |open_time |database_version |snapshot_id |statement_id |current_time |is_statement_active + --------------+----------------+-------------------+-----------------+------------+-------------+-------------------+------------------- + master |on_new_statement|2024-07-04 17:16:56|1 |30898 |0 |2024-07-04 17:16:57|1 + + Permissions =========== From 7af975541989bbad0f8e263ba5237d9994c620ad Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 12:16:35 +0300 Subject: [PATCH 1433/1892] RCA --- .DS_Store | Bin 6148 -> 10244 bytes operational_guides/root_cause_analysis.rst | 113 ++++++++++++++++++++- 2 files changed, 111 insertions(+), 2 deletions(-) diff --git a/.DS_Store b/.DS_Store index 536e8fa46ab58c197597811bcf9191ae1dacaef7..a3efb71446bef3ff6221a3cb3a46bb5db103c31e 100644 GIT binary patch literal 10244 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 AYXATM delta 192 zcmZn(XfcprU|?W$DortDU=RQ@Ie-{MGjUEV6q~50D9Q|y2a9Dgq%)K<6fq<+lx!?q z&IpzfVMu1kXUJnnV}Qy|{w%3J`Gk!8WF?_SVIv&{BV)5#9ffK`b3;oV1#=6d$=ifX zC!dm$-K;A6h-qWPO~%FS92|lmOMpOt8%Vf<EZ<o8oq009iX+H%AnRE`G!w*mV6n~d HJad=<g})<K diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/root_cause_analysis.rst index cea101442..d88c17bfc 100644 --- a/operational_guides/root_cause_analysis.rst +++ b/operational_guides/root_cause_analysis.rst @@ -13,9 +13,9 @@ The Root Cause Analysis (RCA) service enhances observability, enabling shorter i Before You Begin ================ -It is essential that you have the following configured: +It is essential that you follow these prerequisites: -* Log files must be saved as ``JSON`` files +* Log files must be saved as ``JSON`` files Usage Notes =========== @@ -26,6 +26,115 @@ By default, logs are saved as ``CSV`` files. To configure your log files to be s The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file +Installation +============ + +All RCA-related installations are on a stand-alone installations. + +Grafana +------- + +Grafana is an open-source analytics and monitoring platform that visualizes data and is used to create dashboards that display real-time and historical data. + +Manual Execution +~~~~~~~~~~~~~~~~ + +#. Download Grafana. + +#. Start the Grafana server: + + .. code-block:: console + + /usr/share/grafana/bin/grafana server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=rpm cfg:default.paths.logs=/var/log/grafana cfg:default.paths.data=/var/lib/grafana cfg:default.paths.plugins=/var/lib/grafana/plugins cfg:default.paths.provisioning=/etc/grafana/provisioning + +Setting Linux Service +~~~~~~~~~~~~~~~~~~~~~ + +#. Create Service: + + .. code-block:: console + +#. Start the Grafa service: + + .. code-block:: console + + sudo systemctl <start / stop / restart> grafana-server.service + +#. To view logs: + + .. code-block:: console + + journalctl -xe + +Prometheus +---------- + +Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. Prometheus can be used to scrape and store metrics, enabling real-time monitoring, alerting, and analysis of performance and health. + +#. Download Prometheus. + +#. Set the YML path: + + .. code-block:: console + + PROMETHEUS_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/prometheus.yml + +#. Start Prometheus server: + + .. code-block:: console + + sudo /usr/local/bin/prometheus --config.file <PROMETHEUS_YML_PATH> --storage.tsdb.path /var/lib/prometheus/ --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries &> prometheus.out & + +Loki and Promtail +----------------- + +Loki is a log aggregation system designed to store and query logs, while Promtail is an agent that collects logs and forwards them to Loki. + +#. Download Loki and Promtail to ``<LOKI_PROJECT_PATH>``. + +#. Set the Loki YML path: + + .. code-block:: console + + LOKI_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/loki-local-config.yaml + +#. Set the Promtail YML path: + + .. code-block:: console + + PROMTAIL_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/promtail-local-config.yml + +#. Start Loki server: + + .. code-block:: console + + sudo <LOKI_PROJECT_PATH>/loki-linux-amd64 -config.file=<LOKI_YML_PATH> &> ~/loki.out & + +#. Start Promtail server: + + .. code-block:: console + + sudo <LOKI_PROJECT_PATH>/promtail-linux-amd64 -config.file=<PROMTAIL_YML_PATH> &> ~/promtail.out & + +Tempo +----- + +Tempo is an open-source distributed tracing system designed to handle high volumes of trace data. Tempo can be used to trace database transactions and operations across distributed systems, providing insights into performance bottlenecks and aiding in troubleshooting complex queries. + +#. `Download and install <https://grafana.com/docs/tempo/latest/setup/linux/>`_ Tempo. + +#. Set the Tempo YML path: + + .. code-block:: console + + TEMPO_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/tempo.yml + +#. Start Tempo server: + + .. code-block:: console + + /usr/bin/tempo -config.file /etc/tempo/config.yml &> ~/tempo.out & + Utility Functions ================= From 0eee3282ec6f55abfb5ae05a84d61db5434c0e41 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:12:21 +0300 Subject: [PATCH 1434/1892] Update root_cause_analysis.rst --- operational_guides/root_cause_analysis.rst | 45 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/root_cause_analysis.rst index d88c17bfc..00e485621 100644 --- a/operational_guides/root_cause_analysis.rst +++ b/operational_guides/root_cause_analysis.rst @@ -4,7 +4,7 @@ Root Cause Analysis ******************* -The Root Cause Analysis (RCA) service enhances observability, enabling shorter investigation times and facilitating both high-level and detailed drill-downs. +The Root Cause Analysis (RCA) service enhances observability, enabling shorter investigation times and facilitating both high-level and detailed drill-downs by automatically executing the :ref:`export_open_snapshots` and :ref:`get_open_snapshots` utility functions. .. contents:: :local: @@ -53,6 +53,8 @@ Setting Linux Service #. Create Service: .. code-block:: console + +(Set the command above (case 2) as a linux service) -Slavi #. Start the Grafa service: @@ -73,6 +75,8 @@ Prometheus is an open-source monitoring and alerting toolkit designed for reliab #. Download Prometheus. +#. (Prometheus Exporter installation) -Slavi + #. Set the YML path: .. code-block:: console @@ -135,7 +139,42 @@ Tempo is an open-source distributed tracing system designed to handle high volum /usr/bin/tempo -config.file /etc/tempo/config.yml &> ~/tempo.out & -Utility Functions +Exporters +--------- + +An Exporter is a software component that gathers metrics from various sources (such as hardware, software, or services) and exposes them in a format that Prometheus can scrape and store. + +GPU Exporter +~~~~~~~~~~~~ + + + +CPU Exporter +~~~~~~~~~~~~ + +#. Download the `CPU Exporter <https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-386.tar.gz >`_. + +#. Start the Exporter: + + .. code-block:: console + + /usr/bin/node_exporter &> ~/node_exporter.out & + +Process Exporter +~~~~~~~~~~~~~~~~ + +#. (Prometheus Exporter installation)-Slavi + +#. Start the Exporter: + + .. code-block:: console + + /usr/bin/process-exporter --config.path /etc/process-exporter/all.yaml --web.listen-address=:9256 &> process_exporter.out & + +SQream Dashboards ================= -The RCA executes the :ref:`export_open_snapshots` and :ref:`get_open_snapshots` utility functions. \ No newline at end of file +https://sqream.atlassian.net/wiki/spaces/~477790253/pages/3134488697/RCA+-+Grafana+installation + +-Slavi + From 1f9f517a17d0562b310eb567f3d7fdec487e588f Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:21:52 +0300 Subject: [PATCH 1435/1892] Update show_locks.rst --- reference/sql/sql_statements/utility_commands/show_locks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index 15eb50525..2f032b414 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -69,4 +69,4 @@ Output: Permissions =========== -This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file +This utility function requires a ``CONNECT`` permission on the database level. From d50bc472b2e46305d73f0b7e4c0ad80dc75c15bc Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 13:26:19 +0300 Subject: [PATCH 1436/1892] Update root_cause_analysis.rst --- operational_guides/root_cause_analysis.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/root_cause_analysis.rst index 00e485621..b7ae8f684 100644 --- a/operational_guides/root_cause_analysis.rst +++ b/operational_guides/root_cause_analysis.rst @@ -152,7 +152,7 @@ GPU Exporter CPU Exporter ~~~~~~~~~~~~ -#. Download the `CPU Exporter <https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-386.tar.gz >`_. +#. Download the `CPU Exporter <https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-386.tar.gz>`_. #. Start the Exporter: From 92f29b049a0c773e364a7bc52cade64f6b82e87c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 14:53:37 +0300 Subject: [PATCH 1437/1892] Oracle Migration Guide --- .DS_Store | Bin 10244 -> 10244 bytes .../creating_or_cloning_a_storage_cluster.rst | 19 +-- operational_guides/index.rst | 1 + operational_guides/oracle_migration.rst | 109 ++++++++++++++++++ 4 files changed, 120 insertions(+), 9 deletions(-) create mode 100644 operational_guides/oracle_migration.rst diff --git a/.DS_Store b/.DS_Store index a3efb71446bef3ff6221a3cb3a46bb5db103c31e..65723e4873b423d7ec55f10f0fabd392352fd5f1 100644 GIT binary patch delta 125 zcmZn(XbG6$&#1gHU^hRb@@5`^|C~HY<;4X_Ir&Kp3=BIb>j@QVNLE)Hn_K887+RRr z>L^qj8XKGGD43fX)z)%yh$`z_2gPUS<mTmfPd+9j&)75hq2x?)A%=X00)|wEB8EhU b5{675FAvDdnfzB$c5{_f7RzRKg}>|oGfyP? delta 41 xcmZn(XbG6$&#1UDU^hRb;$|L!|D2Qir1>XvN+)cdE1ku%u|b(}GrPiHb^s_x4cq_# diff --git a/operational_guides/creating_or_cloning_a_storage_cluster.rst b/operational_guides/creating_or_cloning_a_storage_cluster.rst index 0406bda77..e99511a5d 100644 --- a/operational_guides/creating_or_cloning_a_storage_cluster.rst +++ b/operational_guides/creating_or_cloning_a_storage_cluster.rst @@ -1,12 +1,13 @@ .. _creating_or_cloning_a_storage_cluster: -**************************************** +************************************ Creating or Cloning Storage Clusters -**************************************** +************************************ + When SQream DB is installed, it comes with a default storage cluster. This guide will help if you need a fresh storage cluster or a separate copy of an existing storage cluster. Creating a new storage cluster -===================================== +============================== SQream DB comes with a CLI tool, :ref:`sqream_storage_cli_reference`. This tool can be used to create a new empty storage cluster. @@ -22,10 +23,10 @@ This can also be written shorthand as ``SqreamStorage -C -r /home/rhendricks/rav This ``Setting cluster version...`` message confirms the creation of the cluster successfully. Tell SQream DB to use this storage cluster -=============================================== +========================================== Permanently setting the storage cluster setting -------------------------------------------------------- +----------------------------------------------- To permanently set the new cluster location, change the ``"cluster"`` path listed in the configuration file. @@ -72,12 +73,12 @@ should be changed to Now, the cluster should be restarted for the changes to take effect. Start a temporary SQream DB worker with a storage cluster -------------------------------------------------------------- +--------------------------------------------------------- Starting a SQream DB worker with a custom cluster path can be done in two ways: Using a configuration file (recommended) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Similar to the technique above, create a configuration file with the correct cluster path. Then, start ``sqreamd`` using the ``-config`` flag: @@ -86,7 +87,7 @@ Similar to the technique above, create a configuration file with the correct clu $ sqreamd -config config_file.json Using the command line parameters -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Use sqreamd's command line parameters to override the default storage cluster path: @@ -97,7 +98,7 @@ Use sqreamd's command line parameters to override the default storage cluster pa .. note:: sqreamd's command line parameters' order is ``sqreamd <cluster path> <GPU ordinal> <TCP listen port (unsecured)> <License path>`` Copying an existing storage cluster -===================================== +=================================== Copying an existing storage cluster to another path may be useful for testing or troubleshooting purposes. diff --git a/operational_guides/index.rst b/operational_guides/index.rst index eb736d827..9b3914414 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -25,5 +25,6 @@ This section summarizes the following operational guides: security saved_queries optimization_best_practices + oracle_migration \ No newline at end of file diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst new file mode 100644 index 000000000..ab405c92e --- /dev/null +++ b/operational_guides/oracle_migration.rst @@ -0,0 +1,109 @@ +.. _oracle_migration: + +********************** +Oracle Migration Guide +********************** + + + +Before You Begin +================ + + + +Using SQream Commands, Statements, and UDFs +=========================================== + +.. list-table:: Operation Functions + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``+ (unary)`` + - ``+ (unary)`` + - +a + * - ``+`` + - ``+`` + - a+ b + * - ``- (unary)`` + - ``- (unary)`` + - -a + * - ``-`` + - ``-`` + - a - b + * - ``*`` + - ``*`` + - a * b + * - ``/`` + - ``/`` + - a / b + * - ``%`` + - ``%`` + - a % b + * - ``&`` + - ``&`` + - AND + * - ``~`` + - ``~`` + - NOT + * - ``|`` + - ``|`` + - OR + * - ``<<`` + - ``<<`` + - Shift left + * - ``>>`` + - ``>>`` + - Shift right + * - ``XOR`` + - ``XOR`` + - XOR + +.. list-table:: Conditional Functions + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - From 91feda72f789679565f8a0d5d2d05a4a0e42c830 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 7 Jul 2024 15:37:31 +0300 Subject: [PATCH 1438/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 33 +++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index ab405c92e..7d13ef773 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -65,6 +65,39 @@ Using SQream Commands, Statements, and UDFs :widths: auto :header-rows: 1 + * - Oracle + - SQream + - Description + * - ``BETWEEN`` + - ``BETWEEN`` + - Value is in [ or not within ] the range + * - ``CASE`` + - ``CASE`` + - Tests a conditional expression, depending on the result + * - ``COALESCE`` + - ``COALESCE`` + - Evaluate first non-NULL expression + * - ``IN`` + - ``IN`` + - Value is in [ or not within ] a set of values + * - ``ISNULL`` + - ``ISNULL`` + - Alias for COALESCE with two expressions + * - ``IS_ASCII`` + - ``IS_ASCII`` + - Test a TEXT for ASCII-only characters + * - ``IS_NULL`` + - ``IS NULL`` + - Check for NULL [ or non-NULL ] values + * - ``DECODE`` + - ``DECODE`` + - Decodes or extracts binary data from a textual input string + + +.. list-table:: Numeric Functions + :widths: auto + :header-rows: 1 + * - Oracle - SQream - Description From be285aae12eeb0762f12371f2154dc15c9de0b29 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:51:50 +0300 Subject: [PATCH 1439/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 346 +++++++++++++++++++++++- 1 file changed, 342 insertions(+), 4 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index 7d13ef773..c05d59648 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -4,7 +4,9 @@ Oracle Migration Guide ********************** - +.. contents:: + :local: + :depth: 2 Before You Begin ================ @@ -14,7 +16,10 @@ Before You Begin Using SQream Commands, Statements, and UDFs =========================================== -.. list-table:: Operation Functions +Operation Functions +------------------- + +.. list-table:: :widths: auto :header-rows: 1 @@ -61,7 +66,10 @@ Using SQream Commands, Statements, and UDFs - ``XOR`` - XOR -.. list-table:: Conditional Functions +Conditional Functions +--------------------- + +.. list-table:: :widths: auto :header-rows: 1 @@ -93,8 +101,312 @@ Using SQream Commands, Statements, and UDFs - ``DECODE`` - Decodes or extracts binary data from a textual input string +Numeric Functions +----------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``ABS`` + - ``ABS`` + - Calculates the absolute value of an argument + * - ``ACOS`` + - ``ACOS`` + - Calculates the inverse cosine of an argument + * - ``ASIN`` + - ``ASIN`` + - Calculates the inverse sine of an argument + * - ``ATAN`` + - ``ATAN`` + - Calculates the inverse tangent of an argument + * - ``ATN2`` + - ``ATN2`` + - Calculates the inverse tangent for a point (y, x) + * - ``BITAND`` + - ``&`` + - Computes an AND operation on the bits of expr1 and expr2 + * - ``CEIL`` + - ``CEILING``, ``CEIL`` + - Calculates the next integer for an argument + * - ``COS`` + - ``COS`` + - Calculates the cosine of an argument + * - ``COSH`` + - .. code-block:: postgres + + CREATE or replace FUNCTION COSH(x double) + RETURNS double + AS $$ + SELECT (exp(x) + exp(-1*x))/2 + $$ LANGUAGE SQL + ; + - Returns the hyperbolic cosine of n + * - NA + - ``COT`` + - Calculates the cotangent of an argument + * - NA + - ``CRC64`` + - Calculates a CRC-64 hash of an argument + * - NA + - ``DEGREES`` + - Converts a value from radian values to degrees + * - ``EXP`` + - ``EXP`` + - Calculates the natural exponent for an argument + * - ``FLOOR`` + - ``FLOOR`` + - Calculates the largest integer smaller than the argument + * - ``LN`` + - ``LOG`` + - Returns the natural logarithm of n + * - ``LOG(b,n)`` + - .. code-block:: postgres + + CREATE or replace FUNCTION log(b double, n double) + RETURNS double + AS $$ + SELECT (log(n)/log(b)) + $$ LANGUAGE SQL + ; + - Calculates the natural log for an argument + * - ``LOG(10,x)`` + - ``LOG10`` + - Calculates the 10-based log for an argument + * - ``MOD`` + - ``MOD``, ``%`` + - Calculates the modulu (remainder) of two arguments + * - NA + - ``PI`` + - Returns the constant value for π + * - ``NANVL`` + - NA + - Useful only for floating-point numbers of type + * - ``POWER`` + - ``POWER`` + - Calculates x to the power of y (xy) + * - NA + - ``SQUARE`` + - Returns the square value of a numeric expression (x2) + * - NA + - ``RADIANS`` + - Converts a value from degree values to radians + * - ``REMAINDER`` + - .. code-block:: postgres + + CREATE or replace FUNCTION remainder(n1 bigint, n2 bigint) + RETURNS bigint + AS $$ + SELECT (n1 - floor(n1/n2)*n2) + $$ LANGUAGE SQL + ; + - Returns the arguments any numeric datatype + * - ``ROUND (number)`` + - ``ROUND`` + - Rounds an argument down to the nearest integer + * - ``SIGN`` + - .. code-block:: postgres + + CREATE or replace FUNCTION my_sign(n bigint) + RETURNS int + AS $$ + SELECT case when n < 0 then -1 when n = 0 then 0 when n > 0 then 1 end + $$ LANGUAGE SQL + ; + - Returns the sign of the input value + * - ``SIN`` + - ``SIN`` + - Calculates the sine + * - ``SINH`` + - .. code-block:: postgres + + CREATE or replace FUNCTION SINH(x double) + RETURNS double + AS $$ + SELECT (exp(x) - exp(-1*x))/2 + $$ LANGUAGE SQL + ; + - Calculates the hyperbolic sine + * - ``SQRT`` + - ``SQRT`` + - Calculates the square root + * - ``TAN`` + - ``TAN`` + - Calculates the tangent + * - ``TANH`` + - .. code-block:: postgres + + CREATE or replace FUNCTION TANH(x double) + RETURNS double + AS $$ + SELECT (exp(x) - exp(-1*x))/(exp(x) + exp(-1*x)) + $$ LANGUAGE SQL + ; + - Calculates the hyperbolic tangent + * - ``TRUNC (number)`` + - ``TRUNC`` + - Rounds a number to its integer representation towards 0 + * - ``WIDTH_BUCKET(value, low, high, num_buckets)`` + - .. code-block:: postgres + + CREATE or replace FUNCTION myWIDTH_BUCKET(value float, low float, high float, num_buckets int ) + RETURNS INT + AS $$ + select CASE + WHEN value < low THEN 0 + WHEN value >= high THEN num_buckets + 1 + ELSE CEIL(((value - low) / ((high - low) / num_buckets))+1)::INT END + $$ LANGUAGE SQL + ; + - Returns the ID of the bucket into which the value of a specific expression falls + * - NA + - ``TO_HEX`` + - Converts an integer to a hexadecimal representation + +Character Functions Returning Character Values +---------------------------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``CHR`` + - ``CHR`` + - Returns the character having the binary equivalent + * - ``CONCAT`` + - ``||`` (Concatenate) + - Concatenates all the specified strings and returns the final string + * - ``INITCAP`` + - NA + - Returns char, with the first letter of each word in uppercase + * - ``LOWER`` + - ``LOWER`` + - Returns char, with all letters lowercase + * - ``LPAD`` + - NA + - Returns expr1, left-padded to length n characters + * - ``LTRIM`` + - ``LTRIM`` + - Removes from the left end of char + * - ``NLS_INITCAP`` + - NA + - Returns char, with the first letter of each word in uppercase + * - ``NLS_LOWER`` + - NA + - Returns char, with all letters lowercase + * - ``NLSSORT`` + - NA + - Returns the string of bytes used to sort char + * - ``NLS_UPPER`` + - NA + - Returns char, with all letters uppercase + * - ``REGEXP_REPLACE`` + - ``REGEXP_REPLACE`` + - Replaces a substring in a string that matches a specified pattern + * - ``REGEXP_SUBSTR`` + - ``REGEXP_SUBSTR`` + - Returns a substring of an argument that matches a regular expression + * - ``REPLACE`` + - ``REPLACE`` + - Replaces characters in a string + * - ``RPAD`` + - NA + - Right pads a string to a specified length + * - ``RTRIM`` + - ``RTRIM`` + - Removes the space from the right side of a string + * - ``SOUNDEX`` + - NA + - Converts a normal string into a string of the SOUNDEX type + * - ``SUBSTR`` + - ``SUBSTRING``, ``SUBSTR`` + - Returns a substring of an argument + * - ``TRANSLATE`` + - NA + - Returns ``expr`` with all occurrences of each character in ``from_string``, replaced by its corresponding character + * - ``TRIM`` + - ``TRIM`` + - Trims whitespaces from an argument + * - ``UPPER`` + - ``UPPER`` + - Converts an argument to an upper-case equivalent + * - NA + - ``REPEAT`` + - Repeats a string as many times as specified + * - NA + - ``REVERSE`` + - Returns a reversed order of a character string + * - NA + - ``LEFT`` + - Returns the left part of a character string with the specified number of characters + * - NA + - ``RIGHT`` + - Returns the right part of a character string with the specified number of characters + * - NA + - ``LIKE`` + - Tests if a string matches a given pattern. SQL patterns + * - NA + - ``RLIKE`` + - Tests if a string matches a given regular expression pattern. POSIX regular expressions + * - NA + - ``ISPREFIXOF`` + - Checks if one string is a prefix of the other + +Character Functions Returning Number Values +------------------------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``ASCII`` + - NA + - Returns the decimal representation in the database character set + * - ``INSTR`` + - ``CHARINDEX`` + - Search string for substring + * - ``LENGTH`` + - ``CHAR_LENGTH`` + - Calculates the length of a string in characters + * - NA + - ``LEN`` + - Calculates the number of characters in a string. (This function is provided for SQL Server compatibility) + * - NA + - ``OCTET_LENGTH`` + - Calculates the number of bytes in a string + * - NA + - ``CHARINDEX`` + - Returns the starting position of a string inside another string + * - NA + - ``PATINDEX`` + - Returns the starting position of a string inside another string + * - ``REGEXP_COUNT`` + - ``REGEXP_COUNT`` + - Calculates the number of matches of a regular expression + * - ``REGEXP_INSTR`` + - ``REGEXP_INSTR`` + - Returns the start position of a regular expression match in an argument + * - NA + - ``REGEXP_REPLACE`` + - + +Datetime Functions +------------------ -.. list-table:: Numeric Functions +.. list-table:: :widths: auto :header-rows: 1 @@ -140,3 +452,29 @@ Using SQream Commands, Statements, and UDFs * - ```` - ```` - + * - ```` + - ```` + - + * - ```` + - ```` + - + * - ```` + - ```` + - + +General Comparison Functions +---------------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ```` + - ```` + - + * - ```` + - ```` + - \ No newline at end of file From c92fbbd2033447215821d3398254f6076f1cc525 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jul 2024 10:11:00 +0300 Subject: [PATCH 1440/1892] RCA, logFormat, 4.6 --- ..._analysis.rst => health_monitoringrst.rst} | 30 ++++++++++--------- operational_guides/index.rst | 6 ++-- operational_guides/logging.rst | 4 ++- releases/4.6.rst | 8 +++++ 4 files changed, 30 insertions(+), 18 deletions(-) rename operational_guides/{root_cause_analysis.rst => health_monitoringrst.rst} (81%) diff --git a/operational_guides/root_cause_analysis.rst b/operational_guides/health_monitoringrst.rst similarity index 81% rename from operational_guides/root_cause_analysis.rst rename to operational_guides/health_monitoringrst.rst index b7ae8f684..d7c1db970 100644 --- a/operational_guides/root_cause_analysis.rst +++ b/operational_guides/health_monitoringrst.rst @@ -1,10 +1,10 @@ -.. _root_cause_analysis: +.. _health_monitoring: -******************* -Root Cause Analysis -******************* +***************** +Health Monitoring +***************** -The Root Cause Analysis (RCA) service enhances observability, enabling shorter investigation times and facilitating both high-level and detailed drill-downs by automatically executing the :ref:`export_open_snapshots` and :ref:`get_open_snapshots` utility functions. +The Health Monitoring service enhances observability, enabling shorter investigation times and facilitating both high-level and detailed drill-downs. .. contents:: :local: @@ -15,27 +15,27 @@ Before You Begin It is essential that you follow these prerequisites: -* Log files must be saved as ``JSON`` files +* :ref:`Log files<log_structure>` must be saved as ``JSON`` files -Usage Notes -=========== +* :ref:`Set the path<export_open_snapshots>` to where you wish your open snapshot information be saved -By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. - -.. note: - - The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file +Security +======== Installation ============ -All RCA-related installations are on a stand-alone installations. +All Health Monitoring-related installations are on a stand-alone installations. Grafana ------- Grafana is an open-source analytics and monitoring platform that visualizes data and is used to create dashboards that display real-time and historical data. +You may use both Grafana's open source version and its enterprise version, depending on your needs. + +See `Grafana specification <https://grafana.com/docs/grafana/latest/setup-grafana/installation/#hardware-recommendations>`_ + Manual Execution ~~~~~~~~~~~~~~~~ @@ -178,3 +178,5 @@ https://sqream.atlassian.net/wiki/spaces/~477790253/pages/3134488697/RCA+-+Grafa -Slavi +Best Practices +============== \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index 9b3914414..ec5009a21 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -1,8 +1,8 @@ .. _operational_guides: -********************************** +****************** Operational Guides -********************************** +****************** The **Operational Guides** section describes processes that SQream users can manage to affect the way their system operates, such as creating storage clusters and monitoring query performance. @@ -17,7 +17,7 @@ This section summarizes the following operational guides: creating_or_cloning_a_storage_cluster external_data foreign_tables - root_cause_analysis + health_monitoring delete_guide logging query_split diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index c607078ec..f3b9a3b56 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -23,12 +23,14 @@ The worker logs contain information messages, warnings, and errors pertaining to * Statement execution success / failure * Statement execution statistics +.. _log_structure: + Log Structure and Contents -------------------------- By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. -For effective :ref:`Root Cause Analysis (RCA)<root_cause_analysis>`, it's essential that logs are saved in ``JSON`` format, as RCA does not support ``CSV`` files. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. +For effective :ref:`health_monitoring`, it's essential that logs are saved in ``JSON`` format, as Health Monitoring does not support ``CSV`` files. If your current logs are in ``CSV`` format and you require RCA, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. .. list-table:: Log fields :widths: auto diff --git a/releases/4.6.rst b/releases/4.6.rst index 0ac23e286..f368bab11 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -34,6 +34,14 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. + +.. note:: + + The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file + +► :ref:`health_monitoring` + ► REHL 8.x is now officially supported. ► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. From aaf28f407da55230c75189df753a4c4ab05ec52f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jul 2024 11:48:54 +0300 Subject: [PATCH 1441/1892] RCA --- operational_guides/health_monitoringrst.rst | 34 +++++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/operational_guides/health_monitoringrst.rst b/operational_guides/health_monitoringrst.rst index d7c1db970..bcd8e3bc0 100644 --- a/operational_guides/health_monitoringrst.rst +++ b/operational_guides/health_monitoringrst.rst @@ -19,8 +19,8 @@ It is essential that you follow these prerequisites: * :ref:`Set the path<export_open_snapshots>` to where you wish your open snapshot information be saved -Security -======== +* Configure `Grafana authentication <https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/grafana/>`_, even if you're using `LDAP <https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/ldap/>`_ for authentication management + Installation ============ @@ -179,4 +179,32 @@ https://sqream.atlassian.net/wiki/spaces/~477790253/pages/3134488697/RCA+-+Grafa -Slavi Best Practices -============== \ No newline at end of file +============== + +Daily Usage +----------- + +Grafana Alerts +-------------- + +Investigating Health Issues +--------------------------- + +Dealing with Open Snapshots +--------------------------- + +Dealing with Unreleased Locks +----------------------------- + +Dealing with Slow Metadata +-------------------------- + +Dealing with Growing Statement Queue +------------------------------------ + +Dealing with Slow Workers +------------------------- + +Dealing with Hung Workers +------------------------- + From 15c5c782af42dd8f25ccf7c632d40cbedc8c0351 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 8 Jul 2024 14:49:15 +0300 Subject: [PATCH 1442/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 383 ++++++++++++++++++++---- 1 file changed, 331 insertions(+), 52 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index c05d59648..92a5d6fd1 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -4,6 +4,8 @@ Oracle Migration Guide ********************** +This guide is designed to assist those who wish to migrate their database systems from Oracle to SQreamDB. Use this guide to learn how to use the most commonly used Oracle functions with their equivalents in SQreamDB. For functions that do not have direct equivalents in SQreamDB, we provide User-Defined Functions (UDFs). If you need further assistance, our `SQream support team <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ is available to help with any custom UDFs or additional migration questions. + .. contents:: :local: :depth: 2 @@ -26,14 +28,14 @@ Operation Functions * - Oracle - SQream - Description - * - ``+ (unary)`` - - ``+ (unary)`` + * - ``+`` (unary) + - ``+`` (unary) - +a * - ``+`` - ``+`` - a+ b - * - ``- (unary)`` - - ``- (unary)`` + * - ``-`` (unary) + - ``-`` (unary) - -a * - ``-`` - ``-`` @@ -101,6 +103,30 @@ Conditional Functions - ``DECODE`` - Decodes or extracts binary data from a textual input string +Conversion Functions +-------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``TO_DATE`` + - ``+`` (unary) + - Converts a string to a date + * - ``TO_NUMBER`` + - .. code-block:: postgres + + CREATE OR REPLACE FUNCTION SIGN(n,numeric) + RETURNS numeric + AS $$ + CAST(TEXT AS NUMERIC) + $$ LANGUAGE SQL + ; + - Converts a string to a number + Numeric Functions ----------------- @@ -178,7 +204,7 @@ Numeric Functions - Calculates the 10-based log for an argument * - ``MOD`` - ``MOD``, ``%`` - - Calculates the modulu (remainder) of two arguments + - Calculates the modulus (remainder) of two arguments * - NA - ``PI`` - Returns the constant value for π @@ -413,54 +439,112 @@ Datetime Functions * - Oracle - SQream - Description - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` - - - * - ```` - - ```` + * - ``ADD_MONTHS`` + - NA + - Returns a number of months are added to a specified date + * - NA + - ``CURDATE`` + - This function is equivalent to CURRENT_DATE + * - ``CURRENT_DATE`` + - ``CURRENT_DATE`` + - Returns the current date as DATE + * - ``CURRENT_TIMESTAMP`` + - ``CURRENT_TIMESTAMP`` + - Equivalent to ``GETDATE`` + * - ``DBTIMEZONE`` + - NA + - Returns the value of the database time zone + * - ``EXTRACT`` (datetime) + - ``EXTRACT`` + - ANSI syntax for extracting date or time element from a date expression + * - ``FROM_TZ`` + - NA + - Converts a timestamp value and a time zone + * - ``LAST_DAY`` + - ``EOMONTH`` + - Returns the last day of the month in which the specified date value falls + * - NA + - ``CURRENT_TIMESTAMP`` + - Returns the current date and time in the session time zone + * - ``MONTHS_BETWEEN`` + - NA + - Returns the number of months between specified date values + * - ``NEW_TIME`` + - NA + - returns the date and time in time zone + * - ``NEXT_DAY`` + - NA + - Returns the date of the first weekday that is later than a specified data + * - ``NUMTODSINTERVAL`` + - NA + - Converts n to an INTERVAL DAY TO SECOND literal + * - ``NUMTOYMINTERVAL`` + - NA + - Converts number n to an INTERVAL YEAR TO MONTH literal + * - ``ORA_DST_AFFECTED`` + - NA + - Changing the time zone data file + * - ``ORA_DST_CONVERT`` + - NA + - Changing the time zone data file for specify error handling + * - ``ORA_DST_ERROR`` + - NA + - Changing the time zone data file for takes as an argument a datetime + * - ``ROUND`` (date) + - ``ROUND`` + - Rounds an argument down to the nearest integer, or an arbitrary precision + * - ``SESSIONTIMEZONE`` + - NA + - Returns the time zone of the current session + * - ``SYS_EXTRACT_UTC`` + - NA + - extracts the UTC from a datetime value with time zone offset + * - ``SYSDATE`` + - ``SYSDATE`` + - Equivalent to ``GETDATE`` + * - ``SYSTIMESTAMP`` + - ``CURRENT_TIMESTAMP`` + - Returns the current timestamp + * - ``TO_CHAR`` (datetime) + - NA + - Converts a date value to a string in a specified format + * - ``TO_TIMESTAMP`` + - NA + - Converts datatype to a value of TIMESTAMP datatype + * - ``TO_TIMESTAMP_TZ`` + - NA + - Converts datatype to a value of TIMESTAMP WITH TIME ZONE datatype + * - ``TO_DSINTERVAL`` + - NA + - Converts a character string of CHAR datatype + * - ``TO_YMINTERVAL`` + - NA + - Converts a character string of CHAR datatype + * - ``TRUNC`` (date) + - ``TRUNC`` + - Truncates a date element down to a specified date or time element + * - ``TZ_OFFSET`` + - NA + - Returns the time zone offset + * - NA + - ``DATEADD`` - - * - ```` - - ```` + * - NA + - ``DATEDIFF`` - - * - ```` - - ```` + * - NA + - ``DATEPART`` - - * - ```` - - ```` + * - NA + - ``GETDATE`` - - * - ```` - - ```` + * - NA + - ``TO_UNIXTS``, ``TO_UNIXTSMS`` - - * - ```` - - ```` + * - NA + - ``FROM_UNIXTS``, ``FROM_UNIXTSMS`` - + General Comparison Functions ---------------------------- @@ -472,9 +556,204 @@ General Comparison Functions * - Oracle - SQream - Description - * - ```` - - ```` + * - ``GREATEST`` + - NA + - Returns the greatest of a list of one or more expressions + * - ``LEAST`` + - NA + - Returns the least of a list of one or more expressions + +NULL-Related Functions +---------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``COALESCE`` + - ``COALESCE`` + - Returns the first non-null + * - ``LNNVL`` + - NA + - Provides a concise way to evaluate a condition when one or both operands of the condition may be null + * - ``NANVL`` + - NA + - Takes as arguments any numeric data type or any nonnumeric data type + * - ``NULLIF`` + - ``IS NULL`` + - If they are equal, then the function returns null + * - ``NVL`` + - ``ISNULL`` + - Replace null (returned as a blank) with a string in the results of a query + * - ``NVL2`` + - NA + - Determine the value returned by a specified expression is null or not null + +Aggregate Functions +------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - ``AVG`` + - ``AVG`` + - Calculates the average of all of the values + * - ``CHECKSUM`` + - NA + - Detect changes in a table + * - ``COLLECT`` + - NA + - Takes as its argument a column of any type and creates a nested table + * - ``CORR`` + - ``CORR`` + - Calculates the Pearson correlation coefficient + * - ``COUNT`` + - ``COUNT`` + - Calculates the count of all of the values or only distinct values + * - ``COVAR_POP`` + - ``COVAR_POP`` + - Calculates population covariance of values + * - ``COVAR_SAMP`` + - ``COVAR_SAMP`` + - Calculates sample covariance of values + * - ``CUME_DIST`` + - ``CUME_DIST`` + - Calculates the cumulative distribution of a value in a group of values + * - ``FIRST`` + - ``FIRST_VALUE`` + - The FIRST_VALUE function returns the value located in the selected column of the first row of a segment + * - ``GROUP_ID`` + - NA + - Distinguishes duplicate groups resulting from a GROUP BY specification + * - ``GROUPING`` + - NA + - Distinguishes superaggregate rows from regular grouped rows + * - ``GROUPING_ID`` + - NA + - Returns a number corresponding to the GROUPING bit vector associated with a row + * - ``LAST`` + - ``LAST_VALUE`` + - The LAST_VALUE function returns the value located in the selected column of the last row of a segment + * - NA + - ``NTH_VALUE`` + - The NTH_VALUE function returns the value located in the selected column of a specified row of a segment + * - ``MAX`` + - ``MAX`` + - Returns maximum value of all values + * - ``MEDIAN`` + - NA + - Calculates the median value of a column + * - ``MIN`` + - ``MIN`` + - Returns minimum value of all values + * - NA + - ``NTILE`` + - Divides an ordered data set into a number of buckets + * - ``PERCENTILE_CONT`` + - ``PERCENTILE_CONT`` + - Inverse distribution function that assumes a continuous distribution model + * - ``PERCENTILE_DISC`` + - ``PERCENTILE_DISC`` + - Inverse distribution function that assumes a discrete distribution model + * - ``PERCENT_RANK`` + - ``PERCENT_RANK`` + - Range of values returned by PERCENT_RANK is 0 to 1, inclusive + * - ``RANK`` + - ``RANK`` + - Calculates the rank of a value in a group of values + * - ``DENSE_RANK`` + - ``DENSE_RANK`` + - Computes the rank of a row in an ordered group of rows + * - ``STATS_BINOMIAL_TEST`` + - NA + - Exact probability test used for dichotomous variables + * - ``STATS_CROSSTAB`` + - NA + - Method used to analyze two nominal variables + * - ``STATS_F_TEST`` + - NA + - Tests whether two variances are significantly different + * - ``STATS_KS_TEST`` + - NA + - Kolmogorov-Smirnov function that compares two samples to test + * - ``STATS_MODE`` + - NA + - Takes as its argument a set of values and returns the value + * - ``STDDEV`` + - ``STDDEV`` + - Returns the population standard deviation of all input values + * - ``STDDEV_POP`` + - ``STDDEV_POP`` + - Calculates population standard deviation of values + * - ``STDDEV_SAMP`` + - ``STDDEV_SAMP`` + - Calculates sample standard deviation of values + * - ``SUM`` + - ``SUM`` + - Calculates the sum of all of the values or only distinct values + * - ``VAR_POP`` + - ``VAR_POP`` + - Calculates population variance of values + * - ``VAR_SAMP`` + - ``VAR_SAMP`` + - Calculates sample variance of values + * - ``VARIANCE`` + - ``VAR``, ``VARIANCE`` + - Returns the variance of expr + +Analytic Functions +------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle + - SQream + - Description + * - NA + - ``MODE`` - - * - ```` - - ```` - - \ No newline at end of file + * - ``FEATURE_DETAILS`` + - NA + - Returns feature details for each row in the selection + * - ``FEATURE_ID`` + - NA + - Returns the identifier of the highest value feature for each row + * - ``FEATURE_SET`` + - NA + - Returns a set of feature ID and feature value pairs for each row + * - ``FEATURE_VALUE`` + - NA + - Returns a feature value for each row in the selection + * - ``LEAD`` + - ``LEAD`` + - Returns a value from a subsequent row within the partition of a result set + * - ``LAG`` + - ``LAG`` + - Returns a value from a previous row within the partition of a result set + * - ``PREDICTION`` + - NA + - Returns a prediction for each row in the selection + * - ``PREDICTION_COST`` + - NA + - Returns prediction details for each row in the selection + * - ``PREDICTION_DETAILS`` + - NA + - Returns prediction details for each row in the selection + * - ``PREDICTION_PROBABILITY`` + - NA + - Returns a probability for each row in the selection + * - ``PREDICTION_SET`` + - NA + - Returns a set of predictions with either probabilities or costs for each row + * - ``ROW_NUMBER`` + - ``ROW_NUMBER`` + - Assigns a unique number to each row to which it is applied \ No newline at end of file From da62b733552f69d51b19d43c1bc304188d0fc569 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jul 2024 08:06:21 +0300 Subject: [PATCH 1443/1892] Catalog permissions --- .DS_Store | Bin 10244 -> 10244 bytes .../access_control_permissions.rst | 10 ++-------- .../access_control_commands/grant.rst | 6 ++---- .../access_control_commands/revoke.rst | 4 +--- 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/.DS_Store b/.DS_Store index 65723e4873b423d7ec55f10f0fabd392352fd5f1..97d287aef654675e2bec8917779a214612247478 100644 GIT binary patch delta 57 zcmZn(XbG6$&#1C7U^hRb%4QycChp1HQVsm3hGsenCZ;B}IttZ>#uk$|2#HQ!FQu|M NQ+gxwW_E?Y>;Ud95m*2K delta 32 ocmZn(XbG6$&#1gHU^hRb@@5`^ChpDEGCj-_8{TeaSNO{g0J;JTtN;K2 diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 017ce2bb6..a4cc5c879 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -95,8 +95,6 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from catalog | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``ALL`` | All catalog permissions | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **Services** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``USAGE`` | Using a specific service | @@ -165,9 +163,7 @@ GRANT TO <role> [, ...] -- Grant permissions at the catalog level: - GRANT { - {SELECT } [, ...] - | ALL [PERMISSIONS] } + GRANT SELECT ON { CATALOG <catalog_name> [, ...] } TO <role> [, ...] @@ -286,9 +282,7 @@ REVOKE FROM <role> [, ...] -- Revoke permissions at the catalog level: - REVOKE { - {SELECT } [, ...] - | ALL [PERMISSIONS] } + REVOKE SELECT ON { CATALOG <catalog_name> [, ...] } FROM <role> [, ...] diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index ffd914cf5..7668604aa 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -61,9 +61,7 @@ Syntax TO <role> [, ...] -- Grant permissions at the catalog level: - GRANT { - {SELECT } [, ...] - | ALL [PERMISSIONS] } + GRANT SELECT ON { CATALOG <catalog_name> [, ...] } TO <role> [, ...] @@ -197,7 +195,7 @@ The following table describes the supported permissions: - Function - Allows a user to execute UDFs * - ``ALL`` - - Cluster, Database, Schema, Table, Function, Saved Query, Services, Catalog, Foreign Table + - Cluster, Database, Schema, Table, Function, Saved Query, Services, Foreign Table - All of the above permissions at the respective level .. end include diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index 44e27d54a..fb383a59a 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -61,9 +61,7 @@ Syntax FROM <role> [, ...] -- Revoke permissions at the catalog level: - REVOKE { - {SELECT } [, ...] - | ALL [PERMISSIONS] } + REVOKE SELECT ON { CATALOG <catalog_name> [, ...] } FROM <role> [, ...] From d54877c08a72d37439d86277d55bccc06b1e75a1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:23:25 +0300 Subject: [PATCH 1444/1892] JDBC 5.3.1 --- connecting_to_sqream/client_drivers/index.rst | 2 +- operational_guides/foreign_tables.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 1b0119926..29d0c7f39 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -29,7 +29,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.2.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.2.0.jar>`_ + - `sqream-jdbc 5.3.1 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.3.1.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 38b3affea..685368840 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -4,7 +4,7 @@ Foreign Tables ************** -Foreign tables can be used to run queries directly on data without inserting it into SQream DB first. +Foreign tables can be used to run queries directly on data without inserting it into SQreamDB first. SQream DB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. Running queries directly on foreign data is most effectively used for one-off querying. If you are repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. From 42f8ece8d31be95a5c5a5c1c80afee8454cb78ee Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:26:20 +0300 Subject: [PATCH 1445/1892] JDBC 5.3.1 --- releases/4.5.rst | 2 +- releases/4.6.rst | 2 +- releases/4.7.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index d3b6982e3..b45a5cd72 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -23,7 +23,7 @@ Compatibility Matrix +---------------------------------+------------------------------------------------------------------------+ | Storage version | 50 | +---------------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.0.0 | +| Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 5.0.0 | diff --git a/releases/4.6.rst b/releases/4.6.rst index f368bab11..546483985 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -22,7 +22,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.2.0 | +| Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | diff --git a/releases/4.7.rst b/releases/4.7.rst index a12d8b28a..e7a2b1278 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -23,7 +23,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.2.0 | +| Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | | | * NodeJS | | | * .NET 3.0.2 | From d1d1c4fc2b6da9d453ff746267cbef7cb02f50fb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 09:49:20 +0300 Subject: [PATCH 1446/1892] Maintenance --- data_ingestion/ingesting_from_databases.rst | 24 +-- .../preparing_oracle_for_data_migration.rst | 6 +- external_storage_platforms/hdfs.rst | 178 ++++++++---------- 3 files changed, 97 insertions(+), 111 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 653043277..f35a4286e 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -528,18 +528,18 @@ In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGIN { "oracle": [ - { - "names": ["column1", "column2", "column3"], - "sqream": "bigint", - "java": "int", - "length": false - }, - { - "type": ["bigint","int","smallint","integer"], - "sqream": "bigint", - "java": "int", - "length": false - } + { + "names": ["column1", "column2", "column3"], + "sqream": "bigint", + "java": "int", + "length": false + }, + { + "type": ["bigint","int","smallint","integer"], + "sqream": "bigint", + "java": "int", + "length": false + } } .. code-block:: json diff --git a/data_ingestion/preparing_oracle_for_data_migration.rst b/data_ingestion/preparing_oracle_for_data_migration.rst index 307a2e545..973dce83f 100644 --- a/data_ingestion/preparing_oracle_for_data_migration.rst +++ b/data_ingestion/preparing_oracle_for_data_migration.rst @@ -4,10 +4,10 @@ Preparing Oracle for Data Migration *********************************** -The preparation of incremental and Change Data Capture (CDC) tables is essential for efficiently tracking and managing changes to data over time, enabling streamlined data synchronization and replication. +The preparation of incremental and Change Data Capture (CDC) tables is essential for efficiently tracking and managing changes to data over time, enabling streamlined data synchronization, and replication. -Preparing Change Data Capture Table -=================================== +Preparing CDC Tables +==================== 1. Prepare the data table: diff --git a/external_storage_platforms/hdfs.rst b/external_storage_platforms/hdfs.rst index 99bb465ea..bf4e59cc6 100644 --- a/external_storage_platforms/hdfs.rst +++ b/external_storage_platforms/hdfs.rst @@ -1,14 +1,12 @@ .. _hdfs: -.. _back_to_top_hdfs: - HDFS Environment -======================================= +================ .. _configuring_an_hdfs_environment_for_the_user_sqream: Configuring an HDFS Environment for the User **sqream** ----------------------------------------------------------- +------------------------------------------------------- This section describes how to configure an HDFS environment for the user **sqream** and is only relevant for users with an HDFS environment. @@ -18,33 +16,31 @@ This section describes how to configure an HDFS environment for the user **sqrea .. code-block:: console - $ vim /home/sqream/.bash_profile + vim /home/sqream/.bash_profile -.. - Comment: - see below; do we want to be a bit more specific on what changes we're talking about? .. code-block:: console - $ #PATH=$PATH:$HOME/.local/bin:$HOME/bin + #PATH=$PATH:$HOME/.local/bin:$HOME/bin - $ #export PATH + #export PATH - $ # PS1 - $ #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') - $ #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" + # PS1 + #MYIP=$(curl -s -XGET "http://ip-api.com/json" | python -c 'import json,sys; jstr=json.load(sys.stdin); print jstr["query"]') + #PS1="\[\e[01;32m\]\D{%F %T} \[\e[01;33m\]\u@\[\e[01;36m\]$MYIP \[\e[01;31m\]\w\[\e[37;36m\]\$ \[\e[1;37m\]" - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME + SQREAM_HOME=/usr/local/sqream + export SQREAM_HOME - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH + PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + export PATH 2. Verify that the edits have been made: @@ -56,7 +52,7 @@ This section describes how to configure an HDFS environment for the user **sqrea .. code-block:: console - $ hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ + hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ .. Comment: - @@ -76,24 +72,21 @@ This section describes how to configure an HDFS environment for the user **sqrea .. code-block:: console - $ #!/bin/bash + #!/bin/bash - $ SQREAM_HOME=/usr/local/sqream - $ export SQREAM_HOME + SQREAM_HOME=/usr/local/sqream + export SQREAM_HOME - $ export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk - $ export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop - $ export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` - $ export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR + export JAVA_HOME=${SQREAM_HOME}/hdfs/jdk + export HADOOP_INSTALL=${SQREAM_HOME}/hdfs/hadoop + export CLASSPATH=`${HADOOP_INSTALL}/bin/hadoop classpath --glob` + export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_INSTALL}/lib/native + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${SQREAM_HOME}/lib:$HADOOP_COMMON_LIB_NATIVE_DIR - $ PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin - $ export PATH - -:ref:`Back to top <back_to_top_hdfs>` + PATH=$PATH:$HOME/.local/bin:$HOME/bin:${SQREAM_HOME}/bin/:${JAVA_HOME}/bin:$HADOOP_INSTALL/bin + export PATH - .. _authenticate_hadoop_servers_that_require_kerberos: Authenticating Hadoop Servers that Require Kerberos @@ -105,99 +98,94 @@ If your Hadoop server requires Kerberos authentication, do the following: .. code-block:: console - $ kadmin -p root/admin@SQ.COM - $ addprinc sqream@SQ.COM + kadmin -p root/admin@SQ.COM + addprinc sqream@SQ.COM -2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run **kadmin.local**: +2. If you do not know yor Kerberos root credentials, connect to the Kerberos server as a root user with ssh and run: .. code-block:: console - $ kadmin.local + kadmin.local - Running **kadmin.local** does not require a password. + Running ``kadmin.local`` does not require a password. -3. If a password is not required, change your password to **sqream@SQ.COM**. +3. If a password is not required, change your password to ``sqream@SQ.COM``. .. code-block:: console - $ change_password sqream@SQ.COM + change_password sqream@SQ.COM 4. Connect to the hadoop name node using ssh: .. code-block:: console - $ cd /var/run/cloudera-scm-agent/process + cd /var/run/cloudera-scm-agent/process 5. Check the most recently modified content of the directory above: .. code-block:: console - $ ls -lrt + ls -lrt 6. Look for a recently updated folder containing the text **hdfs**. -The following is an example of the correct folder name: + The following is an example of the correct folder name: .. code-block:: console cd <number>-hdfs-<something> - This folder should contain a file named **hdfs.keytab** or another similar .keytab file. + This folder should contain a file named **hdfs.keytab** or a similar ``.keytab`` file. - -.. - Comment: - Does "something" need to be replaced with "file name" - - -7. Copy the .keytab file to user **sqream's** Home directory on the remote machines that you are planning to use Hadoop on. +7. Copy the ``.keytab`` file to user **sqream**'s Home directory on the remote machines that you are planning to use Hadoop on. -8. Copy the following files to the **sqream sqream@server:<sqream folder>/hdfs/hadoop/etc/hadoop:** directory: +8. Copy the following files to the ``sqream sqream@server:<sqream folder>/hdfs/hadoop/etc/hadoop:`` directory: * core-site.xml * hdfs-site.xml -9. Connect to the sqream server and verify that the .keytab file's owner is a user sqream and is granted the correct permissions: +9. Connect to the sqream server and verify that the ``.keytab`` file's owner is a user sqream and is granted the correct permissions: .. code-block:: console - $ sudo chown sqream:sqream /home/sqream/hdfs.keytab - $ sudo chmod 600 /home/sqream/hdfs.keytab + sudo chown sqream:sqream /home/sqream/hdfs.keytab + sudo chmod 600 /home/sqream/hdfs.keytab 10. Log into the sqream server. 11. Log in as the user **sqream**. -12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following .keytab file: +12. Navigate to the Home directory and check the name of a Kerberos principal represented by the following ``.keytab`` file: .. code-block:: console - $ klist -kt hdfs.keytab + klist -kt hdfs.keytab The following is an example of the correct output: .. code-block:: console - $ sqream@Host-121 ~ $ klist -kt hdfs.keytab - $ Keytab name: FILE:hdfs.keytab - $ KVNO Timestamp Principal - $ ---- ------------------- ------------------------------------------------------ - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM - $ 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + sqream@Host-121 ~ $ klist -kt hdfs.keytab + Keytab name: FILE:hdfs.keytab + KVNO Timestamp Principal + ---- ------------------- ------------------------------------------------------ + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 HTTP/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM + 5 09/15/2020 18:03:05 hdfs/nn1@SQ.COM 13. Verify that the hdfs service named **hdfs/nn1@SQ.COM** is shown in the generated output above. @@ -205,48 +193,46 @@ The following is an example of the correct folder name: .. code-block:: console - $ kinit -kt hdfs.keytab hdfs/nn1@SQ.COM + kinit -kt hdfs.keytab hdfs/nn1@SQ.COM 15. Check the output: .. code-block:: console - $ klist + klist The following is an example of the correct output: .. code-block:: console - $ Ticket cache: FILE:/tmp/krb5cc_1000 - $ Default principal: sqream@SQ.COM - $ - $ Valid starting Expires Service principal - $ 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM + Ticket cache: FILE:/tmp/krb5cc_1000 + Default principal: sqream@SQ.COM + + Valid starting Expires Service principal + 09/16/2020 13:44:18 09/17/2020 13:44:18 krbtgt/SQ.COM@SQ.COM 16. List the files located at the defined server name or IP address: .. code-block:: console - $ hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ + hadoop fs -ls hdfs://<hadoop server name or ip>:8020/ 17. Do one of the following: - * If the list below is output, continue with Step 16. + * If the list below is output, continue with the next step. * If the list is not output, verify that your environment has been set up correctly. -If any of the following are empty, verify that you followed :ref:`Step 6 <step_6>` in the **Configuring an HDFS Environment for the User sqream** section above correctly: + If any of the following are empty, verify that you followed :ref:`Step 6 <step_6>` in the **Configuring an HDFS Environment for the User sqream** section above correctly: .. code-block:: console - $ echo $JAVA_HOME - $ echo $SQREAM_HOME - $ echo $CLASSPATH - $ echo $HADOOP_COMMON_LIB_NATIVE_DIR - $ echo $LD_LIBRARY_PATH - $ echo $PATH + echo $JAVA_HOME + echo $SQREAM_HOME + echo $CLASSPATH + echo $HADOOP_COMMON_LIB_NATIVE_DIR + echo $LD_LIBRARY_PATH + echo $PATH 18. Verify that you copied the correct keytab file. 19. Review this procedure to verify that you have followed each step. - -:ref:`Back to top <back_to_top_hdfs>` \ No newline at end of file From 1b77170c2fda606759132e9648d8d61a5b8ae333 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 11:52:44 +0300 Subject: [PATCH 1447/1892] Update swap_table_names.rst --- .../sql_statements/utility_commands/swap_table_names.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst index 90ee73665..80daf14b9 100644 --- a/reference/sql/sql_statements/utility_commands/swap_table_names.rst +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -11,7 +11,7 @@ Syntax .. code-block:: postgres - SELECT SWAP_TABLE_NAMES (<schema_name>, <table1_name>, <table2_name>) + SELECT SWAP_TABLE_NAMES ('<schema_name>', '<table1_name>', '<table2_name>') Parameters ========== @@ -37,6 +37,9 @@ Examples .. code-block:: postgres + SELECT SWAP_TABLE_NAMES ('public', 'table1', 'table2'); Permissions -=========== \ No newline at end of file +=========== + +This utility command requires a ``CONNECT`` permission on the database level. \ No newline at end of file From 7110dc88e845b27207170d3c35c281a4e3423f87 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:14:13 +0300 Subject: [PATCH 1448/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 60 --------------------- 1 file changed, 60 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index f35a4286e..2699f15e6 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -541,66 +541,6 @@ In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGIN "length": false } } - -.. code-block:: json - - { - "type": ["char","nchar","varchar","varchar2","nvarchar","nvarchar2","character"], - "sqream": "text", - "java": "string", - "length": true - }, - { - "type": ["date","datetime"], - "sqream": "datetime", - "java": "datetime", - "length": false - }, - { - "type": ["timestamp"], - "sqream": "datetime", - "java": "timestamp", - "length": false - }, - { - "type": ["date"], - "sqream": "date", - "java": "datetime", - "length": false - }, - { - "type": ["boolean"], - "sqream": "bool", - "java": "boolean", - "length": false - }, - { - "type": ["number"], - "sqream": "numeric", - "java": "bigdecimal", - "length": true, - "prec": true - }, - { - "type": ["float","double"], - "sqream": "double", - "java": "double", - "length": false - }, - { - "type": ["clob"], - "sqream": "text", - "java": "clob", - "length": false - }, - { - "type": ["blob"], - "sqream": "text", - "java": "blob", - "length": false - } - ] - } --------------------------------- From 8b18b340624ee653cebe4a7fe0b9fce8661685e6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 13:38:43 +0300 Subject: [PATCH 1449/1892] Update preparing_oracle_for_data_migration.rst --- data_ingestion/preparing_oracle_for_data_migration.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_ingestion/preparing_oracle_for_data_migration.rst b/data_ingestion/preparing_oracle_for_data_migration.rst index 973dce83f..4b4238da2 100644 --- a/data_ingestion/preparing_oracle_for_data_migration.rst +++ b/data_ingestion/preparing_oracle_for_data_migration.rst @@ -48,7 +48,7 @@ Preparing CDC Tables ); -- Insert record to CDC_TABLES in the catalog - INSERT INTO SMSDW.CDC_TABLES ( + INSERT INTO public.CDC_TABLES ( DB_NAME, SCHEMA_NAME, TABLE_NAME, @@ -79,7 +79,7 @@ Preparing CDC Tables ); -- Insert record to primary keys table in the catalog - INSERT INTO SMSDW.CDC_TABLE_PRIMARY_KEYS ( + INSERT INTO public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME, SCHEMA_NAME, TABLE_NAME, @@ -175,7 +175,7 @@ Preparing Incremental Table .. code-block:: sql -- Insert record into CDC_TABLES in the catalog - INSERT INTO SMSDW.CDC_TABLES ( + INSERT INTO public.CDC_TABLES ( DB_NAME, SCHEMA_NAME, TABLE_NAME, @@ -198,7 +198,7 @@ Preparing Incremental Table ); -- Insert record into primary keys table in the catalog - INSERT INTO SMSDW.CDC_TABLE_PRIMARY_KEYS ( + INSERT INTO public.CDC_TABLE_PRIMARY_KEYS ( DB_NAME, SCHEMA_NAME, TABLE_NAME, From f7b5c336896122a1f9ff7879b0195eb4e2434e26 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 15:50:33 +0300 Subject: [PATCH 1450/1892] Maintenance --- .../current_method_configuration_levels.rst | 133 +++++++++--------- .../current_method_flag_types.rst | 49 ++++--- .../utility_commands/swap_table_names.rst | 2 +- 3 files changed, 98 insertions(+), 86 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 3f3f85c28..9d1deb976 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -56,12 +56,12 @@ Flag List ``33554432,67108864,134217728,268435456,536870912,786432000,107374,`` ``1824,1342177280,1610612736,1879048192,2147483648,2415919104,`` ``2684354560,2952790016,3221225472`` - * - ``cacheEvictionMilliseconds`` - - Anyone + * - ``blockNewVarcharObjects`` + - SUPERUSER - Session - - Sets how long the cache stores contents before being flushed. Allowed values: 1-4000000000. - - bigint - - ``2000`` + - Disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. + - boolean + - ``FALSE`` * - ``cacheDiskDir`` - Anyone - Session @@ -74,6 +74,12 @@ Flag List - Sets the amount of memory (GB) to be used by Spool on the disk. Allowed values: 0-4000000000. - bigint - ``128`` + * - ``cacheEvictionMilliseconds`` + - Anyone + - Session + - Sets how long the cache stores contents before being flushed. Allowed values: 1-4000000000. + - bigint + - ``2000`` * - ``cachePartitions`` - Anyone - Session @@ -104,72 +110,72 @@ Flag List - Sets the pad device memory allocations with safety buffers to catch out-of-bounds writes. - boolean - ``FALSE`` - * - ``clientReconnectionTimeout`` - - Anyone - - Cluster - - Reconnection time out for the system in seconds. - - Integer - - ``30`` * - ``compilerGetsOnlyUFs`` - SUPERUSER - Session - Sets the runtime to pass only utility functions names to the compiler. - boolean - ``FALSE`` + * - ``clientReconnectionTimeout`` + - Anyone + - Cluster + - Reconnection time out for the system in seconds. + - Integer + - ``30`` * - ``copyToRestrictUtf8`` - SUPERUSER - Session - Sets the custom bin size in the cache to enable high granularity bin control. - boolean - - ``FALSE`` - * - ``cpuReduceHashtableSize`` - - SUPERUSER - - Session - - Sets the hash table size of the CpuReduce. - - uint - - ``10000`` + - ``FALSE`` * - ``csvLimitRowLength`` - SUPERUSER - Cluster - Sets the maximum supported CSV row length. Allowed values: 1-4000000000 - uint - - ``100000`` + - ``100000`` * - ``cudaMemcpyMaxSizeBytes`` - SUPERUSER - Session - Sets the chunk size for copying from CPU to GPU. If set to 0, do not divide. - uint - - ``0`` + - ``0`` * - ``CudaMemcpySynchronous`` - SUPERUSER - Session - Indicates if copying from/to GPU is synchronous. - boolean - ``FALSE`` + * - ``defaultGracefulShutdownTimeoutMinutes`` + - SUPERUSER + - Cluster + - Used for setting the amount of time to pass before SQream performs a graceful server shutdown. Allowed values - 1-4000000000. Related flags: ``is_healer_on`` and ``healer_max_inactivity_hours`` + - bigint + - ``5`` * - ``developerMode`` - SUPERUSER - Session - Enables modifying R&D flags. - boolean - - ``FALSE`` + - ``FALSE`` * - ``enableDeviceDebugMessages`` - SUPERUSER - Session - Checks for CUDA errors after producing each chunk. - boolean - - ``FALSE`` + - ``FALSE`` * - ``enableLogDebug`` - SUPERUSER - Session - Enables creating and logging in the clientLogger_debug file. - boolean - - ``TRUE`` + - ``TRUE`` * - ``enableNvprofMarkers`` - SUPERUSER - Session - Activates the Nvidia profiler (nvprof) markers. - boolean - - ``FALSE`` + - ``FALSE`` * - ``endLogMessage`` - SUPERUSER - Session @@ -182,12 +188,6 @@ Flag List - Sets the minimum size in mebibytes of extents for table bulk data. - uint - ``20`` - * - ``externalTableBlobEstimate`` - - ? - - Session - - ? - - ? - - ? * - ``flipJoinOrder`` - Anyone - Session @@ -205,7 +205,7 @@ Flag List - Session - Increases the chunk size to reduce query speed. - boolean - - ``FALSE`` + - ``FALSE`` * - ``increaseMemFactors`` - SUPERUSER - Session @@ -238,42 +238,36 @@ Flag List - Sets the CPU to compress columns with size above (flag’s value) * (row count). - uint - ``120`` - * - ``maxPinnedPercentageOfTotalRAM`` - - SUPERUSER - - Session - - Sets the maximum percentage CPU RAM that pinned memory can use. - - uint - - ``70`` - * - ``memMergeBlobOffsetsCount`` - - SUPERUSER - - Session - - Sets the size of memory used during a query to trigger aborting the server. - - uint - - ``0`` * - ``memoryResetTriggerMB`` - SUPERUSER - Session - Sets the size of memory used during a query to trigger aborting the server. - uint - - ``0`` + - ``0`` * - ``mtRead`` - SUPERUSER - Session - Splits large reads to multiple smaller ones and executes them concurrently. - boolean - - ``FALSE`` + - ``FALSE`` * - ``mtReadWorkers`` - SUPERUSER - Session - Sets the number of workers to handle smaller concurrent reads. - uint - - ``30`` + - ``30`` * - ``orcImplicitCasts`` - SUPERUSER - Session - Sets the implicit cast in orc files, such as **int** to **tinyint** and vice versa. - boolean - ``TRUE`` + * - ``QueryTimeoutMinutes`` + - Anyone + - Session + - Terminates queries that have exceeded a predefined execution time limit, ranging from ``1`` to ``4,320`` minutes (72 hours). + - integer + - ``0`` (no query timeout) * - ``sessionTag`` - Anyone - Session @@ -291,40 +285,45 @@ Flag List - Session - Sets the timeout (seconds) for acquiring object locks before executing statements. - uint - - ``3`` + - ``3`` * - ``useLegacyDecimalLiterals`` - SUPERUSER - Session - Interprets decimal literals as **Double** instead of **Numeric**. Used to preserve legacy behavior in existing customers. - boolean - - ``FALSE`` - * - ``blockNewVarcharObjects`` + - ``FALSE`` + + + + + * - ``cpuReduceHashtableSize`` - SUPERUSER - Session - - Disables the creation of new tables, views, external tables containing Varchar columns, and the creation of user-defined functions with Varchar arguments or a Varchar return value. - - boolean - - ``FALSE`` - * - ``defaultGracefulShutdownTimeoutMinutes`` + - Sets the hash table size of the CpuReduce. + - uint + - ``10000`` + * - ``externalTableBlobEstimate`` + - ? + - Session + - ? + - ? + - ? + * - ``maxPinnedPercentageOfTotalRAM`` - SUPERUSER - - Cluster - - Used for setting the amount of time to pass before SQream performs a graceful server shutdown. Allowed values - 1-4000000000. Related flags: ``is_healer_on`` and ``healer_max_inactivity_hours`` - - bigint - - ``5`` - * - ``limitQueryMemoryGB`` + - Session + - Sets the maximum percentage CPU RAM that pinned memory can use. + - uint + - ``70`` + * - ``memMergeBlobOffsetsCount`` - SUPERUSER - - Cluster - - Prevents a query from processing more memory than the defined value. + - Session + - Sets the size of memory used during a query to trigger aborting the server. - uint - - ``100000`` + - ``0`` * - ``queueTimeoutMinutes`` - Anyone - Session - Terminates queries that have exceeded a predefined time limit in the queue. - integer - Default value: 0. Minimum values: 1 minute. Maximum value: 4320 minutes (72 hours) - * - ``QueryTimeoutMinutes`` - - Anyone - - Session - - Terminates queries that have exceeded a predefined execution time limit, ranging from ``1`` to ``4,320`` minutes (72 hours). - - integer - - ``0`` (no query timeout) + diff --git a/configuration_guides/current_method_flag_types.rst b/configuration_guides/current_method_flag_types.rst index d0b72b6a2..6135268c2 100644 --- a/configuration_guides/current_method_flag_types.rst +++ b/configuration_guides/current_method_flag_types.rst @@ -23,31 +23,36 @@ It is worth noting that the worker configuration file is not subject to frequent - Sets the percentage of total device memory used by your instance of SQream. - uint - ``90`` - * - ``healerMaxInactivityHours`` + * - ``healerDetectionFrequencySeconds`` - SUPERUSER - - Used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. - - bigint - - ``5`` + - Determines the default frequency for the healer to check that its conditions are met. + - + - ``86,400`` (seconds) * - ``isHealerOn`` - SUPERUSER - Enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``healerMaxInactivityHours`` flag setting. - boolean - - ``TRUE`` - * - ``limitQueryMemoryGB`` - - Anyone - - Prevents a query from processing more memory than the defined value. - - uint - - ``100000`` + - ``TRUE`` + * - ``logFormat`` + - SUPERUSER + - Determines the file format of the log files. Format may by ``csv``, ``json``, or both (all logs will be written saved both as ``csv`` and ``json`` files) + - string + - ``csv`` * - ``loginMaxRetries`` - SUPERUSER - Sets the permitted log-in attempts. - bigint - - ``5`` + - ``5`` * - ``machineIP`` - SUPERUSER - Enables you to manually set the reported IP. - string - - ``127.0.0.1`` + - ``127.0.0.1`` + * - ``maxConnectionInactivitySeconds`` + - SUPERUSER + - Determines the maximum period of session idleness, after which the connection is terminated. + - bigint + - ``86,400`` (seconds) * - ``maxConnections`` - SUPERUSER - Defines the maximum allowed connections per Worker. @@ -57,17 +62,25 @@ It is worth noting that the worker configuration file is not subject to frequent - SUPERUSER - Sets the port used to connect to the metadata server. SQream recommends using port ranges above 1024 because ports below 1024 are usually reserved, although there are no strict limitations. You can use any positive number (1 - 65535) while setting this flag. - uint - - ``3105`` + - ``3105`` * - ``useConfigIP`` - SUPERUSER - Activates the machineIP (``TRUE``). Setting this flag to ``FALSE`` ignores the machineIP and automatically assigns a local network IP. This cannot be activated in a cloud scenario (on-premises only). - boolean - - ``FALSE`` - * - ``logFormat`` + - ``FALSE`` + + + * - ``healerMaxInactivityHours`` - SUPERUSER - - Determines the file format of the log files. Format may by ``csv``, ``json``, or both (all logs will be written saved both as ``csv`` and ``json`` files) - - string - - ``csv`` + - Used for defining the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. + - bigint + - ``5`` + * - ``limitQueryMemoryGB`` + - Anyone + - Prevents a query from processing more memory than the defined value. + - uint + - ``100000`` + diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst index 80daf14b9..fcb0d17a4 100644 --- a/reference/sql/sql_statements/utility_commands/swap_table_names.rst +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -42,4 +42,4 @@ Examples Permissions =========== -This utility command requires a ``CONNECT`` permission on the database level. \ No newline at end of file +This utility command requires a permission to execute utility functions. \ No newline at end of file From a62cdbe2bf2fac58df1e0aa309c181b2ac79a803 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 10 Jul 2024 16:10:49 +0300 Subject: [PATCH 1451/1892] SQLoader --- data_ingestion/index.rst | 8 ++------ data_ingestion/ingesting_from_databases.rst | 5 ----- .../preparing_oracle_for_data_migration.rst | 2 +- data_ingestion/sqloader.rst | 18 ++++++++++++++++++ 4 files changed, 21 insertions(+), 12 deletions(-) create mode 100644 data_ingestion/sqloader.rst diff --git a/data_ingestion/index.rst b/data_ingestion/index.rst index ab4d25111..b80f9a8c6 100644 --- a/data_ingestion/index.rst +++ b/data_ingestion/index.rst @@ -12,10 +12,7 @@ The **Data Ingestion Sources** page provides information about the following: * :ref:`parquet` * :ref:`orc` * :ref:`json` -* Loading from external databases: - - * :ref:`SQLoader As a Service<sqloader_as_a_service>` - * :ref:`SQLoader As a Process<ingesting_from_databases>` +* :ref:`sqloader` .. toctree:: :maxdepth: 1 @@ -28,7 +25,6 @@ The **Data Ingestion Sources** page provides information about the following: parquet orc json - sqloader_as_a_service - ingesting_from_databases + sqloader diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 2699f15e6..251255f76 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -671,8 +671,3 @@ Loading data into a table using a the ``filter`` parameter: -.. toctree:: - :maxdepth: 1 - :glob: - - preparing_oracle_for_data_migration diff --git a/data_ingestion/preparing_oracle_for_data_migration.rst b/data_ingestion/preparing_oracle_for_data_migration.rst index 4b4238da2..86124baed 100644 --- a/data_ingestion/preparing_oracle_for_data_migration.rst +++ b/data_ingestion/preparing_oracle_for_data_migration.rst @@ -1,4 +1,4 @@ -.. _preparing_oracle_for_data_migration +.. _preparing_oracle_for_data_migration: *********************************** Preparing Oracle for Data Migration diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst new file mode 100644 index 000000000..3c16ff6d3 --- /dev/null +++ b/data_ingestion/sqloader.rst @@ -0,0 +1,18 @@ +.. _sqloader: + +******** +SQLoader +******** + +SQLoader enables you to load data into SQreamDB from other DBMS and DBaaS. You may use it as a :ref:`process<ingesting_from_databases>` or as a :ref:`service<sqloader_as_a_service>`. + +For loading data from Oracle, check out this :ref:`preparing_oracle_for_data_migration` + +.. toctree:: + :maxdepth: 1 + :glob: + :hidden: + + sqloader_as_a_service + ingesting_from_databases + preparing_oracle_for_data_migration \ No newline at end of file From 8795c1ad36ed7988a961e2d4d913d9f6eff77e76 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 07:54:53 +0300 Subject: [PATCH 1452/1892] :orphan: --- configuration_guides/bin_sizes.rst | 2 ++ configuration_guides/block_new_varchar_objects.rst | 2 ++ configuration_guides/cache_disk_dir.rst | 2 ++ configuration_guides/cache_disk_gb.rst | 2 ++ configuration_guides/cache_eviction_milliseconds.rst | 2 ++ configuration_guides/cache_partitions.rst | 2 ++ configuration_guides/cache_persistent_dir.rst | 2 ++ configuration_guides/cache_persistent_gb.rst | 2 ++ configuration_guides/cache_ram_gb.rst | 2 ++ configuration_guides/check_cuda_memory.rst | 2 ++ configuration_guides/compiler_gets_only_ufs.rst | 2 ++ configuration_guides/configuring_sqream.rst | 2 ++ configuration_guides/copy_to_restrict_utf8.rst | 2 ++ configuration_guides/csv_limit_row_length.rst | 2 ++ configuration_guides/cuda_mem_cpy_max_size_bytes.rst | 2 ++ configuration_guides/cuda_mem_cpy_synchronous.rst | 2 ++ configuration_guides/cuda_mem_quota.rst | 3 +++ .../current_method_showing_all_flags_in_the_catalog_table.rst | 2 ++ .../default_graceful_shutdown_timeout_minutes.rst | 2 ++ configuration_guides/developer_mode.rst | 2 ++ configuration_guides/enable_device_debug_messages.rst | 2 ++ configuration_guides/enable_log_debug.rst | 2 ++ configuration_guides/enable_nv_prof_markers.rst | 2 ++ configuration_guides/end_log_message.rst | 2 ++ configuration_guides/extent_storage_file_size_mb.rst | 2 ++ configuration_guides/flip_join_order.rst | 2 ++ configuration_guides/gather_mem_stat.rst | 2 ++ configuration_guides/graceful_shutdown.rst | 2 ++ configuration_guides/healer_action_cleanup_connection.rst | 2 ++ configuration_guides/healer_action_graceful_shutdown.rst | 2 ++ configuration_guides/healer_detection_frequency_seconds.rst | 2 ++ configuration_guides/healer_run_action_automatically.rst | 2 ++ configuration_guides/increase_chunk_size_before_reduce.rst | 2 ++ configuration_guides/increase_mem_factors.rst | 2 ++ configuration_guides/is_healer_on.rst | 2 ++ configuration_guides/level_db_write_buffer_size.rst | 2 ++ configuration_guides/limit_query_memory_gb.rst | 2 ++ configuration_guides/log_sys_level.rst | 2 ++ configuration_guides/login_max_retries.rst | 2 ++ configuration_guides/machine_ip.rst | 2 ++ configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst | 2 ++ configuration_guides/max_connection_inactivity_seconds.rst | 2 ++ configuration_guides/max_connections.rst | 2 ++ configuration_guides/max_statement_inactivity_seconds.rst | 2 ++ configuration_guides/memory_reset_trigger_mb.rst | 2 ++ configuration_guides/metadata_server_port.rst | 2 ++ configuration_guides/mt_read.rst | 2 ++ configuration_guides/mt_read_workers.rst | 2 ++ configuration_guides/orc_implicit_casts.rst | 2 ++ configuration_guides/query_timeout_minutes.rst | 2 ++ configuration_guides/session_tag.rst | 2 ++ configuration_guides/spool_memory_gb.rst | 3 +++ configuration_guides/statement_lock_timeout.rst | 3 +++ configuration_guides/use_config_ip.rst | 3 +++ configuration_guides/use_legacy_decimal_literals.rst | 3 +++ configuration_guides/use_legacy_string_literals.rst | 3 +++ 56 files changed, 118 insertions(+) diff --git a/configuration_guides/bin_sizes.rst b/configuration_guides/bin_sizes.rst index 8338dcc35..94db3fffb 100644 --- a/configuration_guides/bin_sizes.rst +++ b/configuration_guides/bin_sizes.rst @@ -1,3 +1,5 @@ +:orphan: + .. _bin_sizes: **************** diff --git a/configuration_guides/block_new_varchar_objects.rst b/configuration_guides/block_new_varchar_objects.rst index d78fa8e98..acae66096 100644 --- a/configuration_guides/block_new_varchar_objects.rst +++ b/configuration_guides/block_new_varchar_objects.rst @@ -1,3 +1,5 @@ +:orphan: + .. _block_new_varchar_objects: **************************** diff --git a/configuration_guides/cache_disk_dir.rst b/configuration_guides/cache_disk_dir.rst index 9e0fd4f76..5b8ff0fb4 100644 --- a/configuration_guides/cache_disk_dir.rst +++ b/configuration_guides/cache_disk_dir.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_disk_dir: ************************************************** diff --git a/configuration_guides/cache_disk_gb.rst b/configuration_guides/cache_disk_gb.rst index eb3d530cd..fc02e3065 100644 --- a/configuration_guides/cache_disk_gb.rst +++ b/configuration_guides/cache_disk_gb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_disk_gb: ************************* diff --git a/configuration_guides/cache_eviction_milliseconds.rst b/configuration_guides/cache_eviction_milliseconds.rst index 129d6281b..8876959af 100644 --- a/configuration_guides/cache_eviction_milliseconds.rst +++ b/configuration_guides/cache_eviction_milliseconds.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_eviction_milliseconds: ************************* diff --git a/configuration_guides/cache_partitions.rst b/configuration_guides/cache_partitions.rst index 0637e347c..4e2182c34 100644 --- a/configuration_guides/cache_partitions.rst +++ b/configuration_guides/cache_partitions.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_partitions: ************************* diff --git a/configuration_guides/cache_persistent_dir.rst b/configuration_guides/cache_persistent_dir.rst index fbc7eb147..f434cb173 100644 --- a/configuration_guides/cache_persistent_dir.rst +++ b/configuration_guides/cache_persistent_dir.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_persistent_dir: ****************************************************** diff --git a/configuration_guides/cache_persistent_gb.rst b/configuration_guides/cache_persistent_gb.rst index ff223b299..35f0df896 100644 --- a/configuration_guides/cache_persistent_gb.rst +++ b/configuration_guides/cache_persistent_gb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_persistent_gb: ***************************************** diff --git a/configuration_guides/cache_ram_gb.rst b/configuration_guides/cache_ram_gb.rst index bf91ddc21..d68f7896f 100644 --- a/configuration_guides/cache_ram_gb.rst +++ b/configuration_guides/cache_ram_gb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cache_ram_gb: ***************************** diff --git a/configuration_guides/check_cuda_memory.rst b/configuration_guides/check_cuda_memory.rst index 84eec3f07..e826bdeef 100644 --- a/configuration_guides/check_cuda_memory.rst +++ b/configuration_guides/check_cuda_memory.rst @@ -1,3 +1,5 @@ +:orphan: + .. _check_cuda_memory: ************************* diff --git a/configuration_guides/compiler_gets_only_ufs.rst b/configuration_guides/compiler_gets_only_ufs.rst index d7d3d9151..2a48b0cc8 100644 --- a/configuration_guides/compiler_gets_only_ufs.rst +++ b/configuration_guides/compiler_gets_only_ufs.rst @@ -1,3 +1,5 @@ +:orphan: + .. _compiler_gets_only_ufs: ************************************* diff --git a/configuration_guides/configuring_sqream.rst b/configuration_guides/configuring_sqream.rst index bbaffc9e1..9c74d2a02 100644 --- a/configuration_guides/configuring_sqream.rst +++ b/configuration_guides/configuring_sqream.rst @@ -1,3 +1,5 @@ +:orphan: + .. _configuring_sqream: ************************* diff --git a/configuration_guides/copy_to_restrict_utf8.rst b/configuration_guides/copy_to_restrict_utf8.rst index 66ee4ab72..62cbd9b4f 100644 --- a/configuration_guides/copy_to_restrict_utf8.rst +++ b/configuration_guides/copy_to_restrict_utf8.rst @@ -1,3 +1,5 @@ +:orphan: + .. _copy_to_restrict_utf8: ************************************* diff --git a/configuration_guides/csv_limit_row_length.rst b/configuration_guides/csv_limit_row_length.rst index a4558f923..318318df2 100644 --- a/configuration_guides/csv_limit_row_length.rst +++ b/configuration_guides/csv_limit_row_length.rst @@ -1,3 +1,5 @@ +:orphan: + .. _csv_limit_row_length: ****************************** diff --git a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst index 9c7de07ce..dccc32e3b 100644 --- a/configuration_guides/cuda_mem_cpy_max_size_bytes.rst +++ b/configuration_guides/cuda_mem_cpy_max_size_bytes.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cuda_mem_cpy_max_size_bytes: ********************************************** diff --git a/configuration_guides/cuda_mem_cpy_synchronous.rst b/configuration_guides/cuda_mem_cpy_synchronous.rst index adbedce48..fcba5f734 100644 --- a/configuration_guides/cuda_mem_cpy_synchronous.rst +++ b/configuration_guides/cuda_mem_cpy_synchronous.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cuda_mem_cpy_synchronous: **************************** diff --git a/configuration_guides/cuda_mem_quota.rst b/configuration_guides/cuda_mem_quota.rst index b659c566d..a738e3477 100644 --- a/configuration_guides/cuda_mem_quota.rst +++ b/configuration_guides/cuda_mem_quota.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _cuda_mem_quota: **************************************************** diff --git a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst index 7400684f7..f47432e64 100644 --- a/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst +++ b/configuration_guides/current_method_showing_all_flags_in_the_catalog_table.rst @@ -1,3 +1,5 @@ +:orphan: + .. _current_method_showing_all_flags_in_the_catalog_table: ************************************** diff --git a/configuration_guides/default_graceful_shutdown_timeout_minutes.rst b/configuration_guides/default_graceful_shutdown_timeout_minutes.rst index dbdedcfcd..20e27302c 100644 --- a/configuration_guides/default_graceful_shutdown_timeout_minutes.rst +++ b/configuration_guides/default_graceful_shutdown_timeout_minutes.rst @@ -1,3 +1,5 @@ +:orphan: + .. _default_graceful_shutdown_timeout_minutes: ***************************************** diff --git a/configuration_guides/developer_mode.rst b/configuration_guides/developer_mode.rst index 7b78e2806..ebd9873f0 100644 --- a/configuration_guides/developer_mode.rst +++ b/configuration_guides/developer_mode.rst @@ -1,3 +1,5 @@ +:orphan: + .. _developer_mode: ********************************** diff --git a/configuration_guides/enable_device_debug_messages.rst b/configuration_guides/enable_device_debug_messages.rst index ac9ddb09f..9f83211e7 100644 --- a/configuration_guides/enable_device_debug_messages.rst +++ b/configuration_guides/enable_device_debug_messages.rst @@ -1,3 +1,5 @@ +:orphan: + .. _enable_device_debug_messages: **************************************** diff --git a/configuration_guides/enable_log_debug.rst b/configuration_guides/enable_log_debug.rst index 6706de6a9..c8e922ffc 100644 --- a/configuration_guides/enable_log_debug.rst +++ b/configuration_guides/enable_log_debug.rst @@ -1,3 +1,5 @@ +:orphan: + .. _enable_log_debug: ************************************************ diff --git a/configuration_guides/enable_nv_prof_markers.rst b/configuration_guides/enable_nv_prof_markers.rst index 6d1d0422d..8689b8bd1 100644 --- a/configuration_guides/enable_nv_prof_markers.rst +++ b/configuration_guides/enable_nv_prof_markers.rst @@ -1,3 +1,5 @@ +:orphan: + .. _enable_nv_prof_markers: ************************************** diff --git a/configuration_guides/end_log_message.rst b/configuration_guides/end_log_message.rst index 60df1a6a3..088cc1e30 100644 --- a/configuration_guides/end_log_message.rst +++ b/configuration_guides/end_log_message.rst @@ -1,3 +1,5 @@ +:orphan: + .. _end_log_message: ************************************ diff --git a/configuration_guides/extent_storage_file_size_mb.rst b/configuration_guides/extent_storage_file_size_mb.rst index cdbce6b6c..84d762563 100644 --- a/configuration_guides/extent_storage_file_size_mb.rst +++ b/configuration_guides/extent_storage_file_size_mb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _extent_storage_file_size_mb: *********************************************** diff --git a/configuration_guides/flip_join_order.rst b/configuration_guides/flip_join_order.rst index d160beb5a..72aa365a8 100644 --- a/configuration_guides/flip_join_order.rst +++ b/configuration_guides/flip_join_order.rst @@ -1,3 +1,5 @@ +:orphan: + .. _flip_join_order: ************************************** diff --git a/configuration_guides/gather_mem_stat.rst b/configuration_guides/gather_mem_stat.rst index 19756ff2a..53fe275b3 100644 --- a/configuration_guides/gather_mem_stat.rst +++ b/configuration_guides/gather_mem_stat.rst @@ -1,3 +1,5 @@ +:orphan: + .. _gather_mem_stat: ************************************************* diff --git a/configuration_guides/graceful_shutdown.rst b/configuration_guides/graceful_shutdown.rst index ba9c8a57f..839170ce5 100644 --- a/configuration_guides/graceful_shutdown.rst +++ b/configuration_guides/graceful_shutdown.rst @@ -1,3 +1,5 @@ +:orphan: + .. _graceful_shutdown: ************************************ diff --git a/configuration_guides/healer_action_cleanup_connection.rst b/configuration_guides/healer_action_cleanup_connection.rst index 180d920df..2d0c9f7e1 100644 --- a/configuration_guides/healer_action_cleanup_connection.rst +++ b/configuration_guides/healer_action_cleanup_connection.rst @@ -1,3 +1,5 @@ +:orphan: + .. _healer_action_cleanup_connection: ******************************** diff --git a/configuration_guides/healer_action_graceful_shutdown.rst b/configuration_guides/healer_action_graceful_shutdown.rst index 7787af229..2de9bb81c 100644 --- a/configuration_guides/healer_action_graceful_shutdown.rst +++ b/configuration_guides/healer_action_graceful_shutdown.rst @@ -1,3 +1,5 @@ +:orphan: + .. _healer_action_graceful_shutdown: ******************************* diff --git a/configuration_guides/healer_detection_frequency_seconds.rst b/configuration_guides/healer_detection_frequency_seconds.rst index f64497600..22283272e 100644 --- a/configuration_guides/healer_detection_frequency_seconds.rst +++ b/configuration_guides/healer_detection_frequency_seconds.rst @@ -1,3 +1,5 @@ +:orphan: + .. _healer_detection_frequency_seconds: ********************************** diff --git a/configuration_guides/healer_run_action_automatically.rst b/configuration_guides/healer_run_action_automatically.rst index afb0578f9..b1a69fed5 100644 --- a/configuration_guides/healer_run_action_automatically.rst +++ b/configuration_guides/healer_run_action_automatically.rst @@ -1,3 +1,5 @@ +:orphan: + .. _healer_run_action_automatically: ******************************* diff --git a/configuration_guides/increase_chunk_size_before_reduce.rst b/configuration_guides/increase_chunk_size_before_reduce.rst index a817c7bff..8768f124e 100644 --- a/configuration_guides/increase_chunk_size_before_reduce.rst +++ b/configuration_guides/increase_chunk_size_before_reduce.rst @@ -1,3 +1,5 @@ +:orphan: + .. _increase_chunk_size_before_reduce: ******************************************* diff --git a/configuration_guides/increase_mem_factors.rst b/configuration_guides/increase_mem_factors.rst index f3421a7b5..ac58ae393 100644 --- a/configuration_guides/increase_mem_factors.rst +++ b/configuration_guides/increase_mem_factors.rst @@ -1,3 +1,5 @@ +:orphan: + .. _increase_mem_factors: ************************************************ diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst index add20259f..1399682df 100644 --- a/configuration_guides/is_healer_on.rst +++ b/configuration_guides/is_healer_on.rst @@ -1,3 +1,5 @@ +:orphan: + .. _is_healer_on: ************ diff --git a/configuration_guides/level_db_write_buffer_size.rst b/configuration_guides/level_db_write_buffer_size.rst index c3cd60516..53e4cad57 100644 --- a/configuration_guides/level_db_write_buffer_size.rst +++ b/configuration_guides/level_db_write_buffer_size.rst @@ -1,3 +1,5 @@ +:orphan: + .. _level_db_write_buffer_size: ************************* diff --git a/configuration_guides/limit_query_memory_gb.rst b/configuration_guides/limit_query_memory_gb.rst index 7a27bd3ee..2208954bd 100644 --- a/configuration_guides/limit_query_memory_gb.rst +++ b/configuration_guides/limit_query_memory_gb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _limit_query_memory_gb: ************************************* diff --git a/configuration_guides/log_sys_level.rst b/configuration_guides/log_sys_level.rst index 07e1e5800..23b22da72 100644 --- a/configuration_guides/log_sys_level.rst +++ b/configuration_guides/log_sys_level.rst @@ -1,3 +1,5 @@ +:orphan: + .. _log_sys_level: ************************* diff --git a/configuration_guides/login_max_retries.rst b/configuration_guides/login_max_retries.rst index 90f5e077f..2d7161a83 100644 --- a/configuration_guides/login_max_retries.rst +++ b/configuration_guides/login_max_retries.rst @@ -1,3 +1,5 @@ +:orphan: + .. _login_max_retries: *********************************** diff --git a/configuration_guides/machine_ip.rst b/configuration_guides/machine_ip.rst index 56ecb8edb..8aaeb79bc 100644 --- a/configuration_guides/machine_ip.rst +++ b/configuration_guides/machine_ip.rst @@ -1,3 +1,5 @@ +:orphan: + .. _machine_ip: ************************************* diff --git a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst index c3e026835..dd57d341f 100644 --- a/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst +++ b/configuration_guides/max_avg_blob_size_to_compress_on_gpu.rst @@ -1,3 +1,5 @@ +:orphan: + .. _max_avg_blob_size_to_compress_on_gpu: *************************************** diff --git a/configuration_guides/max_connection_inactivity_seconds.rst b/configuration_guides/max_connection_inactivity_seconds.rst index 195660df8..fab0e5951 100644 --- a/configuration_guides/max_connection_inactivity_seconds.rst +++ b/configuration_guides/max_connection_inactivity_seconds.rst @@ -1,3 +1,5 @@ +:orphan: + .. _max_connection_inactivity_seconds: ********************************* diff --git a/configuration_guides/max_connections.rst b/configuration_guides/max_connections.rst index 7c442ecb5..0f4ea10b2 100644 --- a/configuration_guides/max_connections.rst +++ b/configuration_guides/max_connections.rst @@ -1,3 +1,5 @@ +:orphan: + .. _max_connections: ******************************** diff --git a/configuration_guides/max_statement_inactivity_seconds.rst b/configuration_guides/max_statement_inactivity_seconds.rst index 7a1483f6c..7c4d148a2 100644 --- a/configuration_guides/max_statement_inactivity_seconds.rst +++ b/configuration_guides/max_statement_inactivity_seconds.rst @@ -1,3 +1,5 @@ +:orphan: + .. _max_statement_inactivity_seconds: ******************************** diff --git a/configuration_guides/memory_reset_trigger_mb.rst b/configuration_guides/memory_reset_trigger_mb.rst index def2c02df..b9952670b 100644 --- a/configuration_guides/memory_reset_trigger_mb.rst +++ b/configuration_guides/memory_reset_trigger_mb.rst @@ -1,3 +1,5 @@ +:orphan: + .. _memory_reset_trigger_mb: *********************************** diff --git a/configuration_guides/metadata_server_port.rst b/configuration_guides/metadata_server_port.rst index 084359c52..0600a3a0e 100644 --- a/configuration_guides/metadata_server_port.rst +++ b/configuration_guides/metadata_server_port.rst @@ -1,3 +1,5 @@ +:orphan: + .. _metadata_server_port: ************************************************** diff --git a/configuration_guides/mt_read.rst b/configuration_guides/mt_read.rst index d56584536..0c54ec07d 100644 --- a/configuration_guides/mt_read.rst +++ b/configuration_guides/mt_read.rst @@ -1,3 +1,5 @@ +:orphan: + .. _mt_read: ********************************************** diff --git a/configuration_guides/mt_read_workers.rst b/configuration_guides/mt_read_workers.rst index 52a9ef07b..033bf759e 100644 --- a/configuration_guides/mt_read_workers.rst +++ b/configuration_guides/mt_read_workers.rst @@ -1,3 +1,5 @@ +:orphan: + .. _mt_read_workers: ************************************************ diff --git a/configuration_guides/orc_implicit_casts.rst b/configuration_guides/orc_implicit_casts.rst index 39d4d6d6c..1c09f7a97 100644 --- a/configuration_guides/orc_implicit_casts.rst +++ b/configuration_guides/orc_implicit_casts.rst @@ -1,3 +1,5 @@ +:orphan: + .. _orc_implicit_casts: *********************************** diff --git a/configuration_guides/query_timeout_minutes.rst b/configuration_guides/query_timeout_minutes.rst index f553d8127..114ee5720 100644 --- a/configuration_guides/query_timeout_minutes.rst +++ b/configuration_guides/query_timeout_minutes.rst @@ -1,3 +1,5 @@ +:orphan: + .. _query_timeout_minutes: ************************************************** diff --git a/configuration_guides/session_tag.rst b/configuration_guides/session_tag.rst index 12a98f01c..534e73f09 100644 --- a/configuration_guides/session_tag.rst +++ b/configuration_guides/session_tag.rst @@ -1,3 +1,5 @@ +:orphan: + .. _session_tag: ************************* diff --git a/configuration_guides/spool_memory_gb.rst b/configuration_guides/spool_memory_gb.rst index 5ed3264b1..269dfbd5f 100644 --- a/configuration_guides/spool_memory_gb.rst +++ b/configuration_guides/spool_memory_gb.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _spool_memory_gb: ************************* diff --git a/configuration_guides/statement_lock_timeout.rst b/configuration_guides/statement_lock_timeout.rst index bcb7cdd60..5697cebdf 100644 --- a/configuration_guides/statement_lock_timeout.rst +++ b/configuration_guides/statement_lock_timeout.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _statement_lock_timeout: ********************************************************************* diff --git a/configuration_guides/use_config_ip.rst b/configuration_guides/use_config_ip.rst index 3d80204c7..43edccd98 100644 --- a/configuration_guides/use_config_ip.rst +++ b/configuration_guides/use_config_ip.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _use_config_ip: ************************** diff --git a/configuration_guides/use_legacy_decimal_literals.rst b/configuration_guides/use_legacy_decimal_literals.rst index e839e69ed..a52b9fb87 100644 --- a/configuration_guides/use_legacy_decimal_literals.rst +++ b/configuration_guides/use_legacy_decimal_literals.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _use_legacy_decimal_literals: ********************************************************** diff --git a/configuration_guides/use_legacy_string_literals.rst b/configuration_guides/use_legacy_string_literals.rst index 325c95713..165c02667 100644 --- a/configuration_guides/use_legacy_string_literals.rst +++ b/configuration_guides/use_legacy_string_literals.rst @@ -1,3 +1,6 @@ +:orphan: + + .. _use_legacy_string_literals: **************************** From 926991fd117e224e5ea6743a2cea6d8b4c9489a9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 08:29:47 +0300 Subject: [PATCH 1453/1892] swap table name --- .../sql/sql_statements/utility_commands/swap_table_names.rst | 2 +- releases/4.5.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst index fcb0d17a4..226ab1166 100644 --- a/reference/sql/sql_statements/utility_commands/swap_table_names.rst +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -4,7 +4,7 @@ SWAP TABLE NAMES **************** -The ``SWAP_TABLE_NAMES`` command enables you to swap the names of two tables contained within a schema. +The ``SWAP_TABLE_NAMES`` command enables you to swap the names of two tables within a schema. Syntax ====== diff --git a/releases/4.5.rst b/releases/4.5.rst index b45a5cd72..753418b99 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -42,6 +42,8 @@ New Features and Enhancements ► Optimized ``JOIN`` operation for improved performance with large tables +► The new :ref:`swap_table_names` utility function enables you to swap the names of two tables within a schema. + Known Issues ------------ From 8d8fffc90cfba2a36855d4f1ebb59d77579d5249 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:45:01 +0300 Subject: [PATCH 1454/1892] Foreign Table Auto Mapping --- data_ingestion/json.rst | 2 +- operational_guides/foreign_tables.rst | 25 +++++++++---------- .../ddl_commands/create_foreign_table.rst | 11 ++++---- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/data_ingestion/json.rst b/data_ingestion/json.rst index eec94c891..cb41322eb 100644 --- a/data_ingestion/json.rst +++ b/data_ingestion/json.rst @@ -1 +1 @@ -.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQream DB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQream. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- You may let SQream DB automatically infer the schema of a foreign table when using ``json_fdw``. For more information, follow the :ref:`CREATE FOREIGN TABLE<create_foreign_table>` page. Automatic Schema Inference example: .. code-block:: postgres CREATE FOREIGN TABLE nba WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY nba FROM WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY nba TO WRAPPER json_fdw OPTIONS (location = 's3://sqream-docs/nba.json'); When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t (id int not null) WRAPPER json_fdw OPTIONS (location = 'sqream-docs.json'); The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS (LOCATION = 'sqream-docs.json'); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file +.. _json: **** JSON **** JSON (Java Script Object Notation) is used both as a file format and as a serialization method. The JSON file format is flexible and is commonly used for dynamic, nested, and semi-structured data representations. The SQreamDB JSON parser supports the `RFC 8259 <https://datatracker.ietf.org/doc/html/rfc8259>`_ data interchange format and supports both JSON objects and JSON object arrays. Only the `JSON Lines <https://jsonlines.org/>`_ data format is supported by SQreamDB. .. contents:: :local: :depth: 1 Foreign Data Wrapper Prerequisites =================================== Before proceeding, ensure the following Foreign Data Wrapper (FDW) prerequisites: * **File Existence:** Verify that the file you are ingesting data from exists at the specified path. * **Path Accuracy:** Confirm that all path elements are present and correctly spelled. Any inaccuracies may lead to data retrieval issues. * **Bucket Access Permissions:** Ensure that you have the necessary access permissions to the bucket from which you are ingesting data. Lack of permissions can hinder the data retrieval process. * **Wildcard Accuracy:** If using wildcards, double-check their spelling and configuration. Misconfigured wildcards may result in unintended data ingestion. Making JSON Files Accessible to Workers ======================================= To give workers access to files, every node in your system must have access to the storage being used. The following are required for JSON files to be accessible to workers: * For files hosted on NFS, ensure that the mount is accessible from all servers. * For HDFS, ensure that SQream servers have access to the HDFS NameNode with the correct **user-id**. For more information, see :ref:`hdfs`. * For S3, ensure network access to the S3 endpoint. For more information, see :ref:`s3`. For more information about configuring worker access, see :ref:`workload_manager`. Mapping between JSON and SQream =============================== A JSON field consists of a key name and a value. Key names, which are case sensitive, are mapped to SQream columns. Key names which do not have corresponding SQream table columns are treated as errors by default, unless the ``IGNORE_EXTRA_FIELDS`` parameter is set to ``true``, in which case these key names will be ignored during the mapping process. SQream table columns which do not have corresponding JSON fields are automatically set to ``null`` as a value. Values may be one of the following reserved words (lower-case): ``false``, ``true``, or ``null``, or any of the following data types: .. list-table:: :widths: auto :header-rows: 1 * - JSON Data Type - Representation in SQream * - Number - ``TINYINT``, ``SMALLINT``, ``INT``, ``BIGINT``, ``FLOAT``, ``DOUBLE``, ``NUMERIC`` * - String - ``TEXT`` * - JSON Literal - ``NULL``, ``TRUE``, ``FALSE`` * - JSON Array - ``TEXT`` * - JSON Object - ``TEXT`` Character Escaping ------------------ The ASCII 10 character (LF) marks the end of JSON objects. Use ``\\n`` to escape the ``\n`` character when you do not mean it be a new line. Ingesting JSON Data into SQream =============================== .. contents:: In this topic: :local: Syntax ------- To access JSON files, use the ``json_fdw`` with a ``COPY FROM``, ``COPY TO``, or ``CREATE FOREIGN TABLE`` statement. The Foreign Data Wrapper (FDW) syntax is: .. code-block:: json_fdw [OPTIONS(option=value[,...])] Parameters ---------- The following parameters are supported by ``json_fdw``: .. list-table:: :widths: auto :header-rows: 1 * - Parameter - Description * - ``DATETIME_FORMAT`` - Default format is ``yyyy-mm-dd``. Other supported date formats are:``iso8601``, ``iso8601c``, ``dmy``, ``ymd``, ``mdy``, ``yyyymmdd``, ``yyyy-m-d``, ``yyyy-mm-dd``, ``yyyy/m/d``, ``yyyy/mm/dd``, ``d/m/yyyy``, ``dd/mm/yyyy``, ``mm/dd/yyyy``, ``dd-mon-yyyy``, ``yyyy-mon-dd``. * - ``IGNORE_EXTRA_FIELDS`` - Default value is ``false``. When value is ``true``, key names which do not have corresponding SQream table columns will be ignored. Parameter may be used with the ``COPY TO`` and ``IGNORE FOREIGN TABLE`` statements. * - ``COMPRESSION`` - Supported values are ``auto``, ``gzip``, and ``none``. ``auto`` means that the compression type is automatically detected upon import. Parameter is not supported for exporting. ``gzip`` means that a ``gzip`` compression is applied. ``none`` means that no compression or an attempt to decompress will take place. * - ``LOCATION`` - A path on the local filesystem, on S3, or on HDFS URI. The local path must be an absolute path that SQream DB can access. * - ``LIMIT`` - When specified, tells SQream DB to stop ingesting after the specified number of rows. Unlimited if unset. * - ``OFFSET`` - The row number from which to start ingesting. * - ``ERROR_LOG`` - If when using the ``COPY`` command, copying a row fails, the ``ERROR LOG`` command writes error information to the error log specified in the ``ERROR LOG`` command. * If an existing file path is specified, the file will be overwritten. * Specifying the same file for ``ERROR_LOG`` and ``REJECTED_DATA`` is not allowed and will result in error. * Specifying an error log when creating a foreign table will write a new error log for every query on the foreign table. * - ``CONTINUE_ON_ERROR`` - Specifies if errors should be ignored or skipped. When set to true, the transaction will continue despite rejected data. This parameter should be set together with ``ERROR_COUNT``. When reading multiple files, if an entire file cannot be opened, it will be skipped. * - ``ERROR_COUNT`` - Specifies the maximum number of faulty records that will be ignored. This setting must be used in conjunction with ``continue_on_error``. * - ``MAX_FILE_SIZE`` - Sets the maximum file size (bytes). * - ``ENFORCE_SINGLE_FILE`` - Permitted values are ``true`` or ``false``. When set to ``true``, a single file of unlimited size is created. This single file is not limited by the ``MAX_FILE_SIZE`` parameter. ``false`` permits creating several files together limited by the ``MAX_FILE_SIZE`` parameter. Default value: ``false``. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets. Automatic Schema Inference -------------------------- SQreamDB can read the file metadata, enabling the automatic inference of column structure and data types. .. code-block:: postgres CREATE FOREIGN TABLE nba WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); For more information, follow the :ref:`CREATE FOREIGN TABLE<create_foreign_table>` page. Examples -------- JSON objects: .. code-block:: json [ { "name":"Avery Bradley", "age":25, "position":"PG" }, { "name":"Jae Crowder", "age":25, "position":"SF" }, { "name":"John Holland", "age":27, "position":"SG" } ] Using the ``COPY FROM`` statement: .. code-block:: postgres COPY nba FROM WRAPPER json_fdw OPTIONS (LOCATION = 's3://sqream-docs/nba.json'); Note that JSON files generated using the ``COPY TO`` statement will store objects, and not object arrays. .. code-block:: postgres COPY nba TO WRAPPER json_fdw OPTIONS (location = 's3://sqream-docs/nba.json'); When using the ``CREATE FOREIGN TABLE`` statement, make sure that the table schema corresponds with the JSON file structure. .. code-block:: postgres CREATE FOREIGN TABLE t (id int not null) WRAPPER json_fdw OPTIONS (location = 'sqream-docs.json'); The following is an example of loading data from a JSON file into SQream: .. code-block:: postgres WRAPPER json_fdw OPTIONS (LOCATION = 'sqream-docs.json'); .. tip:: An exact match must exist between the SQream and JSON types. For unsupported column types, you can set the type to any type and exclude it from subsequent queries. \ No newline at end of file diff --git a/operational_guides/foreign_tables.rst b/operational_guides/foreign_tables.rst index 685368840..80da99170 100644 --- a/operational_guides/foreign_tables.rst +++ b/operational_guides/foreign_tables.rst @@ -5,22 +5,22 @@ Foreign Tables ************** Foreign tables can be used to run queries directly on data without inserting it into SQreamDB first. -SQream DB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. +SQreamDB supports read-only foreign tables so that you can query from foreign tables, but you cannot insert to them, or run deletes or updates on them. -Running queries directly on foreign data is most effectively used for one-off querying. If you are repeatedly querying data, the performance will usually be better if you insert the data into SQream DB first. +Running queries directly on foreign data is most effectively used for one-off querying. If you are repeatedly querying data, the performance will usually be better if you insert the data into SQreamDB first. -Although foreign tables can be used without inserting data into SQream DB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. +Although foreign tables can be used without inserting data into SQreamDB, one of their main use cases is to help with the insertion process. An insert select statement on a foreign table can be used to insert data into SQream using the full power of the query engine to perform ETL. -.. contents:: In this topic: +.. contents:: :local: :depth: 1 Supported Data Formats ====================== -SQream DB supports foreign tables over: +SQreamDB supports foreign tables using the following file formats: -* Text - CSV, TSV, and PSV +* Text: CSV, TSV, and PSV * Parquet * ORC * Avro @@ -31,9 +31,9 @@ Supported Data Staging SQream can stage data from: -* a local filesystem (e.g. ``/mnt/storage/....``) -* :ref:`s3` buckets (e.g. ``s3://pp-secret-bucket/users/*.parquet``) -* :ref:`hdfs` (e.g. ``hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv``) +* A local filesystem (e.g. ``/mnt/storage/....``) +* :ref:`s3` buckets +* :ref:`hdfs` Using Foreign Tables ==================== @@ -73,15 +73,13 @@ Based on the source file structure, we :ref:`create a foreign table<create_forei DELIMITER = '\r\n' -- DOS delimited file ); -The file format in this case is CSV, and it is stored as an :ref:`s3` object (if the path is on :ref:`hdfs`, change the URI accordingly). +The file format in this case is CSV, and it is stored as an Amazon Web Services object (if the path is on :ref:`hdfs`, change the URI accordingly). We also took note that the record delimiter was a DOS newline (``\r\n``). Querying Foreign Tables ----------------------- -Let's peek at the data from the foreign table: - .. code-block:: psql SELECT * FROM nba LIMIT 10; @@ -165,4 +163,5 @@ Error Handling and Limitations SELECT * FROM nba; Record delimiter mismatch during CSV parsing. User defined line delimiter \n does not match the first delimiter \r\n found in s3://sqream-demo-data/nba.csv -* Since the data for a foreign table is not stored in SQream DB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. + +* Since the data for a foreign table is not stored in SQreamDB, it can be changed or removed at any time by an external process. As a result, the same query can return different results each time it runs against a foreign table. Similarly, a query might fail if the external data is moved, removed, or has changed structure. diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 1f6f5d76c..15a5c3a06 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -4,7 +4,10 @@ CREATE FOREIGN TABLE ******************** -The ``CREATE FOREIGN TABLE`` command creates a foreign table that references data stored outside of SQreamDB. Foreign tables are used for querying data stored in files on a file system, :ref:`external storage platforms<external_storage_platforms>`, or in other databases. +The ``CREATE FOREIGN TABLE`` command creates a foreign table that references data stored externally to SQreamDB. This allows for querying data located in files on a file system, :ref:`external storage platforms<external_storage_platforms>`, or other databases. + + +When querying data stored in file formats that support metadata, such as Parquet, ORC, JSON, and Avro, it is possible to omit the DDL when creating a foreign table. SQreamDB can read the file metadata, enabling the automatic inference of column structure and data types. Syntax ====== @@ -89,11 +92,9 @@ Parameters Usage Notes =========== -The automatic foreign table DDL resolution feature supports Parquet, ORC, JSON, and Avro files, while using it with CSV files generates an error. You can activate this feature when you create a foreign table by omitting the column list, described in the **Syntax** section below. - -Using this feature the path you specify in the ``LOCATION`` option must point to at least one existing file. If no files exist for the schema to read, an error will be generated. You can specify the schema manually even in the event of the error above. +* When creating foreign tables from CSV files, it is required to provide a table DDL. -.. note:: When using this feature, SQream assumes that all files in the path use the same schema. +* When creating a foreign table using the ``*`` wildcard, SQreamDB assumes that all files in the path use the same schema. Examples ======== From d966b456ec86c3aba66d664d60645dfdb48f8d2a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:09:45 +0300 Subject: [PATCH 1455/1892] T4 --- architecture/concurrency_and_scaling_in_sqream.rst | 2 +- getting_started/non_production_hardware_guide.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/architecture/concurrency_and_scaling_in_sqream.rst b/architecture/concurrency_and_scaling_in_sqream.rst index b7cc3e76c..0b9025062 100644 --- a/architecture/concurrency_and_scaling_in_sqream.rst +++ b/architecture/concurrency_and_scaling_in_sqream.rst @@ -47,7 +47,7 @@ Maximum Workers Per GPU: * - GPU - Workers - * - NVIDIA Turing T4 (16GB) + * - NVIDIA Turing A10 (16GB) - 1 * - NVIDIA Volta V100 (32GB) - 2 diff --git a/getting_started/non_production_hardware_guide.rst b/getting_started/non_production_hardware_guide.rst index 4f8739f90..54c7780b0 100644 --- a/getting_started/non_production_hardware_guide.rst +++ b/getting_started/non_production_hardware_guide.rst @@ -49,6 +49,6 @@ Lab Server * - Onboard storage - "2x 960GB SSD 2.5in hot plug for OS, RAID1, 1(or more)x 3.84TB SSD 2.5in Hot plug for storage, RAID5" * - GPU - - 1xNVIDIA T4 or A40 or A10 + - 1xNVIDIA A40 or A10 * - Operating System - Red Hat Enterprise Linux v8.8 From 51b98306bca70aa0fb5b282dda9ce2c887ea5abe Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 13:23:40 +0300 Subject: [PATCH 1456/1892] Remove create from alter default permissions --- operational_guides/access_control_permissions.rst | 1 - .../access_control_commands/alter_default_permissions.rst | 8 ++------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index a4cc5c879..37956db3e 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -389,7 +389,6 @@ schema statement is run. { CREATE FUNCTION | SUPERUSER | CONNECT - | CREATE | USAGE | SELECT | INSERT diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index f8e92fd85..89ce4eb75 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -44,7 +44,6 @@ Syntax { CREATE FUNCTION | SUPERUSER | CONNECT - | CREATE | USAGE | SELECT | INSERT @@ -71,9 +70,6 @@ The following table describes the supported permissions: * - ``SUPERUSER`` - Schema - The most privileged role, with full control over a cluster, database, or schema - * - ``CREATE`` - - Schema - - For a role to create and manage objects, it needs the ``CREATE`` and ``USAGE`` permissions at the respective level * - ``USAGE`` - Schema - For a role to see tables in a schema, it needs the ``USAGE`` permissions @@ -144,11 +140,11 @@ For more information about default permissions, see `Default Permissions <https: Granting Automatic Permissions for Newly Created Schemas -------------------------------------------------------- -When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE`` and ``CREATE`` permissions in the new schema, as shown below: +When the role ``demo`` creates a new schema, roles **u1,u2** are granted ``USAGE`` permission in the new schema, as shown below: .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE, CREATE TO u1,u2; + ALTER DEFAULT PERMISSIONS FOR demo FOR SCHEMAS GRANT USAGE TO u1,u2; Granting Automatic Permissions for Newly Created Tables in a Schema ------------------------------------------------------------------- From f03c0e6322bf83dc96f5722bacbdd4edb078be5a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 15 Jul 2024 14:01:20 +0300 Subject: [PATCH 1457/1892] Remove RHEL 8.8 --- getting_started/hardware_guide.rst | 10 +++---- ...eparing_your_machine_to_install_sqream.rst | 8 ++--- .../pre-installation_configurations.rst | 30 ++++++------------- 3 files changed, 18 insertions(+), 30 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 1af7b821e..c9d4fc1c5 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -64,7 +64,7 @@ An average single-node cluster can be a rackmount server or workstation, contain NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v8.8 or Amazon Linux + - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -108,7 +108,7 @@ The following table shows SQreamDB's recommended hardware specifications: * - GPU - NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v8.8 or Amazon Linux + - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux Metadata Server --------------- @@ -134,7 +134,7 @@ The following table shows SQreamDB's recommended metadata server specifications: * - Network Card (Client) - 2x 1 GbE cards or similar * - Operating System - - Red Hat Enterprise Linux v8.8 or Amazon Linux + - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. @@ -158,7 +158,7 @@ The following table shows SQreamDB's recommended Studio server specifications: * - Onboard storage - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v8.8 + - Red Hat Enterprise Linux v7.9 / v8.9 or CentOS v7.9 Cluster Design Considerations ============================= @@ -231,7 +231,7 @@ Operating System SQreamDB can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v8.8 + * Red Hat Enterprise Linux (RHEL) v7.9 / v8.9 * Amazon Linux 2018.03 diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index fbb426d43..e3487c725 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -1,8 +1,8 @@ .. _preparing_your_machine_to_install_sqream: -****************************************** +******************************************* Preparing Your Machine to Install SQreamDB -****************************************** +******************************************* To prepare your machine to install SQreamDB, do the following: @@ -12,7 +12,7 @@ To prepare your machine to install SQreamDB, do the following: * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - * Red Hat Enterprise Linux v8.6 - 8.8 + * Red Hat Enterprise Linux v7.x / v8.6 - 8.9 * Amazon Linux 7 @@ -31,4 +31,4 @@ To prepare your machine to install SQreamDB, do the following: For more information, see the following: * :ref:`pre-installation_configurations` -* :ref:`hardware_guide` +* :ref:`hardware_guide` \ No newline at end of file diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index f7d8d9536..557b7d120 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -82,10 +82,10 @@ If any doubt arises, consult the documentation for your server or your hardware - QPI (QuickPath Interconnect) Snoop lets you configure different Snoop modes that impact the QPI interconnect. Changing this setting may improve the performance of certain workloads. The default setting of **Home Snoop** provides high memory bandwidth in an average NUMA environment. **Cluster on Die** may provide increased memory bandwidth in highly optimized NUMA workloads. **Early Snoop** may decrease memory latency, but may result in lower overall bandwidth compared to other modes. Installing the Operating System -=============================== +================================ Before You Begin ----------------- +------------------- * Your system must have at least 200 gigabytes of free space on the root ``/`` mount. @@ -93,12 +93,12 @@ Before You Begin * Once the BIOS settings have been set, you must install the operating system. -* A typical SQreamDB installation requires RHEL7.9 or RHEL8.X (RHEL8.8 recommended) +* A typical SQreamDB installation requires RHEL7.9 or RHEL8.X (RHEL8.9 recommended) * Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. Installation ------------- +---------------- #. Select a language (English recommended). #. From **Software Selection**, select **Minimal** and check the **Development Tools** group checkbox. @@ -127,12 +127,12 @@ Installation The OS shell is booted up. Configuring the Operating System -================================ +================================== When configuring the operating system, several basic settings related to creating a new server are required. Configuring these as part of your basic set-up increases your server's security and usability. Creating a ``sqream`` User --------------------------- +---------------------------- **The sqream user must have the same UID and GID across all servers in your cluster.** @@ -806,18 +806,12 @@ Disable Nouveau, which is the default operating system driver. Installing the CUDA Driver -------------------------- +The current recommendation is for CUDA 12.3.2. + .. contents:: :local: :depth: 1 -The current recommendation is for CUDA 12.3.2. - -For A100 GPU and other A series GPUs, you must install CUDA driver **11.4.3** or a later version. - -For H100 GPU and other H series GPUs, you must install CUDA driver **11.8** or a later version. - -For L40S GPU and other L series GPUs, you must install CUDA driver **12.0** or a later version. - For questions related to which driver to install, contact `SqreamDB support <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_. Installing the CUDA Driver from the Repository @@ -861,14 +855,8 @@ Installing the CUDA driver from the Repository is the recommended installation m sudo yum clean all sudo yum -y install nvidia-driver-latest-dkms - * **RHEL8.6 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - sudo dnf localinstall cuda-repo-rhel8-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - * **RHEL8.8 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + * **RHEL8.9 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console From 3e373c9b5cc43ec8c352424741fa3afdd1f16d8b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Jul 2024 08:39:19 +0300 Subject: [PATCH 1458/1892] Update logging.rst --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index f3b9a3b56..b3bec651e 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -109,7 +109,7 @@ For effective :ref:`health_monitoring`, it's essential that logs are saved in `` - ``INFO`` - Statement passed to another worker for execution - - * ``""Reconstruct query before parsing"`` + * ``"Reconstruct query before parsing"`` * ``"SELECT * FROM nba WHERE ""Team"" NOT LIKE ""Portland%%"""`` (statement preparing on node) * - ``4`` - ``INFO`` From 9b5669c5a905c6894c2fd06958697b1b3225c5ac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:24:36 +0300 Subject: [PATCH 1459/1892] Allow lower and upper case characters delimiters --- .../sql_statements/dml_commands/copy_from.rst | 2 - .../sql_statements/dml_commands/copy_to.rst | 104 ------------------ 2 files changed, 106 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index a4466c80c..b5c2f4c92 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -363,8 +363,6 @@ The following ASCII field delimiters (octal range 001 - 176) are not supported: | 8 | 56 | 70 | n | 110 | 156 | 13 | 49 | 13 | +---------------+-------------+------------+---------------+-------------+------------+ | | | | 9 | 57 | 71 | o | 111 | 157 | | | | -+---------------+-------------+------------+---------------+-------------+------------+ | | | -| a | 97 | 141 | p | 112 | 160 | | | | +---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index f15b7e36f..42ea5e738 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -299,112 +299,8 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 58 | : | Colon | 72 | 3A | 111010 | &#58; | &colon; | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 65 | A | Upper Case Letter A | 101 | 41 | 1000001 | &#65; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 66 | B | Upper Case Letter B | 102 | 42 | 1000010 | &#66; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 67 | C | Upper Case Letter C | 103 | 43 | 1000011 | &#67; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 68 | D | Upper Case Letter D | 104 | 44 | 1000100 | &#68; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 69 | E | Upper Case Letter E | 105 | 45 | 1000101 | &#69; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 70 | F | Upper Case Letter F | 106 | 46 | 1000110 | &#70; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 71 | G | Upper Case Letter G | 107 | 47 | 1000111 | &#71; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 72 | H | Upper Case Letter H | 110 | 48 | 1001000 | &#72; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 73 | I | Upper Case Letter I | 111 | 49 | 1001001 | &#73; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 74 | J | Upper Case Letter J | 112 | 4A | 1001010 | &#74; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 75 | K | Upper Case Letter K | 113 | 4B | 1001011 | &#75; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 76 | L | Upper Case Letter L | 114 | 4C | 1001100 | &#76; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 77 | M | Upper Case Letter M | 115 | 4D | 1001101 | &#77; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 78 | N | Upper Case Letter N | 116 | 4E | 1001110 | &#78; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 79 | O | Upper Case Letter O | 117 | 4F | 1001111 | &#79; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 80 | P | Upper Case Letter P | 120 | 50 | 1010000 | &#80; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 81 | Q | Upper Case Letter Q | 121 | 51 | 1010001 | &#81; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 82 | R | Upper Case Letter R | 122 | 52 | 1010010 | &#82; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 83 | S | Upper Case Letter S | 123 | 53 | 1010011 | &#83; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 84 | T | Upper Case Letter T | 124 | 54 | 1010100 | &#84; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 85 | U | Upper Case Letter U | 125 | 55 | 1010101 | &#85; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 86 | V | Upper Case Letter V | 126 | 56 | 1010110 | &#86; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 87 | W | Upper Case Letter W | 127 | 57 | 1010111 | &#87; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 88 | X | Upper Case Letter X | 130 | 58 | 1011000 | &#88; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 89 | Y | Upper Case Letter Y | 131 | 59 | 1011001 | &#89; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 90 | Z | Upper Case Letter Z | 132 | 5A | 1011010 | &#90; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 97 | a | Lower Case Letter a | 141 | 61 | 1100001 | &#97; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 98 | b | Lower Case Letter b | 142 | 62 | 1100010 | &#98; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 99 | c | Lower Case Letter c | 143 | 63 | 1100011 | &#99; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 100 | d | Lower Case Letter d | 144 | 64 | 1100100 | &#100; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 101 | e | Lower Case Letter e | 145 | 65 | 1100101 | &#101; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 102 | f | Lower Case Letter f | 146 | 66 | 1100110 | &#102; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 103 | g | Lower Case Letter g | 147 | 67 | 1100111 | &#103; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 104 | h | Lower Case Letter h | 150 | 68 | 1101000 | &#104; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 105 | i | Lower Case Letter i | 151 | 69 | 1101001 | &#105; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 106 | j | Lower Case Letter j | 152 | 6A | 1101010 | &#106; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 107 | k | Lower Case Letter k | 153 | 6B | 1101011 | &#107; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 108 | l | Lower Case Letter l | 154 | 6C | 1101100 | &#108; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 109 | m | Lower Case Letter m | 155 | 6D | 1101101 | &#109; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 110 | n | Lower Case Letter n | 156 | 6E | 1101110 | &#110; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 111 | o | Lower Case Letter o | 157 | 6F | 1101111 | &#111; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 112 | p | Lower Case Letter p | 160 | 70 | 1110000 | &#112; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 113 | q | Lower Case Letter q | 161 | 71 | 1110001 | &#113; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 114 | r | Lower Case Letter r | 162 | 72 | 1110010 | &#114; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 115 | s | Lower Case Letter s | 163 | 73 | 1110011 | &#115; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 116 | t | Lower Case Letter t | 164 | 74 | 1110100 | &#116; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 117 | u | Lower Case Letter u | 165 | 75 | 1110101 | &#117; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 118 | v | Lower Case Letter v | 166 | 76 | 1110110 | &#118; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 119 | w | Lower Case Letter w | 167 | 77 | 1110111 | &#119; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 120 | x | Lower Case Letter x | 170 | 78 | 1111000 | &#120; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 121 | y | Lower Case Letter y | 171 | 79 | 1111001 | &#121; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ -| 122 | z | Lower Case Letter z | 172 | 7A | 1111010 | &#122; | | -+-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ Date Format --------------- From 1f65027c2be44748c37b8bb2266840623cd63b84 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 22 Jul 2024 09:26:37 +0300 Subject: [PATCH 1460/1892] Update conf.py --- conf.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/conf.py b/conf.py index 293ced6d2..46c0bdedc 100644 --- a/conf.py +++ b/conf.py @@ -10,9 +10,16 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) +import os + +# Define the canonical URL if you are using a custom domain on Read the Docs +html_baseurl = os.environ.get("READTHEDOCS_CANONICAL_URL", "") + +# Tell Jinja2 templates the build is running on Read the Docs +if os.environ.get("READTHEDOCS", "") == "True": + if "html_context" not in globals(): + html_context = {} + html_context["READTHEDOCS"] = True import sphinx_rtd_theme From 3b71cd5336f39629b7b9c5f836f9f27d1e2a3597 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:01:11 +0300 Subject: [PATCH 1461/1892] Update copy_to.rst --- .../sql_statements/dml_commands/copy_to.rst | 110 +++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index 42ea5e738..c64e4b655 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -118,7 +118,7 @@ Supported Field Delimiters Printable ASCII Characters ^^^^^^^^^^^^^^^^^^^^^^^^^^ -Any printable ASCII character can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). +All printable ASCII character (except for ``N``) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). The following table shows the supported printable ASCII characters: @@ -181,6 +181,112 @@ The following table shows the supported printable ASCII characters: +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ | ~ | Tilde | 126 | 176 | 7E | 1111110 | &#126; | &tilde; | +---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 58 | : | Colon | 72 | 3A | 111010 | &#58; | &colon; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 65 | A | A | 101 | 41 | 1000001 | &#65; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 66 | B | B | 102 | 42 | 1000010 | &#66; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 67 | C | C | 103 | 43 | 1000011 | &#67; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 68 | D | D | 104 | 44 | 1000100 | &#68; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 69 | E | E | 105 | 45 | 1000101 | &#69; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 70 | F | F | 106 | 46 | 1000110 | &#70; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 71 | G | G | 107 | 47 | 1000111 | &#71; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 72 | H | H | 110 | 48 | 1001000 | &#72; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 73 | I | I | 111 | 49 | 1001001 | &#73; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 74 | J | J | 112 | 4A | 1001010 | &#74; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 75 | K | K | 113 | 4B | 1001011 | &#75; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 76 | L | L | 114 | 4C | 1001100 | &#76; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 77 | M | M | 115 | 4D | 1001101 | &#77; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 79 | O | O | 117 | 4F | 1001111 | &#79; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 80 | P | P | 120 | 50 | 1010000 | &#80; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 81 | Q | Q | 121 | 51 | 1010001 | &#81; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 82 | R | R | 122 | 52 | 1010010 | &#82; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 83 | S | S | 123 | 53 | 1010011 | &#83; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 84 | T | T | 124 | 54 | 1010100 | &#84; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 85 | U | U | 125 | 55 | 1010101 | &#85; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 86 | V | V | 126 | 56 | 1010110 | &#86; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 87 | W | W | 127 | 57 | 1010111 | &#87; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 88 | X | X | 130 | 58 | 1011000 | &#88; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 89 | Y | Y | 131 | 59 | 1011001 | &#89; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 90 | Z | Z | 132 | 5A | 1011010 | &#90; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 97 | a | a | 141 | 61 | 1100001 | &#97; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 98 | b | b | 142 | 62 | 1100010 | &#98; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 99 | c | c | 143 | 63 | 1100011 | &#99; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 100 | d | d | 144 | 64 | 1100100 | &#100; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 101 | e | e | 145 | 65 | 1100101 | &#101; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 102 | f | f | 146 | 66 | 1100110 | &#102; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 103 | g | g | 147 | 67 | 1100111 | &#103; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 104 | h | h | 150 | 68 | 1101000 | &#104; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 105 | i | i | 151 | 69 | 1101001 | &#105; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 106 | j | j | 152 | 6A | 1101010 | &#106; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 107 | k | k | 153 | 6B | 1101011 | &#107; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 108 | l | l | 154 | 6C | 1101100 | &#108; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 109 | m | m | 155 | 6D | 1101101 | &#109; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 110 | n | n | 156 | 6E | 1101110 | &#110; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 111 | o | o | 157 | 6F | 1101111 | &#111; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 112 | p | p | 160 | 70 | 1110000 | &#112; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 113 | q | q | 161 | 71 | 1110001 | &#113; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 114 | r | r | 162 | 72 | 1110010 | &#114; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 115 | s | s | 163 | 73 | 1110011 | &#115; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 116 | t | t | 164 | 74 | 1110100 | &#116; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 117 | u | u | 165 | 75 | 1110101 | &#117; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 118 | v | v | 166 | 76 | 1110110 | &#118; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 119 | w | w | 167 | 77 | 1110111 | &#119; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 120 | x | x | 170 | 78 | 1111000 | &#120; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 121 | y | y | 171 | 79 | 1111001 | &#121; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 122 | z | z | 172 | 7A | 1111010 | &#122; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ Non-Printable ASCII Characters ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -301,6 +407,8 @@ The following table shows the unsupported ASCII field delimiters: +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ | 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | +-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 78 | N | N | 116 | 4E | 1001110 | &#78; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ Date Format --------------- From bac683dd5810aead4bae1f048076b1eb3582bf76 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 23 Jul 2024 13:23:29 +0300 Subject: [PATCH 1462/1892] Update copy_from.rst --- .../sql_statements/dml_commands/copy_from.rst | 316 ++++++++++++++++-- 1 file changed, 279 insertions(+), 37 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index b5c2f4c92..450573068 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -311,21 +311,253 @@ A multi-character delimiter can be specified. For example, ``DELIMITER '%%'``, ` Printable Characters -------------------- -Any printable ASCII character (or characters) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). +All printable ASCII character (except for ``N``) can be used as a delimiter without special syntax. The default CSV field delimiter is a comma (``,``). + + +The following table shows the supported printable ASCII characters: + ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **ASCII** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| (Space) | Space | 32 | 40 | 20 | 100000 | &#32; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ! | Exclamation Mark | 33 | 41 | 21 | 100001 | &#33; | &excl; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| # | Hash or Number | 35 | 43 | 23 | 100011 | &#35; | &num; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| $ | Dollar Sign | 36 | 44 | 24 | 100100 | &#36; | &dollar; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| % | Percentage | 37 | 45 | 25 | 100101 | &#37; | &percnt; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| & | Ampersand | 38 | 46 | 26 | 100110 | &#38; | &amp; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ( | Left Parenthesis | 40 | 50 | 28 | 101000 | &#40; | &lpar; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ) | Right Parenthesis | 41 | 51 | 29 | 101001 | &#41; | &rpar; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \*\ | Asterisk | 42 | 52 | 2A | 101010 | &#42; | &ast; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \+\ | Plus Sign | 43 | 53 | 2B | 101011 | &#43; | &plus; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| , | Comma | 44 | 54 | 2C | 101100 | &#44; | &comma; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| / | Slash | 47 | 57 | 2F | 101111 | &#47; | &sol; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ; | Semicolon | 59 | 73 | 3B | 111011 | &#59; | &semi; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| < | Less Than | 60 | 74 | 3C | 111100 | &#60; | &lt; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| = | Equals Sign | 61 | 75 | 3D | 111101 | &#61; | &equals; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| > | Greater Than | 62 | 76 | 3E | 111110 | &#62; | &gt; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ? | Question Mark | 63 | 77 | 3F | 111111 | &#63; | &quest; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| @ | At Sign | 64 | 100 | 40 | 1000000 | &#64; | &commat; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| [ | Left Square Bracket | 91 | 133 | 5B | 1011011 | &#91; | &lsqb; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \\ | Backslash | 92 | 134 | 5C | 1011100 | \&\#92\; | &bsol; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ] | Right Square Bracket | 93 | 135 | 5D | 1011101 | &#93; | &rsqb; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ^ | Caret or Circumflex | 94 | 136 | 5E | 1011110 | &#94; | &hat; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| _ | Underscore | 95 | 137 | 5F | 1011111 | &#95; | &lowbar; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ` | Grave Accent | 96 | 140 | 60 | 1100000 | &#96; | &grave; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| { | Left Curly Bracket | 123 | 173 | 7B | 1111011 | &#123; | &lcub; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| \|\ | Vertical Bar | 124 | 174 | 7C | 1111100 | &#124; | &verbar; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| } | Right Curly Bracket | 125 | 175 | 7D | 1111101 | &#125; | &rcub; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ~ | Tilde | 126 | 176 | 7E | 1111110 | &#126; | &tilde; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 58 | : | Colon | 72 | 3A | 111010 | &#58; | &colon; | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 65 | A | A | 101 | 41 | 1000001 | &#65; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 66 | B | B | 102 | 42 | 1000010 | &#66; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 67 | C | C | 103 | 43 | 1000011 | &#67; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 68 | D | D | 104 | 44 | 1000100 | &#68; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 69 | E | E | 105 | 45 | 1000101 | &#69; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 70 | F | F | 106 | 46 | 1000110 | &#70; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 71 | G | G | 107 | 47 | 1000111 | &#71; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 72 | H | H | 110 | 48 | 1001000 | &#72; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 73 | I | I | 111 | 49 | 1001001 | &#73; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 74 | J | J | 112 | 4A | 1001010 | &#74; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 75 | K | K | 113 | 4B | 1001011 | &#75; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 76 | L | L | 114 | 4C | 1001100 | &#76; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 77 | M | M | 115 | 4D | 1001101 | &#77; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 79 | O | O | 117 | 4F | 1001111 | &#79; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 80 | P | P | 120 | 50 | 1010000 | &#80; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 81 | Q | Q | 121 | 51 | 1010001 | &#81; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 82 | R | R | 122 | 52 | 1010010 | &#82; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 83 | S | S | 123 | 53 | 1010011 | &#83; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 84 | T | T | 124 | 54 | 1010100 | &#84; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 85 | U | U | 125 | 55 | 1010101 | &#85; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 86 | V | V | 126 | 56 | 1010110 | &#86; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 87 | W | W | 127 | 57 | 1010111 | &#87; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 88 | X | X | 130 | 58 | 1011000 | &#88; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 89 | Y | Y | 131 | 59 | 1011001 | &#89; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 90 | Z | Z | 132 | 5A | 1011010 | &#90; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 97 | a | a | 141 | 61 | 1100001 | &#97; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 98 | b | b | 142 | 62 | 1100010 | &#98; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 99 | c | c | 143 | 63 | 1100011 | &#99; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 100 | d | d | 144 | 64 | 1100100 | &#100; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 101 | e | e | 145 | 65 | 1100101 | &#101; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 102 | f | f | 146 | 66 | 1100110 | &#102; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 103 | g | g | 147 | 67 | 1100111 | &#103; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 104 | h | h | 150 | 68 | 1101000 | &#104; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 105 | i | i | 151 | 69 | 1101001 | &#105; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 106 | j | j | 152 | 6A | 1101010 | &#106; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 107 | k | k | 153 | 6B | 1101011 | &#107; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 108 | l | l | 154 | 6C | 1101100 | &#108; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 109 | m | m | 155 | 6D | 1101101 | &#109; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 110 | n | n | 156 | 6E | 1101110 | &#110; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 111 | o | o | 157 | 6F | 1101111 | &#111; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 112 | p | p | 160 | 70 | 1110000 | &#112; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 113 | q | q | 161 | 71 | 1110001 | &#113; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 114 | r | r | 162 | 72 | 1110010 | &#114; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 115 | s | s | 163 | 73 | 1110011 | &#115; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 116 | t | t | 164 | 74 | 1110100 | &#116; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 117 | u | u | 165 | 75 | 1110101 | &#117; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 118 | v | v | 166 | 76 | 1110110 | &#118; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 119 | w | w | 167 | 77 | 1110111 | &#119; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 120 | x | x | 170 | 78 | 1111000 | &#120; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 121 | y | y | 171 | 79 | 1111001 | &#121; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ +| 122 | z | z | 172 | 7A | 1111010 | &#122; | | ++---------------+----------------------+-----------+-----------+---------+------------+---------------+---------------+ -A printable character is any ASCII character in the range 32 - 126. - -:ref:`Literal quoting rules<string_literals>` apply with delimiters. For example, to use ``'`` as a field delimiter, use ``DELIMITER ''''`` Non-Printable Characters ------------------------ -A non-printable character (1 - 31, 127) can be used in its octal form. - A tab can be specified by escaping it, for example ``\t``. Other non-printable characters can be specified using their octal representations, by using the ``E'\000'`` format, where ``000`` is the octal value of the character. For example, ASCII character ``15``, known as "shift in", can be specified using ``E'\017'``. +The following table shows the supported non-printable ASCII characters: + ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| **Character** | **Description** | **Octal** | **ASCII** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NUL | Null | 0 | 0 | 0 | 0 | &#0; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SOH | Start of Heading | 1 | 1 | 1 | 1 | &#1; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| STX | Start of Text | 2 | 2 | 2 | 10 | &#2; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETX | End of Text | 3 | 3 | 3 | 11 | &#3; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EOT | End of Transmission | 4 | 4 | 4 | 100 | &#4; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ENQ | Enquiry | 5 | 5 | 5 | 101 | &#5; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ACK | Acknowledge | 6 | 6 | 6 | 110 | &#6; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BEL | Bell | 7 | 7 | 7 | 111 | &#7; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| BS | Backspace | 10 | 8 | 8 | 1000 | &#8; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| HT | Horizontal Tab | 11 | 9 | 9 | 1001 | &#9; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| VT | Vertical Tab | 13 | 11 | 0B | 1011 | &#11; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FF | NP Form Feed, New Page | 14 | 12 | 0C | 1100 | &#12; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SO | Shift Out | 16 | 14 | 0E | 1110 | &#14; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SI | Shift In | 17 | 15 | 0F | 1111 | &#15; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DLE | Data Link Escape | 20 | 16 | 10 | 10000 | &#16; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC1 | Device Control 1 | 21 | 17 | 11 | 10001 | &#17; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC2 | Device Control 2 | 22 | 18 | 12 | 10010 | &#18; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC3 | Device Control 3 | 23 | 19 | 13 | 10011 | &#19; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DC4 | Device Control 4 | 24 | 20 | 14 | 10100 | &#20; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| NAK | Negative Acknowledge | 25 | 21 | 15 | 10101 | &#21; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SYN | Synchronous Idle | 26 | 22 | 16 | 10110 | &#22; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ETB | End of Transmission Block | 27 | 23 | 17 | 10111 | &#23; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| CAN | Cancel | 30 | 24 | 18 | 11000 | &#24; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| EM | End of Medium | 31 | 25 | 19 | 11001 | &#25; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| SUB | Substitute | 32 | 26 | 1A | 11010 | &#26; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| ESC | Escape | 33 | 27 | 1B | 11011 | &#27; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| FS | File Separator | 34 | 28 | 1C | 11100 | &#28; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| GS | Group Separator | 35 | 29 | 1D | 11101 | &#29; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| RS | Record Separator | 36 | 30 | 1E | 11110 | &#30; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| US | Unit Separator | 37 | 31 | 1F | 11111 | &#31; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ +| DEL | Delete | 177 | 127 | 7F | 1111111 | &#127; | | ++---------------+---------------------------+-----------+-----------+---------+------------+---------------+---------------+ + .. _capturing_rejected_rows: Unsupported Field Delimiters @@ -333,37 +565,47 @@ Unsupported Field Delimiters The following ASCII field delimiters (octal range 001 - 176) are not supported: -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | **Character** | **Decimal** | **Symbol** | -+===============+=============+============+===============+=============+============+===============+=============+============+ -| - | 45 | 55 | b | 98 | 142 | q | 113 | 161 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| . | 46 | 56 | c | 99 | 143 | r | 114 | 162 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| : | 58 | 72 | d | 100 | 144 | s | 115 | 163 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| \ | 92 | 134 | e | 101 | 145 | t | 116 | 164 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 0 | 48 | 60 | f | 102 | 146 | u | 117 | 165 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 1 | 49 | 61 | g | 103 | 147 | v | 118 | 166 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 2 | 50 | 62 | h | 104 | 150 | w | 119 | 167 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 3 | 51 | 63 | i | 105 | 151 | x | 120 | 170 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 4 | 52 | 64 | j | 106 | 152 | y | 121 | 171 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 5 | 53 | 65 | k | 107 | 153 | z | 122 | 172 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 6 | 54 | 66 | l | 108 | 154 | N | 78 | 116 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 7 | 55 | 67 | m | 109 | 155 | 10 | 49 | 12 | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ -| 8 | 56 | 70 | n | 110 | 156 | 13 | 49 | 13 | -+---------------+-------------+------------+---------------+-------------+------------+ | | | -| 9 | 57 | 71 | o | 111 | 157 | | | | -+---------------+-------------+------------+---------------+-------------+------------+---------------+-------------+------------+ +The following table shows the unsupported ASCII field delimiters: + ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| **ASCII** | **Character** | **Description** | **Octal** | **Hex** | **Binary** | **HTML Code** | **HTML Name** | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 10 | LF | NL Line Feed, New Line | 12 | 0A | 1010 | &#10; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 13 | CR | Carriage Return | 15 | 0D | 1101 | &#13; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 34 | " | Double Quote | 42 | 22 | 100010 | &#34; | &quot; | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 45 | \-\ | Minus Sign | 55 | 2D | 101101 | &#45; | &minus; | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 46 | . | Period | 56 | 2E | 101110 | &#46; | &period; | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 48 | 0 | Zero | 60 | 30 | 110000 | &#48; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 49 | 1 | Number One | 61 | 31 | 110001 | &#49; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 50 | 2 | Number Two | 62 | 32 | 110010 | &#50; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 51 | 3 | Number Three | 63 | 33 | 110011 | &#51; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 52 | 4 | Number Four | 64 | 34 | 110100 | &#52; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 53 | 5 | Number Five | 65 | 35 | 110101 | &#53; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 54 | 6 | Number Six | 66 | 36 | 110110 | &#54; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 55 | 7 | Number Seven | 67 | 37 | 110111 | &#55; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 56 | 8 | Number Eight | 70 | 38 | 111000 | &#56; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 57 | 9 | Number Nine | 71 | 39 | 111001 | &#57; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 58 | : | Colon | 72 | 3A | 111010 | &#58; | &colon; | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 92 | \\ | Backslash | 134 | 5C | 01011100 | \&\#92\; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ +| 78 | N | N | 116 | 4E | 1001110 | &#78; | | ++-----------+---------------+------------------------+-----------+---------+------------+---------------+---------------+ From b08a943b16b09f9ebd5fb9e8f394f656e2f1f14d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:35:19 +0300 Subject: [PATCH 1463/1892] Update custom.css --- _static/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_static/css/custom.css b/_static/css/custom.css index 7823005ee..2b6e61be8 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -57,3 +57,7 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { display: none; } +.container.bottom-right { + left: 20px; + bottom: 50px; +} \ No newline at end of file From 20570c02d0a599455f26ab3d39308015c1ab700c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Jul 2024 13:41:46 +0300 Subject: [PATCH 1464/1892] Update custom.css --- _static/css/custom.css | 1 - 1 file changed, 1 deletion(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index 2b6e61be8..95585fa48 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -58,6 +58,5 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } .container.bottom-right { - left: 20px; bottom: 50px; } \ No newline at end of file From dec9173fec9b187b289a8b702a3c0b2c56019275 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:29:28 +0300 Subject: [PATCH 1465/1892] Configuration flags --- .../current_method_configuration_levels.rst | 34 +++++++++++++++++++ .../current_method_modification_methods.rst | 1 - operational_guides/logging.rst | 14 ++++---- releases/4.6.rst | 1 - 4 files changed, 41 insertions(+), 9 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 9d1deb976..0d79a3df2 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -218,6 +218,40 @@ Flag List - Sets the buffer size. - uint - ``524288`` + * - ``logClientLevel`` + - SUPERUSER + - Cluster + - Used to control which :ref:`log level<information_level>` should appear in the logs. Value range: ``0`` - ``6`` + - int + - Default value: ``4`` + + Acceptable values: + + ``0`` - Only SYSTEM level logs + + ``1`` - SYSTEM and FATAL + + ``2`` - SYSTEM, FATAL, and ERROR level logs + + ``3`` - SYSTEM, FATAL, ERROR, and WARNING level logs + + ``4`` - SYSTEM, FATAL, ERROR, WARNING, and INFO level logs + + ``5`` - SYSTEM, FATAL, ERROR, WARNING, INFO, and DEBUG level logs + + ``6`` - SYSTEM, FATAL, ERROR, WARNING, INFO, DEBUG, and TRACE level logs + * - ``logFileRotateTimeFrequency`` + - SUPERUSER + - Cluster + - Specifies when the system begins writing to a new log file. SQreamDB recommends using the ``logFileRotateTimeFrequency`` flag (rather than the ``logMaxFilesSizeMB`` flag) to configure when a new log file is created, as this flag does not limit the number of log files. + - string + - ``daily``. Acceptable values: ``daily``, ``weekly``, or ``monthly`` + * - ``logMaxFilesSizeMB`` + - SUPERUSER + - Cluster + - Specifies when the system begins writing to a new log file. When configured with the ``logMaxFilesSizeMB`` flag, the system maintains up to 13 log files. Once the 13th file is complete, the oldest log file is overwritten by the newly created log file. SQreamDB recommends using the ``logFileRotateTimeFrequency`` flag to configure when a new log file is created, as this flag does not limit the number of log files. + - int + - ``100`` (Megabyte) * - ``logSysLevel`` - Anyone - Session diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index cf413a117..b248320b4 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -63,7 +63,6 @@ The following is an example of the default cluster and session configuration fil "useClientLog": true, "useMetadataServer": true, "spoolMemoryGB": 28, - "useLogMaxFileSize": false, "logMaxFileSizeMB": 20, "logFileRotateTimeFrequency": "daily", "waitForClientSeconds": 18000 diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index b3bec651e..0aa0a6ca2 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -88,6 +88,10 @@ For effective :ref:`health_monitoring`, it's essential that logs are saved in `` - Warnings * - ``INFO`` - Information and statistics + * - ``DEBUG`` + - Information helpful for debugging + * - ``TRACE`` + - .. _message_type: @@ -256,18 +260,14 @@ A few configuration settings alter the log rotation policy: - Description - Default - Values - * - ``useLogMaxFileSize`` - - Rotate log files once they reach a certain file size. When ``true``, set the ``logMaxFileSizeMB`` accordingly. When ``false`` set the ``logFileRotateTimeFrequency`` accordingly. - - ``false`` - - ``false`` or ``true``. * - ``logMaxFileSizeMB`` - Sets the size threshold in megabytes after which a new log file will be opened. - - ``20`` + - ``100`` - ``1`` to ``1024`` (1MB to 1GB) * - ``logFileRotateTimeFrequency`` - Frequency of log rotation - - ``never`` - - ``daily``, ``weekly``, ``monthly``, ``never`` + - ``daily`` + - ``daily``, ``weekly``, or ``monthly`` .. _collecting_logs2: diff --git a/releases/4.6.rst b/releases/4.6.rst index 546483985..8ec224789 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -81,7 +81,6 @@ New Features and Enhancements { - "useLogMaxFileSize": false, "logMaxFileSizeMB": 20, "logFileRotateTimeFrequency": "daily", From 01cb4fffb5639580e27b8ebf361173a5c0ec7691 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:52:20 +0300 Subject: [PATCH 1466/1892] Update logging.rst --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 0aa0a6ca2..21b4b2efc 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -91,7 +91,7 @@ For effective :ref:`health_monitoring`, it's essential that logs are saved in `` * - ``DEBUG`` - Information helpful for debugging * - ``TRACE`` - - + - In-depth information helpful for debugging, such as tracing system function executions and identifying specific error conditions or performance issues. .. _message_type: From 1963b75d532bcd419105ecb71205b19d7e2e5c91 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:40:42 +0300 Subject: [PATCH 1467/1892] Update custom.css --- _static/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_static/css/custom.css b/_static/css/custom.css index 95585fa48..d867791cf 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -59,4 +59,8 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { .container.bottom-right { bottom: 50px; +} + +div.dl { + display: none; } \ No newline at end of file From 84eeb1ed7af3fa74faf1c00921506b70a0674d8c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:49:34 +0300 Subject: [PATCH 1468/1892] Flyout menu addons --- _static/css/custom.css | 22 +++++++++++++++++----- _static/custom.js | 34 ++++++++++++++++++++++++++++++++++ conf.py | 4 +++- 3 files changed, 54 insertions(+), 6 deletions(-) create mode 100644 _static/custom.js diff --git a/_static/css/custom.css b/_static/css/custom.css index d867791cf..50982cabd 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -57,10 +57,22 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { display: none; } -.container.bottom-right { - bottom: 50px; +/* custom.css */ +#custom-flyout-parent { + position: fixed; + top: 0; + left: 0; + height: 100%; + width: 250px; /* Adjust width as needed */ + background-color: #f8f9fa; /* Adjust background color as needed */ + box-shadow: 2px 0 5px rgba(0,0,0,0.1); /* Optional shadow for better visibility */ + z-index: 1000; /* Ensure it is above other elements */ } -div.dl { - display: none; -} \ No newline at end of file +.readthedocs-flyout { + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 100%; +} diff --git a/_static/custom.js b/_static/custom.js new file mode 100644 index 000000000..7034a30c1 --- /dev/null +++ b/_static/custom.js @@ -0,0 +1,34 @@ +document.addEventListener('readthedocsdataready', function(event) { + var data = event.detail; + console.log('RTD Data:', data); + + // Select the shadow host element + var shadowHost = document.querySelector('body > readthedocs-flyout'); + + if (shadowHost) { + // Access the shadow root + var shadowRoot = shadowHost.shadowRoot; + if (shadowRoot) { + // Select the flyout menu within the shadow root + var flyoutMenu = shadowRoot.querySelector('div'); + + if (flyoutMenu) { + // Select the new parent element where you want to move the flyout menu + var newParent = document.querySelector('.custom-location'); // Replace with your desired new parent selector + + if (newParent) { + // Move the flyout menu to the new location + newParent.appendChild(flyoutMenu); + } else { + console.error('New parent element not found!'); + } + } else { + console.error('Flyout menu not found in shadow DOM!'); + } + } else { + console.error('Shadow root not found!'); + } + } else { + console.error('Shadow host element not found!'); + } +}); diff --git a/conf.py b/conf.py index 46c0bdedc..a025a1838 100644 --- a/conf.py +++ b/conf.py @@ -74,7 +74,9 @@ html_static_path = ['_static'] - +html_js_files = [ + 'custom.js', # Relative to the _static path +] html_css_files = [ 'css/custom.css', # Relative to the _static path From 020e037ae3bb85f3363754a62d8575c18863aedb Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 09:53:41 +0300 Subject: [PATCH 1469/1892] Revert "Flyout menu addons" This reverts commit 84eeb1ed7af3fa74faf1c00921506b70a0674d8c. --- _static/css/custom.css | 22 +++++----------------- _static/custom.js | 34 ---------------------------------- conf.py | 4 +--- 3 files changed, 6 insertions(+), 54 deletions(-) delete mode 100644 _static/custom.js diff --git a/_static/css/custom.css b/_static/css/custom.css index 50982cabd..d867791cf 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -57,22 +57,10 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { display: none; } -/* custom.css */ -#custom-flyout-parent { - position: fixed; - top: 0; - left: 0; - height: 100%; - width: 250px; /* Adjust width as needed */ - background-color: #f8f9fa; /* Adjust background color as needed */ - box-shadow: 2px 0 5px rgba(0,0,0,0.1); /* Optional shadow for better visibility */ - z-index: 1000; /* Ensure it is above other elements */ +.container.bottom-right { + bottom: 50px; } -.readthedocs-flyout { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; -} +div.dl { + display: none; +} \ No newline at end of file diff --git a/_static/custom.js b/_static/custom.js deleted file mode 100644 index 7034a30c1..000000000 --- a/_static/custom.js +++ /dev/null @@ -1,34 +0,0 @@ -document.addEventListener('readthedocsdataready', function(event) { - var data = event.detail; - console.log('RTD Data:', data); - - // Select the shadow host element - var shadowHost = document.querySelector('body > readthedocs-flyout'); - - if (shadowHost) { - // Access the shadow root - var shadowRoot = shadowHost.shadowRoot; - if (shadowRoot) { - // Select the flyout menu within the shadow root - var flyoutMenu = shadowRoot.querySelector('div'); - - if (flyoutMenu) { - // Select the new parent element where you want to move the flyout menu - var newParent = document.querySelector('.custom-location'); // Replace with your desired new parent selector - - if (newParent) { - // Move the flyout menu to the new location - newParent.appendChild(flyoutMenu); - } else { - console.error('New parent element not found!'); - } - } else { - console.error('Flyout menu not found in shadow DOM!'); - } - } else { - console.error('Shadow root not found!'); - } - } else { - console.error('Shadow host element not found!'); - } -}); diff --git a/conf.py b/conf.py index a025a1838..46c0bdedc 100644 --- a/conf.py +++ b/conf.py @@ -74,9 +74,7 @@ html_static_path = ['_static'] -html_js_files = [ - 'custom.js', # Relative to the _static path -] + html_css_files = [ 'css/custom.css', # Relative to the _static path From af889d7824779a3a7bc7b0633936658023147d2e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 10:56:09 +0300 Subject: [PATCH 1470/1892] Reapply "Flyout menu addons" This reverts commit 020e037ae3bb85f3363754a62d8575c18863aedb. --- _static/css/custom_flyout.css | 4 ++++ conf.py | 6 ++++++ 2 files changed, 10 insertions(+) create mode 100644 _static/css/custom_flyout.css diff --git a/_static/css/custom_flyout.css b/_static/css/custom_flyout.css new file mode 100644 index 000000000..b02bc7794 --- /dev/null +++ b/_static/css/custom_flyout.css @@ -0,0 +1,4 @@ +.container.bottom-left { + left: 20px; + bottom: 50px; +} \ No newline at end of file diff --git a/conf.py b/conf.py index 46c0bdedc..4686744ca 100644 --- a/conf.py +++ b/conf.py @@ -23,6 +23,11 @@ import sphinx_rtd_theme +# Overrides RTD Addons Flyout menu to appear on the left hand side + +def setup(app): + app.add_css_file('css/custom.css') + app.add_css_file('css/custom_flyout.css') # -- Project information ----------------------------------------------------- @@ -78,6 +83,7 @@ html_css_files = [ 'css/custom.css', # Relative to the _static path + 'css/custom_flyout.css' ] html_logo = '_static/images/SQream_logo_without background-15.png' From 54c5d606665cae5a81bcb4723f592cace568256d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:06:08 +0300 Subject: [PATCH 1471/1892] Update custom_flyout.css --- _static/css/custom_flyout.css | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_static/css/custom_flyout.css b/_static/css/custom_flyout.css index b02bc7794..486556140 100644 --- a/_static/css/custom_flyout.css +++ b/_static/css/custom_flyout.css @@ -1,4 +1,4 @@ .container.bottom-left { - left: 20px; - bottom: 50px; -} \ No newline at end of file + left: 20px !important; + bottom: 50px !important; +} From b62e51f666812b13883044af28263b032a20bbb5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:13:13 +0300 Subject: [PATCH 1472/1892] Update custom_flyout.css --- _static/css/custom_flyout.css | 1 + 1 file changed, 1 insertion(+) diff --git a/_static/css/custom_flyout.css b/_static/css/custom_flyout.css index 486556140..00b911489 100644 --- a/_static/css/custom_flyout.css +++ b/_static/css/custom_flyout.css @@ -1,4 +1,5 @@ .container.bottom-left { + background-color: red !important; /* For testing */ left: 20px !important; bottom: 50px !important; } From b5be0b645fa8efe6a121b42d30e00d95a8659a7d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:18:26 +0300 Subject: [PATCH 1473/1892] Update custom_flyout.css --- _static/css/custom_flyout.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/css/custom_flyout.css b/_static/css/custom_flyout.css index 00b911489..363b5f270 100644 --- a/_static/css/custom_flyout.css +++ b/_static/css/custom_flyout.css @@ -1,4 +1,4 @@ -.container.bottom-left { +body .container.bottom-left { background-color: red !important; /* For testing */ left: 20px !important; bottom: 50px !important; From 822490012f6cd6950747e2e62ad4b4e26900332b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:27:56 +0300 Subject: [PATCH 1474/1892] Update conf.py --- conf.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/conf.py b/conf.py index 4686744ca..776710407 100644 --- a/conf.py +++ b/conf.py @@ -25,9 +25,6 @@ # Overrides RTD Addons Flyout menu to appear on the left hand side -def setup(app): - app.add_css_file('css/custom.css') - app.add_css_file('css/custom_flyout.css') # -- Project information ----------------------------------------------------- From 65817c1826b7447df473788a87a60fd45f14c58a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 11:43:37 +0300 Subject: [PATCH 1475/1892] Menu --- _static/js/custom.js | 18 ++++++++++++++++++ conf.py | 4 ++++ 2 files changed, 22 insertions(+) create mode 100644 _static/js/custom.js diff --git a/_static/js/custom.js b/_static/js/custom.js new file mode 100644 index 000000000..915a9f1d4 --- /dev/null +++ b/_static/js/custom.js @@ -0,0 +1,18 @@ +document.addEventListener('DOMContentLoaded', function() { + const flyoutElement = document.querySelector('readthedocs-flyout'); + + if (flyoutElement) { + // Modify the position property + flyoutElement.position = 'bottom-left'; // or any other position if available + flyoutElement.requestUpdate(); // Request an update to apply the change + + // Apply custom styles directly if needed + const style = document.createElement('style'); + style.textContent = ` + readthedocs-flyout { + /* Custom styles if needed */ + } + `; + document.head.appendChild(style); + } +}); diff --git a/conf.py b/conf.py index 776710407..e9e38f32f 100644 --- a/conf.py +++ b/conf.py @@ -24,6 +24,10 @@ import sphinx_rtd_theme # Overrides RTD Addons Flyout menu to appear on the left hand side +def setup(app): + app.add_css_file('css/custom.css') + app.add_css_file('css/custom_flyout.css') + app.add_js_file('js/custom.js') # Ensure you use the correct path From a76ee6a42f15e920f37235f698991fd99fef335e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 13:49:37 +0300 Subject: [PATCH 1476/1892] Addons --- _static/css/custom_flyout.css | 5 ----- conf.py | 6 ------ 2 files changed, 11 deletions(-) delete mode 100644 _static/css/custom_flyout.css diff --git a/_static/css/custom_flyout.css b/_static/css/custom_flyout.css deleted file mode 100644 index 363b5f270..000000000 --- a/_static/css/custom_flyout.css +++ /dev/null @@ -1,5 +0,0 @@ -body .container.bottom-left { - background-color: red !important; /* For testing */ - left: 20px !important; - bottom: 50px !important; -} diff --git a/conf.py b/conf.py index e9e38f32f..680ce7be5 100644 --- a/conf.py +++ b/conf.py @@ -23,11 +23,6 @@ import sphinx_rtd_theme -# Overrides RTD Addons Flyout menu to appear on the left hand side -def setup(app): - app.add_css_file('css/custom.css') - app.add_css_file('css/custom_flyout.css') - app.add_js_file('js/custom.js') # Ensure you use the correct path @@ -84,7 +79,6 @@ def setup(app): html_css_files = [ 'css/custom.css', # Relative to the _static path - 'css/custom_flyout.css' ] html_logo = '_static/images/SQream_logo_without background-15.png' From 022639f7a8ba83518ef96e3c5de9a67d00518ac7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:09:32 +0300 Subject: [PATCH 1477/1892] JS --- _static/js/custom.js | 418 +++++++++++++++++++++++++++++++++++++++++-- conf.py | 4 +- 2 files changed, 403 insertions(+), 19 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index 915a9f1d4..368bc6176 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,18 +1,400 @@ -document.addEventListener('DOMContentLoaded', function() { - const flyoutElement = document.querySelector('readthedocs-flyout'); - - if (flyoutElement) { - // Modify the position property - flyoutElement.position = 'bottom-left'; // or any other position if available - flyoutElement.requestUpdate(); // Request an update to apply the change - - // Apply custom styles directly if needed - const style = document.createElement('style'); - style.textContent = ` - readthedocs-flyout { - /* Custom styles if needed */ - } - `; - document.head.appendChild(style); - } -}); +import { ajv } from "./data-validation"; +import READTHEDOCS_LOGO from "./images/logo-wordmark-light.svg"; +import { library, icon } from "@fortawesome/fontawesome-svg-core"; +import { faCodeBranch } from "@fortawesome/free-solid-svg-icons"; +import { html, nothing, render, LitElement } from "lit"; +import { classMap } from "lit/directives/class-map.js"; +import { default as objectPath } from "object-path"; + +import styleSheet from "./flyout.css"; +import { AddonBase, addUtmParameters } from "./utils"; +import { + EVENT_READTHEDOCS_SEARCH_SHOW, + EVENT_READTHEDOCS_FLYOUT_HIDE, + EVENT_READTHEDOCS_FLYOUT_SHOW, +} from "./events"; + +export class FlyoutElement extends LitElement { + static elementName = "readthedocs-flyout"; + + static properties = { + config: { state: true }, + opened: { type: Boolean }, + floating: { type: Boolean }, + position: { type: String }, + }; + + static styles = styleSheet; + + constructor() { + super(); + + this.config = null; + this.opened = false; + this.floating = true; + this.position = "bottom-right"; + } + + loadConfig(config) { + // Validate the config object before assigning it to the Addon. + // Later, ``render()`` method will check whether this object exists and (not) render + // accordingly + if (!FlyoutAddon.isEnabled(config)) { + return; + } + this.config = config; + } + + _toggleOpen(e) { + this.opened = !this.opened; + } + + _onOutsideClick = (e) => { + if (e.target !== this) { + this.opened = false; + } + }; + + renderHeader() { + library.add(faCodeBranch); + const iconCodeBranch = icon(faCodeBranch, { + classes: ["icon"], + }); + let version = nothing; + if ( + this.config.projects.current.versioning_scheme !== + "single_version_without_translations" + ) { + version = html`<span + >${iconCodeBranch.node[0]} ${this.config.versions.current.slug}</span + >`; + } + + return html` + <header @click="${this._toggleOpen}"> + <img class="logo" src="${READTHEDOCS_LOGO}" alt="Read the Docs" /> + ${version} + </header> + `; + } + + renderFooter() { + return html` + <small> + <span> + <a + href="${addUtmParameters( + "https://docs.readthedocs.io/page/addons.html", + "flyout", + )}" + >Addons documentation</a + ></span + > + <span> ― </span> + <span + >Hosted by + <a + href="${addUtmParameters( + "https://about.readthedocs.com/", + "flyout", + )}" + >Read the Docs</a + ></span + > + </small> + `; + } + + showSearch() { + // Dispatch the custom event to hide/collapse the flyout when showing the search modal + const flyoutEvent = new CustomEvent(EVENT_READTHEDOCS_FLYOUT_HIDE); + document.dispatchEvent(flyoutEvent); + + // Dispatch the custom event the search addon is listening to show the modal + const searchEvent = new CustomEvent(EVENT_READTHEDOCS_SEARCH_SHOW); + document.dispatchEvent(searchEvent); + } + + renderSearch() { + // Display the search input only if the search is enabled for this project + // Note we use ``objectPath`` here instead of validating via JSON schema + // because this value is optional: even if the search API response is broken, + // we want to keep showing the flyout but without the search input. + const searchEnabled = objectPath.get( + this.config, + "addons.search.enabled", + false, + ); + if (searchEnabled) { + return html` + <dl> + <dt>Search</dt> + <dd> + <form @focusin="${this.showSearch}" id="flyout-search-form"> + <input + type="text" + name="q" + aria-label="Search docs" + placeholder="Search docs" + /> + </form> + </dd> + </dl> + `; + } + return nothing; + } + + renderVCS() { + if ( + // TODO: remove this check when ``vcs`` property becomes required + !this.config.addons.flyout.vcs || + !this.config.addons.flyout.vcs.view_url + ) { + return nothing; + } + const { vcs } = this.config.addons.flyout; + + return html` + <dl> + <dt>On ${vcs.name}</dt> + <dd> + <a href="${vcs.view_url}">View</a> + </dd> + </dl> + `; + } + + renderReadTheDocs() { + return html` + <dl> + <dt>On Read the Docs</dt> + <dd> + <a + href="${addUtmParameters( + this.config.projects.current.urls.home + .replace("readthedocs.org", "app.readthedocs.org") + .replace("readthedocs.com", "app.readthedocs.com"), + "flyout", + )}" + >Project Home</a + > + </dd> + <dd> + <a + href="${addUtmParameters( + this.config.projects.current.urls.builds + .replace("readthedocs.org", "app.readthedocs.org") + .replace("readthedocs.com", "app.readthedocs.com"), + "flyout", + )}" + >Builds</a + > + </dd> + </dl> + `; + } + + renderDownloads() { + if (!Object.keys(this.config.versions.current.downloads).length) { + return nothing; + } + + const nameDisplay = { + pdf: "PDF", + epub: "EPUB", + htmlzip: "HTML", + }; + + return html` + <dl class="downloads"> + <dt>Downloads</dt> + ${Object.entries(this.config.versions.current.downloads).map( + ([name, url]) => + html`<dd> + <a href="${url}">${nameDisplay[name]}</a> + </dd>`, + )} + </dl> + `; + } + + _getFlyoutLinkWithFilename = (url) => { + // Get the resolver's filename returned by the application (as HTTP header) + // and injected by Cloudflare Worker as a meta HTML tag + const metaFilename = document.querySelector( + "meta[name='readthedocs-resolver-filename']", + ); + + // Remove trailing slashes from the version's URL and append the + // resolver's filename after removing trailing ``index.html``. + // Examples: + // + // URL: https://docs.readthedocs.io/en/latest/ + // Filename: /index.html + // Flyuout URL: https://docs.readthedocs.io/en/latest/ + // + // URL: https://docs.readthedocs.io/en/stable/ + // Filename: /guides/access/index.html + // Flyuout URL: https://docs.readthedocs.io/en/stable/guides/access/ + + // Keep only one trailing slash + const base = url.replace(/\/+$/, "/"); + + // 1. remove initial slash to make it relative to the base + // 2. remove the trailing "index.html" + const filename = metaFilename.content + .replace(/\/index.html$/, "/") + .replace(/^\//, ""); + + return new URL(filename, base); + }; + + renderVersions() { + if ( + !this.config.versions.active.length || + this.config.projects.current.versioning_scheme === + "single_version_without_translations" + ) { + return nothing; + } + + const getVersionLink = (version) => { + const url = this._getFlyoutLinkWithFilename(version.urls.documentation); + const link = html`<a href="${url}">${version.slug}</a>`; + return this.config.versions.current.slug == version.slug + ? html`<strong>${link}</strong>` + : link; + }; + + return html` + <dl class="versions"> + <dt>Versions</dt> + ${this.config.versions.active.map( + (version) => html`<dd>${getVersionLink(version)}</dd>`, + )} + </dl> + `; + } + + renderLanguages() { + if (!this.config.projects.translations.length) { + return nothing; + } + + const getLanguageLink = (translation) => { + const url = this._getFlyoutLinkWithFilename( + translation.urls.documentation, + ); + const link = html`<a href="${url}">${translation.language.code}</a>`; + return this.config.projects.current.slug === translation.slug + ? html`<strong>${link}</strong>` + : link; + }; + + // Add the current project as "translation" and sort them based on language's code + let translations = this.config.projects.translations.concat( + this.config.projects.current, + ); + translations = translations.sort((a, b) => + a.language.code.localeCompare(b.language.code), + ); + + return html` + <dl class="languages"> + <dt>Languages</dt> + ${translations.map( + (translation) => html`<dd>${getLanguageLink(translation)}</dd>`, + )} + </dl> + `; + } + + render() { + // The element doesn't yet have our config, don't render it. + if (this.config === null) { + // nothing is a special Lit response type + return nothing; + } + + const classes = { floating: this.floating, container: true }; + classes[this.position] = true; + + return html` + <div class=${classMap(classes)}> + ${this.renderHeader()} + <main class=${classMap({ closed: !this.opened })}> + ${this.renderLanguages()} ${this.renderVersions()} + ${this.renderDownloads()} ${this.renderReadTheDocs()} + ${this.renderVCS()} ${this.renderSearch()} + <hr /> + ${this.renderFooter()} + </main> + </div> + `; + } + + _showFlyout = (e) => { + this.opened = true; + }; + + _hideFlyout = (e) => { + this.opened = false; + }; + + connectedCallback() { + super.connectedCallback(); + + document.addEventListener(EVENT_READTHEDOCS_FLYOUT_SHOW, this._showFlyout); + document.addEventListener(EVENT_READTHEDOCS_FLYOUT_HIDE, this._hideFlyout); + window.addEventListener("click", this._onOutsideClick); + } + + disconnectedCallback() { + document.removeEventListener( + EVENT_READTHEDOCS_FLYOUT_SHOW, + this.showFlyout, + ); + + document.removeEventListener( + EVENT_READTHEDOCS_FLYOUT_HIDE, + this.hideFlyout, + ); + window.removeEventListener("click", this._onOutsideClick); + + super.disconnectedCallback(); + } +} + +/** + * Flyout addon + * + * @param {Object} config - Addon configuration object + */ +export class FlyoutAddon extends AddonBase { + static jsonValidationURI = + "http://v1.schemas.readthedocs.org/addons.flyout.json"; + static addonEnabledPath = "addons.flyout.enabled"; + static addonName = "Flyout"; + + constructor(config) { + super(); + + // If there are no elements found, inject one + let elems = document.querySelectorAll("readthedocs-flyout"); + if (!elems.length) { + elems = [new FlyoutElement()]; + + // We cannot use `render(elems[0], document.body)` because there is a race conditions between all the addons. + // So, we append the web-component first and then request an update of it. + document.body.append(elems[0]); + elems[0].requestUpdate(); + } + + for (const elem of elems) { + elem.loadConfig(config); + } + } +} + +customElements.define("readthedocs-flyout", FlyoutElement); diff --git a/conf.py b/conf.py index 680ce7be5..61155083c 100644 --- a/conf.py +++ b/conf.py @@ -75,7 +75,9 @@ html_static_path = ['_static'] - +html_js_files = [ + 'js/custom.js', # Relative to the _static path +] html_css_files = [ 'css/custom.css', # Relative to the _static path From 2f1ca5f3083b8ce8d6a32490057c1c45f788ffda Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:24:43 +0300 Subject: [PATCH 1478/1892] Update custom.js --- _static/js/custom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index 368bc6176..1b88e2adc 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -32,7 +32,7 @@ export class FlyoutElement extends LitElement { this.config = null; this.opened = false; this.floating = true; - this.position = "bottom-right"; + this.position = "bottom-left"; } loadConfig(config) { From fbb4ec8e10ece6a31f7207e47e437da1fad2898a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:44:04 +0300 Subject: [PATCH 1479/1892] Update conf.py --- conf.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/conf.py b/conf.py index 61155083c..c87cca98b 100644 --- a/conf.py +++ b/conf.py @@ -23,9 +23,6 @@ import sphinx_rtd_theme - - - # -- Project information ----------------------------------------------------- project = 'SQreamDB' @@ -36,8 +33,6 @@ # The full version, including alpha/beta/rc tags release = '4.7' - - # -- General configuration --------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be @@ -74,6 +69,9 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] +# Include custom JavaScript file +def setup(app): + app.add_js_file('js/custom.js') html_js_files = [ 'js/custom.js', # Relative to the _static path From 28657dc0dd39bbe23f1ecb0c4ffe6282f68ab507 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 14:57:11 +0300 Subject: [PATCH 1480/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index c87cca98b..f3c617c25 100644 --- a/conf.py +++ b/conf.py @@ -71,7 +71,7 @@ # Include custom JavaScript file def setup(app): - app.add_js_file('js/custom.js') + app.add_js_file('js/custom.js', type="module") html_js_files = [ 'js/custom.js', # Relative to the _static path From a6a9f580d44cd470c1de8aeeaed0dae8b5b78ea6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:05:15 +0300 Subject: [PATCH 1481/1892] Update conf.py --- conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conf.py b/conf.py index f3c617c25..fbd56db4d 100644 --- a/conf.py +++ b/conf.py @@ -73,6 +73,7 @@ def setup(app): app.add_js_file('js/custom.js', type="module") + html_js_files = [ 'js/custom.js', # Relative to the _static path ] From 129a336ef5d00228842fb63d846b1d93f315decc Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:10:06 +0300 Subject: [PATCH 1482/1892] Update custom.js --- _static/js/custom.js | 352 +++---------------------------------------- 1 file changed, 19 insertions(+), 333 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index 1b88e2adc..e8fc728eb 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,20 +1,9 @@ -import { ajv } from "./data-validation"; -import READTHEDOCS_LOGO from "./images/logo-wordmark-light.svg"; -import { library, icon } from "@fortawesome/fontawesome-svg-core"; -import { faCodeBranch } from "@fortawesome/free-solid-svg-icons"; -import { html, nothing, render, LitElement } from "lit"; -import { classMap } from "lit/directives/class-map.js"; -import { default as objectPath } from "object-path"; +// Import necessary modules from CDNs +import { LitElement, html, css, nothing } from 'https://unpkg.com/lit-element/lit-element.js?module'; +import { classMap } from 'https://unpkg.com/lit-html/directives/class-map.js?module'; -import styleSheet from "./flyout.css"; -import { AddonBase, addUtmParameters } from "./utils"; -import { - EVENT_READTHEDOCS_SEARCH_SHOW, - EVENT_READTHEDOCS_FLYOUT_HIDE, - EVENT_READTHEDOCS_FLYOUT_SHOW, -} from "./events"; - -export class FlyoutElement extends LitElement { +// Define the custom flyout element +class CustomFlyoutElement extends LitElement { static elementName = "readthedocs-flyout"; static properties = { @@ -24,296 +13,41 @@ export class FlyoutElement extends LitElement { position: { type: String }, }; - static styles = styleSheet; - constructor() { super(); - this.config = null; this.opened = false; this.floating = true; - this.position = "bottom-left"; + this.position = "bottom-left"; // Set default position to bottom-left } loadConfig(config) { - // Validate the config object before assigning it to the Addon. - // Later, ``render()`` method will check whether this object exists and (not) render - // accordingly if (!FlyoutAddon.isEnabled(config)) { return; } this.config = config; } - _toggleOpen(e) { + _toggleOpen() { this.opened = !this.opened; } - _onOutsideClick = (e) => { + _onOutsideClick(e) { if (e.target !== this) { this.opened = false; } - }; + } renderHeader() { - library.add(faCodeBranch); - const iconCodeBranch = icon(faCodeBranch, { - classes: ["icon"], - }); - let version = nothing; - if ( - this.config.projects.current.versioning_scheme !== - "single_version_without_translations" - ) { - version = html`<span - >${iconCodeBranch.node[0]} ${this.config.versions.current.slug}</span - >`; - } - return html` <header @click="${this._toggleOpen}"> - <img class="logo" src="${READTHEDOCS_LOGO}" alt="Read the Docs" /> - ${version} + <img class="logo" src="https://example.com/logo.svg" alt="Read the Docs" /> </header> `; } - renderFooter() { - return html` - <small> - <span> - <a - href="${addUtmParameters( - "https://docs.readthedocs.io/page/addons.html", - "flyout", - )}" - >Addons documentation</a - ></span - > - <span> ― </span> - <span - >Hosted by - <a - href="${addUtmParameters( - "https://about.readthedocs.com/", - "flyout", - )}" - >Read the Docs</a - ></span - > - </small> - `; - } - - showSearch() { - // Dispatch the custom event to hide/collapse the flyout when showing the search modal - const flyoutEvent = new CustomEvent(EVENT_READTHEDOCS_FLYOUT_HIDE); - document.dispatchEvent(flyoutEvent); - - // Dispatch the custom event the search addon is listening to show the modal - const searchEvent = new CustomEvent(EVENT_READTHEDOCS_SEARCH_SHOW); - document.dispatchEvent(searchEvent); - } - - renderSearch() { - // Display the search input only if the search is enabled for this project - // Note we use ``objectPath`` here instead of validating via JSON schema - // because this value is optional: even if the search API response is broken, - // we want to keep showing the flyout but without the search input. - const searchEnabled = objectPath.get( - this.config, - "addons.search.enabled", - false, - ); - if (searchEnabled) { - return html` - <dl> - <dt>Search</dt> - <dd> - <form @focusin="${this.showSearch}" id="flyout-search-form"> - <input - type="text" - name="q" - aria-label="Search docs" - placeholder="Search docs" - /> - </form> - </dd> - </dl> - `; - } - return nothing; - } - - renderVCS() { - if ( - // TODO: remove this check when ``vcs`` property becomes required - !this.config.addons.flyout.vcs || - !this.config.addons.flyout.vcs.view_url - ) { - return nothing; - } - const { vcs } = this.config.addons.flyout; - - return html` - <dl> - <dt>On ${vcs.name}</dt> - <dd> - <a href="${vcs.view_url}">View</a> - </dd> - </dl> - `; - } - - renderReadTheDocs() { - return html` - <dl> - <dt>On Read the Docs</dt> - <dd> - <a - href="${addUtmParameters( - this.config.projects.current.urls.home - .replace("readthedocs.org", "app.readthedocs.org") - .replace("readthedocs.com", "app.readthedocs.com"), - "flyout", - )}" - >Project Home</a - > - </dd> - <dd> - <a - href="${addUtmParameters( - this.config.projects.current.urls.builds - .replace("readthedocs.org", "app.readthedocs.org") - .replace("readthedocs.com", "app.readthedocs.com"), - "flyout", - )}" - >Builds</a - > - </dd> - </dl> - `; - } - - renderDownloads() { - if (!Object.keys(this.config.versions.current.downloads).length) { - return nothing; - } - - const nameDisplay = { - pdf: "PDF", - epub: "EPUB", - htmlzip: "HTML", - }; - - return html` - <dl class="downloads"> - <dt>Downloads</dt> - ${Object.entries(this.config.versions.current.downloads).map( - ([name, url]) => - html`<dd> - <a href="${url}">${nameDisplay[name]}</a> - </dd>`, - )} - </dl> - `; - } - - _getFlyoutLinkWithFilename = (url) => { - // Get the resolver's filename returned by the application (as HTTP header) - // and injected by Cloudflare Worker as a meta HTML tag - const metaFilename = document.querySelector( - "meta[name='readthedocs-resolver-filename']", - ); - - // Remove trailing slashes from the version's URL and append the - // resolver's filename after removing trailing ``index.html``. - // Examples: - // - // URL: https://docs.readthedocs.io/en/latest/ - // Filename: /index.html - // Flyuout URL: https://docs.readthedocs.io/en/latest/ - // - // URL: https://docs.readthedocs.io/en/stable/ - // Filename: /guides/access/index.html - // Flyuout URL: https://docs.readthedocs.io/en/stable/guides/access/ - - // Keep only one trailing slash - const base = url.replace(/\/+$/, "/"); - - // 1. remove initial slash to make it relative to the base - // 2. remove the trailing "index.html" - const filename = metaFilename.content - .replace(/\/index.html$/, "/") - .replace(/^\//, ""); - - return new URL(filename, base); - }; - - renderVersions() { - if ( - !this.config.versions.active.length || - this.config.projects.current.versioning_scheme === - "single_version_without_translations" - ) { - return nothing; - } - - const getVersionLink = (version) => { - const url = this._getFlyoutLinkWithFilename(version.urls.documentation); - const link = html`<a href="${url}">${version.slug}</a>`; - return this.config.versions.current.slug == version.slug - ? html`<strong>${link}</strong>` - : link; - }; - - return html` - <dl class="versions"> - <dt>Versions</dt> - ${this.config.versions.active.map( - (version) => html`<dd>${getVersionLink(version)}</dd>`, - )} - </dl> - `; - } - - renderLanguages() { - if (!this.config.projects.translations.length) { - return nothing; - } - - const getLanguageLink = (translation) => { - const url = this._getFlyoutLinkWithFilename( - translation.urls.documentation, - ); - const link = html`<a href="${url}">${translation.language.code}</a>`; - return this.config.projects.current.slug === translation.slug - ? html`<strong>${link}</strong>` - : link; - }; - - // Add the current project as "translation" and sort them based on language's code - let translations = this.config.projects.translations.concat( - this.config.projects.current, - ); - translations = translations.sort((a, b) => - a.language.code.localeCompare(b.language.code), - ); - - return html` - <dl class="languages"> - <dt>Languages</dt> - ${translations.map( - (translation) => html`<dd>${getLanguageLink(translation)}</dd>`, - )} - </dl> - `; - } - render() { - // The element doesn't yet have our config, don't render it. if (this.config === null) { - // nothing is a special Lit response type return nothing; } @@ -324,77 +58,29 @@ export class FlyoutElement extends LitElement { <div class=${classMap(classes)}> ${this.renderHeader()} <main class=${classMap({ closed: !this.opened })}> - ${this.renderLanguages()} ${this.renderVersions()} - ${this.renderDownloads()} ${this.renderReadTheDocs()} - ${this.renderVCS()} ${this.renderSearch()} - <hr /> - ${this.renderFooter()} + <!-- Add other render methods if needed --> </main> </div> `; } - _showFlyout = (e) => { - this.opened = true; - }; - - _hideFlyout = (e) => { - this.opened = false; - }; - connectedCallback() { super.connectedCallback(); - - document.addEventListener(EVENT_READTHEDOCS_FLYOUT_SHOW, this._showFlyout); - document.addEventListener(EVENT_READTHEDOCS_FLYOUT_HIDE, this._hideFlyout); - window.addEventListener("click", this._onOutsideClick); + window.addEventListener("click", this._onOutsideClick.bind(this)); } disconnectedCallback() { - document.removeEventListener( - EVENT_READTHEDOCS_FLYOUT_SHOW, - this.showFlyout, - ); - - document.removeEventListener( - EVENT_READTHEDOCS_FLYOUT_HIDE, - this.hideFlyout, - ); - window.removeEventListener("click", this._onOutsideClick); - + window.removeEventListener("click", this._onOutsideClick.bind(this)); super.disconnectedCallback(); } } -/** - * Flyout addon - * - * @param {Object} config - Addon configuration object - */ -export class FlyoutAddon extends AddonBase { - static jsonValidationURI = - "http://v1.schemas.readthedocs.org/addons.flyout.json"; - static addonEnabledPath = "addons.flyout.enabled"; - static addonName = "Flyout"; +customElements.define("readthedocs-flyout", CustomFlyoutElement); - constructor(config) { - super(); +document.addEventListener('DOMContentLoaded', function() { + const flyoutElement = document.querySelector('readthedocs-flyout'); - // If there are no elements found, inject one - let elems = document.querySelectorAll("readthedocs-flyout"); - if (!elems.length) { - elems = [new FlyoutElement()]; - - // We cannot use `render(elems[0], document.body)` because there is a race conditions between all the addons. - // So, we append the web-component first and then request an update of it. - document.body.append(elems[0]); - elems[0].requestUpdate(); + if (flyoutElement) { + flyoutElement.position = 'bottom-left'; // Set position to bottom-left } - - for (const elem of elems) { - elem.loadConfig(config); - } - } -} - -customElements.define("readthedocs-flyout", FlyoutElement); +}); From a9d58823606319911029255467468cd7a88c5c80 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:16:07 +0300 Subject: [PATCH 1483/1892] Update custom.js --- _static/js/custom.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index e8fc728eb..68c875e5a 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,6 +1,6 @@ -// Import necessary modules from CDNs -import { LitElement, html, css, nothing } from 'https://unpkg.com/lit-element/lit-element.js?module'; -import { classMap } from 'https://unpkg.com/lit-html/directives/class-map.js?module'; +// Import necessary modules from jsDelivr +import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element@2.5.1/lit-element.js'; +import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html@1.3.0/directives/class-map.js'; // Define the custom flyout element class CustomFlyoutElement extends LitElement { From 823a9c1daec7a35c4fe9a6af4333728a165f9b9f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:21:09 +0300 Subject: [PATCH 1484/1892] Update custom.js --- _static/js/custom.js | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index 68c875e5a..5d28b0c59 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,17 +1,17 @@ // Import necessary modules from jsDelivr -import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element@2.5.1/lit-element.js'; -import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html@1.3.0/directives/class-map.js'; +import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element/lit-element.js'; +import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html/directives/class-map.js'; // Define the custom flyout element class CustomFlyoutElement extends LitElement { - static elementName = "readthedocs-flyout"; - - static properties = { - config: { state: true }, - opened: { type: Boolean }, - floating: { type: Boolean }, - position: { type: String }, - }; + static get properties() { + return { + config: { type: Object }, + opened: { type: Boolean }, + floating: { type: Boolean }, + position: { type: String }, + }; + } constructor() { super(); @@ -22,7 +22,7 @@ class CustomFlyoutElement extends LitElement { } loadConfig(config) { - if (!FlyoutAddon.isEnabled(config)) { + if (!this.isEnabled(config)) { return; } this.config = config; @@ -73,14 +73,18 @@ class CustomFlyoutElement extends LitElement { window.removeEventListener("click", this._onOutsideClick.bind(this)); super.disconnectedCallback(); } + + isEnabled(config) { + return config.addons && config.addons.flyout && config.addons.flyout.enabled; + } } customElements.define("readthedocs-flyout", CustomFlyoutElement); document.addEventListener('DOMContentLoaded', function() { - const flyoutElement = document.querySelector('readthedocs-flyout'); + const flyoutElement = document.querySelector('readthedocs-flyout'); - if (flyoutElement) { - flyoutElement.position = 'bottom-left'; // Set position to bottom-left - } + if (flyoutElement) { + flyoutElement.position = 'bottom-left'; // Set position to bottom-left + } }); From f66628d550b905344d4dca2de9c16d4d8ab3123c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:26:12 +0300 Subject: [PATCH 1485/1892] Update custom.js --- _static/js/custom.js | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index 5d28b0c59..c4fc270ec 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,6 +1,8 @@ -// Import necessary modules from jsDelivr import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element/lit-element.js'; import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html/directives/class-map.js'; +import { library, icon } from 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core/index.js'; +import { faCodeBranch } from 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons/index.js'; +import READTHEDOCS_LOGO from 'https://your-cdn-path/logo.svg'; // Update this to your actual logo path // Define the custom flyout element class CustomFlyoutElement extends LitElement { @@ -39,9 +41,22 @@ class CustomFlyoutElement extends LitElement { } renderHeader() { + library.add(faCodeBranch); + const iconCodeBranch = icon(faCodeBranch, { + classes: ["icon"], + }); + let version = nothing; + if ( + this.config.projects.current.versioning_scheme !== + "single_version_without_translations" + ) { + version = html`<span>${iconCodeBranch.node[0]} ${this.config.versions.current.slug}</span>`; + } + return html` <header @click="${this._toggleOpen}"> - <img class="logo" src="https://example.com/logo.svg" alt="Read the Docs" /> + <img class="logo" src="${READTHEDOCS_LOGO}" alt="Read the Docs" /> + ${version} </header> `; } From 1840bd370c9478cea88f120e570a75fffeb508c7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 15:32:40 +0300 Subject: [PATCH 1486/1892] Update custom.js --- _static/js/custom.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index c4fc270ec..e1b53ae51 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -2,7 +2,7 @@ import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html/directives/class-map.js'; import { library, icon } from 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core/index.js'; import { faCodeBranch } from 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons/index.js'; -import READTHEDOCS_LOGO from 'https://your-cdn-path/logo.svg'; // Update this to your actual logo path + // Define the custom flyout element class CustomFlyoutElement extends LitElement { From 3bd107707f00b07dadfa10611d15572826d98fec Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:09:11 +0300 Subject: [PATCH 1487/1892] Addons --- _static/js/custom.js | 10 +++++----- conf.py | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/_static/js/custom.js b/_static/js/custom.js index e1b53ae51..c84e9a812 100644 --- a/_static/js/custom.js +++ b/_static/js/custom.js @@ -1,10 +1,10 @@ -import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element/lit-element.js'; -import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html/directives/class-map.js'; -import { library, icon } from 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core/index.js'; -import { faCodeBranch } from 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons/index.js'; +import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element@2.5.1/lit-element.js'; +import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html@1.4.1/directives/class-map.js'; +import { library, icon } from 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@1.2.30/index.js'; +import { faCodeBranch } from 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@5.15.3/index.js'; +const READTHEDOCS_LOGO = 'https://assets.readthedocs.org/static/images/logo-wordmark-light.svg'; -// Define the custom flyout element class CustomFlyoutElement extends LitElement { static get properties() { return { diff --git a/conf.py b/conf.py index fbd56db4d..5664be604 100644 --- a/conf.py +++ b/conf.py @@ -74,6 +74,7 @@ def setup(app): app.add_js_file('js/custom.js', type="module") + html_js_files = [ 'js/custom.js', # Relative to the _static path ] From 597507c8edd18bc09e833a11aa960d1d39b9cbe0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 25 Jul 2024 16:24:45 +0300 Subject: [PATCH 1488/1892] JS --- _static/css/custom.css | 5 -- _static/js/custom.js | 105 ----------------------------------------- conf.py | 6 --- 3 files changed, 116 deletions(-) delete mode 100644 _static/js/custom.js diff --git a/_static/css/custom.css b/_static/css/custom.css index d867791cf..89d255239 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -57,10 +57,5 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { display: none; } -.container.bottom-right { - bottom: 50px; } -div.dl { - display: none; -} \ No newline at end of file diff --git a/_static/js/custom.js b/_static/js/custom.js deleted file mode 100644 index c84e9a812..000000000 --- a/_static/js/custom.js +++ /dev/null @@ -1,105 +0,0 @@ -import { LitElement, html, css, nothing } from 'https://cdn.jsdelivr.net/npm/lit-element@2.5.1/lit-element.js'; -import { classMap } from 'https://cdn.jsdelivr.net/npm/lit-html@1.4.1/directives/class-map.js'; -import { library, icon } from 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-svg-core@1.2.30/index.js'; -import { faCodeBranch } from 'https://cdn.jsdelivr.net/npm/@fortawesome/free-solid-svg-icons@5.15.3/index.js'; - -const READTHEDOCS_LOGO = 'https://assets.readthedocs.org/static/images/logo-wordmark-light.svg'; - -class CustomFlyoutElement extends LitElement { - static get properties() { - return { - config: { type: Object }, - opened: { type: Boolean }, - floating: { type: Boolean }, - position: { type: String }, - }; - } - - constructor() { - super(); - this.config = null; - this.opened = false; - this.floating = true; - this.position = "bottom-left"; // Set default position to bottom-left - } - - loadConfig(config) { - if (!this.isEnabled(config)) { - return; - } - this.config = config; - } - - _toggleOpen() { - this.opened = !this.opened; - } - - _onOutsideClick(e) { - if (e.target !== this) { - this.opened = false; - } - } - - renderHeader() { - library.add(faCodeBranch); - const iconCodeBranch = icon(faCodeBranch, { - classes: ["icon"], - }); - let version = nothing; - if ( - this.config.projects.current.versioning_scheme !== - "single_version_without_translations" - ) { - version = html`<span>${iconCodeBranch.node[0]} ${this.config.versions.current.slug}</span>`; - } - - return html` - <header @click="${this._toggleOpen}"> - <img class="logo" src="${READTHEDOCS_LOGO}" alt="Read the Docs" /> - ${version} - </header> - `; - } - - render() { - if (this.config === null) { - return nothing; - } - - const classes = { floating: this.floating, container: true }; - classes[this.position] = true; - - return html` - <div class=${classMap(classes)}> - ${this.renderHeader()} - <main class=${classMap({ closed: !this.opened })}> - <!-- Add other render methods if needed --> - </main> - </div> - `; - } - - connectedCallback() { - super.connectedCallback(); - window.addEventListener("click", this._onOutsideClick.bind(this)); - } - - disconnectedCallback() { - window.removeEventListener("click", this._onOutsideClick.bind(this)); - super.disconnectedCallback(); - } - - isEnabled(config) { - return config.addons && config.addons.flyout && config.addons.flyout.enabled; - } -} - -customElements.define("readthedocs-flyout", CustomFlyoutElement); - -document.addEventListener('DOMContentLoaded', function() { - const flyoutElement = document.querySelector('readthedocs-flyout'); - - if (flyoutElement) { - flyoutElement.position = 'bottom-left'; // Set position to bottom-left - } -}); diff --git a/conf.py b/conf.py index 5664be604..5aa6570cd 100644 --- a/conf.py +++ b/conf.py @@ -69,14 +69,8 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -# Include custom JavaScript file -def setup(app): - app.add_js_file('js/custom.js', type="module") - -html_js_files = [ - 'js/custom.js', # Relative to the _static path ] html_css_files = [ From 3369abae4bf968af0dc518041f424a5bd4c5124c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:06:14 +0300 Subject: [PATCH 1489/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index f007fb1da..1147a987b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx_rtd_theme>=2.0.0 +sphinx_rtd_theme>=2.1.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From ad4c27ee25a86c9f3155e2267be4cdbe9dbb3a20 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:09:07 +0300 Subject: [PATCH 1490/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1147a987b..ea3d4ead4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx_rtd_theme>=2.1.0 +sphinx_rtd_theme==2.1.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From e039822d7571654805fbff3f61de9b17aeb61c4e Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:11:38 +0300 Subject: [PATCH 1491/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index ea3d4ead4..979ffb176 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx_rtd_theme==2.1.0 +phinx-rtd-theme==2.1.0rc1 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From 6c31c040643d27b8f33653b7357dc00e516f34f5 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:19:39 +0300 Subject: [PATCH 1492/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 979ffb176..bd4aecf99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -phinx-rtd-theme==2.1.0rc1 +phinx-rtd-theme==2.1.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From a1e6d83f8629ddd306d54b199b1aa90a94d4f08f Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:22:17 +0300 Subject: [PATCH 1493/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index bd4aecf99..73a097548 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -phinx-rtd-theme==2.1.0 +sphinx-rtd-theme==2.1.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From a65d6309bb3d68dec7b6adc95abb968cfa62d03c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:24:57 +0300 Subject: [PATCH 1494/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 73a097548..a8d601d66 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx-rtd-theme==2.1.0 +sphinx-rtd-theme==2.1.0rc1 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From d1b72f621c235f57d7677c8d7ce433d7cf29b33c Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 09:27:17 +0300 Subject: [PATCH 1495/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 5aa6570cd..ef850ccf8 100644 --- a/conf.py +++ b/conf.py @@ -71,7 +71,7 @@ -] + html_css_files = [ 'css/custom.css', # Relative to the _static path From efdaf88b33d682525714fa12aa59068af0454a06 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 10:46:29 +0300 Subject: [PATCH 1496/1892] Update conf.py --- conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conf.py b/conf.py index ef850ccf8..1ef12125b 100644 --- a/conf.py +++ b/conf.py @@ -63,6 +63,7 @@ # html_theme = 'sphinx_rtd_theme' +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, From 116a765273c3ffb9d1924544e3093bb375cbdd32 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 13:19:55 +0300 Subject: [PATCH 1497/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 98ffd0a3c..53cb9cad7 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -684,7 +684,7 @@ The following summary table DDL uses Oracle syntax. UPDATED_DTTM_FROM DATE VISIBLE, UPDATED_DTTM_TO DATE VISIBLE, LAST_VAL_INT NUMBER(22,0) VISIBLE, - LAST_VAL_TS DATE VISIBLE, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, START_TIME TIMESTAMP(6) VISIBLE, FINISH_TIME TIMESTAMP(6) VISIBLE, ELAPSED_SEC NUMBER VISIBLE, From 0cc99ec34265572873d3d63a212e4bde38e4ccde Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 28 Jul 2024 15:03:50 +0300 Subject: [PATCH 1498/1892] Update sso.rst --- configuration_guides/sso.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/configuration_guides/sso.rst b/configuration_guides/sso.rst index 57f6b5648..bf1fe288c 100644 --- a/configuration_guides/sso.rst +++ b/configuration_guides/sso.rst @@ -30,17 +30,15 @@ Setting SQreamDB Acceleration Studio "ssoValidateUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/userinfo" -#. Set Acceleration Studio to use SSO by adding the following flags to your ``sqream_admin_config.json`` file: +#. Set Acceleration Studio to use SSO by adding the following flag to your ``sqream_admin_config.json`` file: * ``mfaRedirectUrl`` flag with your redirect URL - * ``mfaLogoutUrl`` flag with your logout URL Example: .. code-block:: json "mfaRedirectUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/authorize?client_id=e5636823-fb99-4d38-bbd1-6a46175eddab&redirect_uri=https://ivans.sq.l/login&response_type=token&scope=openid profile p1:read:user", - "mfaLogoutUrl": "https://auth.pingone.eu/9db5d1c6-6dd6-4e40-b939-e0e4209e0ac5/as/signoff" If Acceleration Studio is not yet installed, you can set both URLs during its installation process. From 51c4a4c3bdbe614b0db8aaec59936d7197333c78 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 08:33:54 +0300 Subject: [PATCH 1499/1892] 4.7 RN --- releases/4.6.rst | 16 ++-------------- releases/4.7.rst | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index 8ec224789..a8e6edb9f 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -34,26 +34,20 @@ Compatibility Matrix New Features and Enhancements ----------------------------- + + ► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. .. note:: The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file -► :ref:`health_monitoring` - ► REHL 8.x is now officially supported. -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. - -► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. - ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` -► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. - ► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: * :ref:`is_table_exists` @@ -63,12 +57,6 @@ New Features and Enhancements ► Sign into SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. -► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. - -► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. - -► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. - ► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using keyword arguments. ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. diff --git a/releases/4.7.rst b/releases/4.7.rst index e7a2b1278..461160bbc 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,8 +35,23 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + + + +► :ref:`health_monitoring` + +► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + ► Multi-platform CLI ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. @@ -92,7 +107,7 @@ Version 4.7 resolved Issues +====================+=====================================================================================================================+ | SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | +--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-15690 | **Not fixed yet** - JDBC connector connectivity issue resulting in stuck queries | +| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | +--------------------+---------------------------------------------------------------------------------------------------------------------+ From b706a0ba65f21f6dad37d046fee04e73e67d3068 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 09:14:54 +0300 Subject: [PATCH 1500/1892] Update 4.7.rst --- releases/4.7.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/releases/4.7.rst b/releases/4.7.rst index 461160bbc..63c252a9a 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,6 +35,12 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. + +.. note:: + + The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file + ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. From 82872e3268ded34599c1507c6d810a4a0e6c4b0e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 10:33:00 +0300 Subject: [PATCH 1501/1892] Update custom.css --- _static/css/custom.css | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/_static/css/custom.css b/_static/css/custom.css index 89d255239..191c06250 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -59,3 +59,18 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } +/* Prevent the search box from popping out */ +.wy-side-nav-search .search { + position: static; + width: 100%; + max-width: none; + background: none; + border: none; + box-shadow: none; +} + +.wy-side-nav-search .search input { + width: 100%; + max-width: none; +} + From 9c8a53676f8813f42f5c6510f8cf6d870f868330 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:09:04 +0300 Subject: [PATCH 1502/1892] Update custom.css --- _static/css/custom.css | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index 191c06250..4a026374d 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -60,17 +60,6 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } /* Prevent the search box from popping out */ -.wy-side-nav-search .search { - position: static; - width: 100%; - max-width: none; - background: none; - border: none; - box-shadow: none; -} - -.wy-side-nav-search .search input { - width: 100%; - max-width: none; -} - +[role="search"] .background { + display: none; +} \ No newline at end of file From 8ae9c84b381a637a7c951860b614ab5d2f827f14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:18:08 +0300 Subject: [PATCH 1503/1892] Update custom.css --- _static/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index 4a026374d..4f624e3a0 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -61,5 +61,5 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { /* Prevent the search box from popping out */ [role="search"] .background { - display: none; + display: none !important; } \ No newline at end of file From 14454ad3f27afd99ad408dc3dd6c6b2763428b9e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 11:29:52 +0300 Subject: [PATCH 1504/1892] Update custom.css --- _static/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index 4f624e3a0..6528f3e5f 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -60,6 +60,6 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } /* Prevent the search box from popping out */ -[role="search"] .background { +div.search { display: none !important; } \ No newline at end of file From a3a6eed712aa56bdbf0a48d4763047467affd4dd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:10:06 +0300 Subject: [PATCH 1505/1892] Update custom.css --- _static/css/custom.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_static/css/custom.css b/_static/css/custom.css index 6528f3e5f..51281b5a8 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -62,4 +62,8 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { /* Prevent the search box from popping out */ div.search { display: none !important; +} + +.wy-side-nav-search { + display: block } \ No newline at end of file From 199899dc1a4d21fcca7e891cd6e626c97c464426 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:33:40 +0300 Subject: [PATCH 1506/1892] Update custom.css --- _static/css/custom.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/_static/css/custom.css b/_static/css/custom.css index 51281b5a8..b521f1e21 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -66,4 +66,9 @@ div.search { .wy-side-nav-search { display: block +} + +.container.bottom-right { + display: block; + } \ No newline at end of file From 63a767a6f2d5297fa5380eabc1016eaf06c6851a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:37:34 +0300 Subject: [PATCH 1507/1892] Update custom.css --- _static/css/custom.css | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index b521f1e21..eb4023156 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -59,16 +59,7 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } -/* Prevent the search box from popping out */ -div.search { - display: none !important; -} - -.wy-side-nav-search { - display: block -} - .container.bottom-right { - display: block; + display: none; } \ No newline at end of file From 6fa9359bae38020d0a4e54c71908d0b0cb0bdcb4 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:41:37 +0300 Subject: [PATCH 1508/1892] Update custom.css --- _static/css/custom.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_static/css/custom.css b/_static/css/custom.css index eb4023156..87535c4fe 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -60,6 +60,6 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } .container.bottom-right { - display: none; + display: none !important; } \ No newline at end of file From af2385ddfab3ca8b77a65e077adf646be8502da3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:58:41 +0300 Subject: [PATCH 1509/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index a8d601d66..cdf56e782 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx-rtd-theme==2.1.0rc1 +sphinx-rtd-theme>=2.1.0rc1 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From d95809a77461d6ab14061b3910b636c5ebc21ad5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:20:29 +0300 Subject: [PATCH 1510/1892] Update requirements.txt --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cdf56e782..9daea4d97 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx-rtd-theme>=2.1.0rc1 +sphinx-rtd-theme>=2.1.0 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From 9dab62823ba11013cb451b0428e0ef32de03cf66 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 29 Jul 2024 16:26:13 +0300 Subject: [PATCH 1511/1892] Theming --- conf.py | 2 +- requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf.py b/conf.py index 1ef12125b..d424c3d7e 100644 --- a/conf.py +++ b/conf.py @@ -63,7 +63,7 @@ # html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, diff --git a/requirements.txt b/requirements.txt index 9daea4d97..cdf56e782 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx-rtd-theme>=2.1.0 +sphinx-rtd-theme>=2.1.0rc1 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page From 7442435b158788aa19e899bdb5b89ac04c51fd42 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 30 Jul 2024 11:31:31 +0300 Subject: [PATCH 1512/1892] Oracle Autonomous Database --- data_ingestion/connection_string.ini | 4 ++++ data_ingestion/sqloader_as_a_service.rst | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data_ingestion/connection_string.ini b/data_ingestion/connection_string.ini index 9a1f17ebe..21e35c679 100644 --- a/data_ingestion/connection_string.ini +++ b/data_ingestion/connection_string.ini @@ -7,6 +7,10 @@ connectionStringSource=jdbc:postgresql://<HostIp:port>/<database_name>?user=<use # oracle connectionStringSource=jdbc:oracle:thin:@//<HostIp:port>/<database_name>?user=<user_name>&password=<password>&ssl=<true/false> +# Oracle Autonomous Database + +connectionStringSource=jdbc:oracle:thin:@<database_name>?tns_admin=<path_to_oracle_wallet>&user=<user>&password=<password> + # teradata connectionStringSource=jdbc:teradata://<HostIp>/DATABASE=<database_name>,DBS_PORT=<port>,user=<user_name>,password=<password> diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 53cb9cad7..ba9b66627 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -10,7 +10,7 @@ The **SQLoader** is a Java service that enables you to ingest data into SQreamDB * Greenplum * Microsoft SQL Server -* Oracle +* Oracle (including Oracle Autonomous Database) * Postgresql * SAP HANA * Sybase From a6396620adb1063e41b5426e3ae6febd7a9c6b61 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 08:31:22 +0300 Subject: [PATCH 1513/1892] Update subqueries.rst --- reference/sql/sql_syntax/subqueries.rst | 125 ++++++++++++++++++------ 1 file changed, 94 insertions(+), 31 deletions(-) diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 739098db6..74dee538a 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -24,15 +24,15 @@ The following is an example of table named ``nba`` with the following structure: CREATE TABLE nba ( - "Name" text(40), - "Team" text(40), - "Number" tinyint, - "Position" text(2), - "Age" tinyint, - "Height" text(4), - "Weight" real, - "College" text(40), - "Salary" float + "Name" TEXT, + "Team" TEXT, + "Number" TINYINT, + "Position" TEXT, + "Age" TINYINT, + "Height" TEXT, + "Weight" REAL, + "College" TEXT, + "Salary" FLOAT ); @@ -53,21 +53,48 @@ Simple Subquery .. code-block:: sql - t=> SELECT AVG("Age") FROM - . (SELECT "Name","Team","Age" FROM nba WHERE "Height" > '7-0'); - avg - --- - 26 + SELECT + AVG("Age") + FROM + ( + SELECT + "Name", + "Team", + "Age" + FROM + nba + WHERE + "Height" > '7-0' + ); + +.. code-block:: none + + avg + --- + 26 Combining a Subquery with a Join -------------------------------- .. code-block:: sql - t=> SELECT * FROM - . (SELECT "Name" FROM nba WHERE "Height" > '7-0') AS t(name) - . , nba AS n - . WHERE n."Name"=t.name; + SELECT + * + FROM + ( + SELECT + "Name" + FROM + nba + WHERE + "Height" > '7-0' + ) AS t(name), + nba AS n + WHERE + n."Name" = t.name; + +.. code-block:: none + name | Name | Team | Number | Position | Age | Height | Weight | College | Salary -------------------+--------------------+------------------------+--------+----------+-----+--------+--------+------------+--------- Alex Len | Alex Len | Phoenix Suns | 21 | C | 22 | 7-1 | 260 | Maryland | 3807120 @@ -92,14 +119,36 @@ See :ref:`common_table_expressions` for more information. .. code-block:: sql - nba=> WITH - . nba_ct AS (SELECT "Name", "Team" FROM nba WHERE "College"='Connecticut'), - . nba_az AS (SELECT "Name", "Team" FROM nba WHERE "College"='Arizona') - . SELECT * FROM nba_az JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; - Name | Team | name0 | team0 - ----------------+-----------------+----------------+---------------- - Stanley Johnson | Detroit Pistons | Andre Drummond | Detroit Pistons - Aaron Gordon | Orlando Magic | Shabazz Napier | Orlando Magic + WITH nba_ct AS ( + SELECT + "Name", + "Team" + FROM + nba + WHERE + "College" = 'Connecticut' + ), + nba_az AS ( + SELECT + "Name", + "Team" + FROM + nba + WHERE + "College" = 'Arizona' + ) + SELECT + * + FROM + nba_az + JOIN nba_ct ON nba_ct."Team" = nba_az."Team"; + +.. code-block:: none + + Name | Team | name0 | team0 + ----------------+-----------------+----------------+---------------- + Stanley Johnson | Detroit Pistons | Andre Drummond | Detroit Pistons + Aaron Gordon | Orlando Magic | Shabazz Napier | Orlando Magic Correlated subqueries ===================== @@ -111,15 +160,29 @@ Correlated subqueries are currently not supported. However, you may use the foll # Unsupported correlated subquery SELECT - x,y,z + x, + y, + z FROM t - where x in ( select x from t1 ); + WHERE + x in ( + SELECT + x + FROM + t1 + ); # Correlated subquery workaround - SELECT - x,y,z + x, + y, + z FROM t - JOIN (select x from t1) t1 on t.x = t1.x; \ No newline at end of file + JOIN ( + SELECT + x + FROM + t1 + ) t1 ON t.x = t1.x; \ No newline at end of file From 3e886b8ca5362f87082bb77c46cfa7b0cbd70c13 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 09:02:26 +0300 Subject: [PATCH 1514/1892] 4.7 RN --- releases/4.7.rst | 3 +-- releases/index.rst | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 63c252a9a..f3dd3e502 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -16,8 +16,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * CentOS - 7.x | -| | * RHEL - 7.x / 8.x | +| Supported OS | * RHEL - 7.x / 8.x | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +-------------------------+------------------------------------------------------------------------+ diff --git a/releases/index.rst b/releases/index.rst index 27d94856b..43ad86e08 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -6,13 +6,12 @@ Release Notes :ref:`Version 4.7 - March XX, 2024<4.7>` -* -* +* Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. +* Safely cast data types with the new :ref:`IsCastable<is_castable>` function. :ref:`Version 4.6 - XXXXX XX, 2024<4.6>` -* Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. -* Safely cast data types with the new :ref:`IsCastable<is_castable>` function. + :ref:`Version 4.5 - December 5, 2023<4.5>` From 945b77d652e52dc687f291470f1695d75c70020a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 09:49:45 +0300 Subject: [PATCH 1515/1892] Update 4.6.rst --- releases/4.6.rst | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index a8e6edb9f..1cd9b4711 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -24,28 +24,24 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | | | * Pysqream 5.0.0 | | | * Spark 5.0.0 | -| | * SQLoader 7.12 (compatible with v4.6.1 or later) | +| | * SQLoader 8.0 (compatible with v4.6.1 or later) | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements ----------------------------- - - -► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. - -.. note:: - - The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file - ► REHL 8.x is now officially supported. ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. +► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. + +► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using keyword arguments. + ► The ``clientReconnectionTimeout`` configuration flag has been reclassified as a cluster configuration flag. Unlike session flags, cluster flags apply to the entire cluster and persist across system restarts or shutdowns, retaining the configured value. Learn more about :ref:`SQreamDB configuration flags<current_method_configuration_levels>` ► Two new conditional functions that shorten complex query runtime by checking for the existence of tables and views within the specified schema: @@ -53,16 +49,8 @@ New Features and Enhancements * :ref:`is_table_exists` * :ref:`is_view_exists` -► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. - -► Sign into SQreamDB Acceleration Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. - -► You may now set your :ref:`Server Picker<server_picker_cli_reference>` more easily using keyword arguments. - ► We enhanced our :ref:`Saved Query<saved_queries>` permissions, ensuring that your saved queries are accessible and can be executed and reviewed exclusively by authorized users. -► Our :ref:`Pysqream<sqlalchemy>` connector now support SQLAlchemy version 2.0.27. - ► For any new SQreamDB installation or upgrade, your default :ref:`legacy configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` will include the following cluster flags: .. code-block:: json @@ -74,6 +62,10 @@ New Features and Enhancements } +► Sign into SQreamDB Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication. + +► Our :ref:`Pysqream<sqlalchemy>` connector now support SQLAlchemy version 2.0.27. + Known Issues ------------ @@ -89,12 +81,8 @@ Version 4.6 resolved Issues +--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-12873 | Improved the time it takes to delete metadata keys | +--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-12965 | Fixed ``ReadParquet`` chunk producer output | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-13057 | Fixed ``DOUBLE`` casting into ``TEXT`` issue | +--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-15828 | Fixed slow query runtime due to ``VIEW`` unexpected behavior | +--------------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16397 | Fixed database tree UI rendering issue | @@ -104,9 +92,6 @@ Version 4.6 resolved Issues | SQ-16592 | Fixed a discrepancy issue following ``OR`` condition execution | +--------------------+---------------------------------------------------------------------------------------------------------------------+ - - - Deprecations ------------ @@ -118,8 +103,6 @@ Starting February 2025, support for the Haskell CLI will be discontinued, and it CentOS Linux 7.x has reached its end of life and is not supported by SQreamDB. - - Upgrading to Version 4.6 ------------------------- From a4e3c2a84ba01329334bdd292898b183dab8d9e0 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 09:50:34 +0300 Subject: [PATCH 1516/1892] Update 4.7.rst --- releases/4.7.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index f3dd3e502..627f99b46 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -24,11 +24,11 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 3.0.2 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | | | * Pysqream 5.0.0 | | | * Spark 5.0.0 | -| | * SQLoader 7.12 (compatible with v4.6.1 or later) | +| | * SQLoader 8.0 (compatible with v4.6.1 or later) | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 0165dc96042b1a773c77c3d7728e31a5368e75a3 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 10:05:03 +0300 Subject: [PATCH 1517/1892] Update 4.7.rst --- releases/4.7.rst | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 627f99b46..be8f8816a 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -39,23 +39,10 @@ New Features and Enhancements .. note:: The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file - -► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. - - -► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. - -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. - -► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. - -► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + -► :ref:`health_monitoring` - -► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. ► Multi-platform CLI @@ -95,9 +82,23 @@ New Features and Enhancements "DefaultPathToLogs": "<home/logs/my_logs>" } +► :ref:`health_monitoring` + +► ALL log files should reside under the same folder +► Release locks +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + +► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + +► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. Known Issues ------------ From 2aa31aa3e6ebdc3ff9272723d7024036531cff7d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:00:45 +0300 Subject: [PATCH 1518/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index d424c3d7e..17f1b79ea 100644 --- a/conf.py +++ b/conf.py @@ -40,7 +40,7 @@ # ones. extensions = [ 'sphinx_rtd_theme' - ,'notfound.extension' # 404 handling + #"notfound.extension", # 404 handling ,"sphinx_favicon" ] From 684dc639c496e18f75880be094a4258fca6c0cf5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 31 Jul 2024 15:20:53 +0300 Subject: [PATCH 1519/1892] 404 --- 404.rst | 14 -------------- _static/css/custom.css | 5 ----- conf.py | 4 ++-- 3 files changed, 2 insertions(+), 21 deletions(-) delete mode 100644 404.rst diff --git a/404.rst b/404.rst deleted file mode 100644 index 44f92acfd..000000000 --- a/404.rst +++ /dev/null @@ -1,14 +0,0 @@ -:orphan: - -************************** -Page Cannot Be Found - 404 -************************** - -Use the **Search docs** bar, or use the navigation sidebar to find what you're looking for. - -.. rubric:: Need help? - -If you couldn't find what you're looking for, we're always happy to help. - -Visit the `SQreamDB support portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional help. - diff --git a/_static/css/custom.css b/_static/css/custom.css index 87535c4fe..399293607 100644 --- a/_static/css/custom.css +++ b/_static/css/custom.css @@ -58,8 +58,3 @@ div.rst-versions > div.rst-other-versions > div.injected > dl:nth-child(4) { } } - -.container.bottom-right { - display: none !important; - -} \ No newline at end of file diff --git a/conf.py b/conf.py index 17f1b79ea..fcb830cf0 100644 --- a/conf.py +++ b/conf.py @@ -39,8 +39,8 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx_rtd_theme' - #"notfound.extension", # 404 handling + "sphinx_rtd_theme" + "notfound.extension", # 404 handling ,"sphinx_favicon" ] From 27e50e7a4008cd3a9674631a24349ee9956b580a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Aug 2024 07:52:44 +0300 Subject: [PATCH 1520/1892] Update conf.py --- conf.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/conf.py b/conf.py index fcb830cf0..07ba7b3c6 100644 --- a/conf.py +++ b/conf.py @@ -40,7 +40,7 @@ # ones. extensions = [ "sphinx_rtd_theme" - "notfound.extension", # 404 handling + #"notfound.extension", # 404 handling ,"sphinx_favicon" ] @@ -70,10 +70,6 @@ # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] - - - - html_css_files = [ 'css/custom.css', # Relative to the _static path ] From 4104ea4652bb0b3d46334d2314183850c8ae6403 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 1 Aug 2024 09:39:36 +0300 Subject: [PATCH 1521/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index ba9b66627..0b22a28a7 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -536,7 +536,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``loadTypeName`` - Optional - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc``, and ``inc`` are supported only for Oracle + - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc`` is supported for Oracle only and that ``inc`` is supported for Oracle and Postgresql * - ``lockCheck`` - Optional - ``true`` @@ -628,7 +628,7 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only * - Incremental - ``inc`` - - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle only + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle and Postgresql From 8a035f444b5737d3db0d6fcff2f8b39404f91fc2 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:22:47 +0300 Subject: [PATCH 1522/1892] Update sqream_sql.rst --- reference/cli/sqream_sql.rst | 103 ++++++++++++++++------------------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index fd96eef2b..23ba59255 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -1,61 +1,34 @@ .. _sqream_sql_cli_reference: -************************ -Sqream SQL CLI Reference -************************ +************** +Sqream SQL CLI +************** -SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. +SQreamDB SQL Java-based CLI allows SQL statements to be executed interactively or using shell scripts. This CLI is cross-platform, meaning it can be executed on any operating system which Java supports. If you are not using Bash to manage and run your Java applications, please use the ``java -jar`` command to run this CLI. -This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. +.. note:: + For the old version of the SQream SQL (Haskell-based) CLI, see :ref:`Haskell CLI documentation<sqream_sql_haskell_cli>` -.. contents:: In this topic: +.. contents:: :local: + :depth: 1 -Installing Sqream SQL -===================== +Before You Begin +================ -If you have a SQreamDB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQreamDB installation, under the name ``sqream``. +It is essential that you have the following installed: +* `SQreamDB Java CLI <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ +* Java 8 +It is essential you have the Java home path configured in your ``sqream`` file: -.. versionchanged:: 2020.1 - As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. - - -To run ``sqream sql`` on any other Linux host: - -#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. -#. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` -#. Start the client: - - .. code-block:: psql - - $ cd sqream-sql-v2020.1.1_stable.x86_64 - $ ./sqream sql --port=5000 --username=jdoe --databasename=master - Password: - - Interactive client mode - To quit, use ^D or \q. - - master=> _ - -Troubleshooting Sqream SQL Installation ---------------------------------------- - -Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. +.. code-block:: none -Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. - -* RHEL: - - #. Install ``ncurses``: - - ``$ sudo yum install -y ncurses-libs`` - #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. - - For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: - - ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` + if [[ "$@" =~ "access-token" ]]; then + JAVA_CMD="/usr/lib/jvm/jdk-8.0.0/bin/java" + else + JAVA_CMD="/usr/lib/jvm/java-1.8.0/bin/java" Using SQreamDB SQL ================== @@ -349,19 +322,19 @@ Command Line Arguments - Description * - ``-c`` or ``--command`` - None - - Changes the mode of operation to single-command, non-interactive. Use this argument to run a statement and immediately exit. + - Changes the mode of operation to single-command, non-interactive. Use this argument to run a statement and immediately exit * - ``-f`` or ``--file`` - None - - Changes the mode of operation to multi-command, non-interactive. Use this argument to run a sequence of statements from an external file and immediately exit. - * - ``--host`` + - Changes the mode of operation to multi-command, non-interactive. Use this argument to run a sequence of statements from an external file and immediately exit + * - ``-h``, or``--host`` - ``127.0.0.1`` - - Address of the SQreamDB worker. - * - ``--port`` + - Address of the SQreamDB worker + * - ``-p`` or ``--port`` - ``5000`` - Sets the connection port. - * - ``--databasename`` or ``-d`` + * - ``--databasename``, ``-d``, or ``database`` - None - - Specifies the database name for queries and statements in this session. + - Specifies the database name for queries and statements in this session * - ``--username`` - None - Username to connect to the specified database. @@ -370,10 +343,10 @@ Command Line Arguments - Specify the password using the command line argument. If not specified, the client will prompt the user for the password. * - ``--clustered`` - False - - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQreamDB worker. - * - ``--service`` + - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQreamDB worker + * - ``-s`` or ``--service`` - ``sqream`` - - :ref:`Service name (queue)<workload_manager>` that statements will file into. + - :ref:`Service name (queue)<workload_manager>` that statements will file into * - ``--results-only`` - False - Outputs results only, without timing information and row counts @@ -382,7 +355,23 @@ Command Line Arguments - When set, prevents command history from being saved in ``~/.sqream/clientcmdhist`` * - ``--delimiter`` - ``,`` - - Specifies the field separator. By default, ``sqream sql`` outputs valid CSVs. Change the delimiter to modify the output to another delimited format (e.g. TSV, PSV). See the section :ref:`supported record delimiters<supported_record_delimiters>` below for more information. + - Specifies the field separator. By default, ``sqream sql`` outputs valid CSVs. Change the delimiter to modify the output to another delimited format (e.g. TSV, PSV). See the section :ref:`supported record delimiters<supported_record_delimiters>` below for more information + * - ``--chunksize`` + - 128 * 1024 (128 Kb) + - Network chunk size + * - ``--log`` or ``log-file`` + - False + - A log file will be created + * - ``--show-results`` + - True + - Determines whether or not results are shown + * - ``--ssl`` + - False + - Determines connection SSL + * - ``--table-view`` + - ``true`` + - Displays query results in a table view format with column headers. The display limit is set to 10,000 rows + .. tip:: Run ``$ sqream sql --help`` to see a full list of arguments From 5e7bb81e2dd27670b416a508bb5434c8cf655aab Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 4 Aug 2024 14:23:58 +0300 Subject: [PATCH 1523/1892] Haskell CLI Page --- .DS_Store | Bin 10244 -> 10244 bytes reference/cli/sqream_sql_haskell_cli.rst | 523 +++++++++++++++++++++++ 2 files changed, 523 insertions(+) create mode 100644 reference/cli/sqream_sql_haskell_cli.rst diff --git a/.DS_Store b/.DS_Store index 97d287aef654675e2bec8917779a214612247478..9bbcbcac4c0ec3d73d537815167a51d2e28dbfbc 100644 GIT binary patch delta 52 zcmZn(XbG6$&o9luz`)4BAi%&-!jQ?3yfJPqKcn<!D*++i%{S!q88<fUV%*HG@QY=$ Iz9=&@08fhzpa1{> delta 460 zcmZn(XbG6$&#%J3z`)4BAi%&-#8AvovN3KgKQ~B>oxy~`fWc&Pzoa;CH;}LQ9}E~6 zHuDGw@zyf~6&Et(c;@6MC*|ZP0TlpEV3Y-7KA1wF7#GM$hD0FF1hX<3k{OE8^Z*Sf ztS2YkFgQ6sw*Y7+7}NtvtcK_2ySP9d#PPCm#qC?4k2>O3n?khOf(#S~fb3@w1N*6z zAqD8We1>?293YtvWak0drVM%v#z1TY#05Z+bTnW8MDsO2(5y<JI#6g;0QKhq&4Pto bK0_X=Zl?6j{IYh8o7ok9v24C9!psZ+;|g>G diff --git a/reference/cli/sqream_sql_haskell_cli.rst b/reference/cli/sqream_sql_haskell_cli.rst new file mode 100644 index 000000000..c4264c58a --- /dev/null +++ b/reference/cli/sqream_sql_haskell_cli.rst @@ -0,0 +1,523 @@ +:orphan: + +.. _sqream_sql_haskell_cli: + +************************ +Sqream SQL Haskell CLI +************************ + +SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. + +This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. + +.. contents:: + :local: + :depth: 1 + +Installing Sqream SQL +===================== + +If you have a SQreamDB installation on your server, ``sqream sql`` can be found in the ``bin`` directory of your SQreamDB installation, under the name ``sqream``. + + + +.. versionchanged:: 2020.1 + As of version 2020.1, ``ClientCmd`` has been renamed to ``sqream sql``. + + +To run ``sqream sql`` on any other Linux host: + +#. Download the ``sqream sql`` tarball package from the :ref:`client_drivers` page. +#. Untar the package: ``tar xf sqream-sql-v2020.1.1_stable.x86_64.tar.gz`` +#. Start the client: + + .. code-block:: psql + + $ cd sqream-sql-v2020.1.1_stable.x86_64 + $ ./sqream sql --port=5000 --username=jdoe --databasename=master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +Troubleshooting Sqream SQL Installation +--------------------------------------- + +Upon running sqream sql for the first time, you may get an error ``error while loading shared libraries: libtinfo.so.5: cannot open shared object file: No such file or directory``. + +Solving this error requires installing the ncruses or libtinfo libraries, depending on your operating system. + +* RHEL: + + #. Install ``ncurses``: + + ``$ sudo yum install -y ncurses-libs`` + #. Depending on your RHEL version, you may need to create a symbolic link to the newer libtinfo that was installed. + + For example, if ``libtinfo`` was installed as ``/usr/lib64/libtinfo.so.6``: + + ``$ sudo ln -s /usr/lib64/libtinfo.so.6 /usr/lib64/libtinfo.so.5`` + +Using SQreamDB SQL +================== + +By default, sqream sql runs in interactive mode. You can issue commands or SQL statements. + +Running Commands Interactively (SQL shell) +------------------------------------------ + +When starting sqream sql, after entering your password, you are presented with the SQL shell. + +To exit the shell, type ``\q`` or :kbd:`Ctrl-d`. + +.. code-block:: psql + + $ sqream sql --port=5000 --username=jdoe --databasename=master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> _ + +The database name shown means you are now ready to run statements and queries. + +Statements and queries are standard SQL, followed by a semicolon (``;``). Statement results are usually formatted as a valid CSV, +followed by the number of rows and the elapsed time for that statement. + +.. code-block:: psql + + master=> SELECT TOP 5 * FROM nba; + Avery Bradley ,Boston Celtics ,0,PG,25,6-2 ,180,Texas ,7730337 + Jae Crowder ,Boston Celtics ,99,SF,25,6-6 ,235,Marquette ,6796117 + John Holland ,Boston Celtics ,30,SG,27,6-5 ,205,Boston University ,\N + R.J. Hunter ,Boston Celtics ,28,SG,22,6-5 ,185,Georgia State ,1148640 + Jonas Jerebko ,Boston Celtics ,8,PF,29,6-10,231,\N,5000000 + 5 rows + time: 0.001185s + +.. note:: Null values are represented as \\N. + +When writing long statements and queries, it may be beneficial to use line-breaks. +The prompt for a multi-line statement will change from ``=>`` to ``.``, to alert users to the change. The statement will not execute until a semicolon is used. + + +.. code-block:: psql + :emphasize-lines: 13 + + $ sqream sql --port=5000 --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> SELECT "Age", + . AVG("Salary") + . FROM NBA + . GROUP BY 1 + . ORDER BY 2 ASC + . LIMIT 5 + . ; + 38,1840041 + 19,1930440 + 23,2034746 + 21,2067379 + 36,2238119 + 5 rows + time: 0.009320s + + +Executing Batch Scripts (``-f``) +-------------------------------- + +To run an SQL script, use the ``-f <filename>`` argument. + +For example, + +.. code-block:: console + + $ sqream sql --port=5000 --username=jdoe -d master -f sql_script.sql --results-only + +.. tip:: Output can be saved to a file by using redirection (``>``). + +Executing Commands Immediately (``-c``) +--------------------------------------- + +To run a statement from the console, use the ``-c <statement>`` argument. + +For example, + +.. code-block:: console + + $ sqream sql --port=5000 --username=jdoe -d nba -c "SELECT TOP 5 * FROM nba" + Avery Bradley ,Boston Celtics ,0,PG,25,6-2 ,180,Texas ,7730337 + Jae Crowder ,Boston Celtics ,99,SF,25,6-6 ,235,Marquette ,6796117 + John Holland ,Boston Celtics ,30,SG,27,6-5 ,205,Boston University ,\N + R.J. Hunter ,Boston Celtics ,28,SG,22,6-5 ,185,Georgia State ,1148640 + Jonas Jerebko ,Boston Celtics ,8,PF,29,6-10,231,\N,5000000 + 5 rows + time: 0.202618s + +.. tip:: Remove the timing and row count by passing the ``--results-only`` parameter + + +Examples +======== + +Starting a Regular Interactive Shell +------------------------------------ + +Connect to local server 127.0.0.1 on port 5000, to the default built-in database, `master`: + +.. code-block:: psql + + $ sqream sql --port=5000 --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + +Connect to local server 127.0.0.1 via the built-in load balancer on port 3108, to the default built-in database, `master`: + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=mjordan -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + +Executing Statements in an Interactive Shell +-------------------------------------------- + +Note that all SQL commands end with a semicolon. + +Creating a new database and switching over to it without reconnecting: + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=oldmcd -d master + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=> create database farm; + executed + time: 0.003811s + master=> \c farm + farm=> + +.. code-block:: psql + + farm=> create table animals(id int not null, name text(30) not null, is_angry bool not null); + executed + time: 0.011940s + + farm=> insert into animals values(1,'goat',false); + executed + time: 0.000405s + + farm=> insert into animals values(4,'bull',true) ; + executed + time: 0.049338s + + farm=> select * from animals; + 1,goat ,0 + 4,bull ,1 + 2 rows + time: 0.029299s + +Executing SQL Statements from the Command Line +---------------------------------------------- + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals WHERE is_angry = true" + 4,bull ,1 + 1 row + time: 0.095941s + +.. _controlling_output: + +Controlling the Client Output +----------------------------- + +Two parameters control the dispay of results from the client: + +* ``--results-only`` - removes row counts and timing information +* ``--delimiter`` - changes the record delimiter + +Exporting SQL Query Results to CSV +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using the ``--results-only`` flag removes the row counts and timing. + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals" --results-only > file.csv + $ cat file.csv + 1,goat ,0 + 2,sow ,0 + 3,chicken ,0 + 4,bull ,1 + +Changing a CSV to a TSV +^^^^^^^^^^^^^^^^^^^^^^^ + +The ``--delimiter`` parameter accepts any printable character. + +.. tip:: To insert a tab, use :kbd:`Ctrl-V` followed by :kbd:`Tab ↹` in Bash. + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -c "SELECT * FROM animals" --delimiter ' ' > file.tsv + $ cat file.tsv + 1 goat 0 + 2 sow 0 + 3 chicken 0 + 4 bull 1 + + +Executing a Series of Statements From a File +-------------------------------------------- + +Assuming a file containing SQL statements (separated by semicolons): + +.. code-block:: console + + $ cat some_queries.sql + CREATE TABLE calm_farm_animals + ( id INT IDENTITY(0, 1), name TEXT(30) + ); + + INSERT INTO calm_farm_animals (name) + SELECT name FROM animals WHERE is_angry = false; + +.. code-block:: console + + $ sqream sql --port=3105 --clustered --username=oldmcd -d farm -f some_queries.sql + executed + time: 0.018289s + executed + time: 0.090697s + +Connecting Using Environment Variables +-------------------------------------- + +You can save connection parameters as environment variables: + +.. code-block:: console + + $ export SQREAM_USER=sqream; + $ export SQREAM_DATABASE=farm; + $ sqream sql --port=3105 --clustered --username=$SQREAM_USER -d $SQREAM_DATABASE + +Connecting to a Specific Queue +------------------------------ + +When using the :ref:`dynamic workload manager<workload_manager>` - connect to ``etl`` queue instead of using the default ``sqream`` queue. + +.. code-block:: psql + + $ sqream sql --port=3105 --clustered --username=mjordan -d master --service=etl + Password: + + Interactive client mode + To quit, use ^D or \q. + + master=>_ + + +Operations and Flag References +============================== + +Command Line Arguments +---------------------- + +**Sqream SQL** supports the following command line arguments: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Argument + - Default + - Description + * - ``-c`` or ``--command`` + - None + - Changes the mode of operation to single-command, non-interactive. Use this argument to run a statement and immediately exit + * - ``-f`` or ``--file`` + - None + - Changes the mode of operation to multi-command, non-interactive. Use this argument to run a sequence of statements from an external file and immediately exit + * - ``-h``, or``--host`` + - ``127.0.0.1`` + - Address of the SQreamDB worker + * - ``-p`` or ``--port`` + - ``5000`` + - Sets the connection port. + * - ``--databasename``, ``-d``, or ``database`` + - None + - Specifies the database name for queries and statements in this session + * - ``--username`` + - None + - Username to connect to the specified database. + * - ``--password`` + - None + - Specify the password using the command line argument. If not specified, the client will prompt the user for the password + * - ``--clustered`` + - False + - When used, the client connects to the load balancer, usually on port ``3108``. If not set, the client assumes the connection is to a standalone SQreamDB worker + * - ``-s`` or ``--service`` + - ``sqream`` + - :ref:`Service name (queue)<workload_manager>` that statements will file into + * - ``--results-only`` + - False + - Outputs results only, without timing information and row counts + * - ``--no-history`` + - False + - When set, prevents command history from being saved in ``~/.sqream/clientcmdhist`` + * - ``--delimiter`` + - ``,`` + - Specifies the field separator. By default, ``sqream sql`` outputs valid CSVs. Change the delimiter to modify the output to another delimited format (e.g. TSV, PSV). See the section :ref:`supported record delimiters<supported_record_delimiters>` below for more information + * - ``--chunksize`` + - 128 * 1024 (128 Kb) + - Network chunk size + * - ``--log`` or ``log-file`` + - False + - A log file will be created + * - ``--show-results`` + - True + - Determines whether or not results are shown + * - ``--ssl`` + - False + - Determines connection SSL + * - ``--table-view`` + - ``true`` + - Displays query results in a table view format with column headers. The display limit is set to 10,000 rows + + +.. tip:: Run ``$ sqream sql --help`` to see a full list of arguments + +.. _supported_record_delimiters: + +Supported Record Delimiters +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The supported record delimiters are printable ASCII values (32-126). + +* Recommended delimiters for use are: ``,``, ``|``, tab character. + +* The following characters are **not supported**: ``\``, ``N``, ``-``, ``:``, ``"``, ``\n``, ``\r``, ``.``, lower-case latin letters, digits (0-9) + +Meta-Commands +------------- + +* Meta-commands in Sqream SQL start with a backslash (``\``) + +.. note:: Meta commands do not end with a semicolon + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Command + - Example + - Description + * - ``\q`` or ``\quit`` + - .. code-block:: psql + + master=> \q + - Quit the client. (Same as :kbd:`Ctrl-d`) + * - ``\c <database>`` or ``\connect <database>`` + - .. code-block:: psql + + master=> \c fox + fox=> + - Changes the current connection to an alternate database + +Basic Commands +-------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-l` + - Clear the screen. + * - :kbd:`Ctrl-c` + - Terminate the current command. + * - :kbd:`Ctrl-z` + - Suspend/stop the command. + * - :kbd:`Ctrl-d` + - Quit SQream SQL + + + +Moving Around the Command Line +------------------------------ + +.. list-table:: + :widths: 17 83 + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-a` + - Goes to the beginning of the command line. + * - :kbd:`Ctrl-e` + - Goes to the end of the command line. + * - :kbd:`Ctrl-u` + - Deletes from cursor to the beginning of the command line. + * - :kbd:`Ctrl-k` + - Deletes from the cursor to the end of the command line. + * - :kbd:`Ctrl-w` + - Delete from cursor to beginning of a word. + * - :kbd:`Ctrl-y` + - Pastes a word or text that was cut using one of the deletion shortcuts (such as the one above) after the cursor. + * - :kbd:`Alt-b` + - Moves back one word (or goes to the beginning of the word where the cursor is). + * - :kbd:`Alt-f` + - Moves forward one word (or goes to the end of word the cursor is). + * - :kbd:`Alt-d` + - Deletes to the end of a word starting at the cursor. Deletes the whole word if the cursor is at the beginning of that word. + * - :kbd:`Alt-c` + - Capitalizes letters in a word starting at the cursor. Capitalizes the whole word if the cursor is at the beginning of that word. + * - :kbd:`Alt-u` + - Capitalizes from the cursor to the end of the word. + * - :kbd:`Alt-l` + - Makes lowercase from the cursor to the end of the word. + * - :kbd:`Ctrl-f` + - Moves forward one character. + * - :kbd:`Ctrl-b` + - Moves backward one character. + * - :kbd:`Ctrl-h` + - Deletes characters located before the cursor. + * - :kbd:`Ctrl-t` + - Swaps a character at the cursor with the previous character. + +Searching +--------- + +.. list-table:: + :widths: 17 83 + :header-rows: 1 + + * - Command + - Description + * - :kbd:`Ctrl-r` + - Searches the history backward. + * - :kbd:`Ctrl-g` + - Escapes from history-searching mode. + * - :kbd:`Ctrl-p` + - Searches the previous command in history. + * - :kbd:`Ctrl-n` + - Searches the next command in history. \ No newline at end of file From a5544df93158be95456afc6da7d978a7463dae63 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 6 Aug 2024 15:09:10 +0300 Subject: [PATCH 1524/1892] sphinx-notfound-page>=1.0.4 --- conf.py | 6 +++--- requirements.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/conf.py b/conf.py index 07ba7b3c6..2263f8bbd 100644 --- a/conf.py +++ b/conf.py @@ -39,9 +39,9 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - "sphinx_rtd_theme" - #"notfound.extension", # 404 handling - ,"sphinx_favicon" + "sphinx_rtd_theme", + "notfound.extension", # 404 handling + "sphinx_favicon" ] # Mark 'index' as the main page diff --git a/requirements.txt b/requirements.txt index cdf56e782..9a5b53fe3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,7 +5,7 @@ sphinx==7.2.6 sphinx-rtd-theme>=2.1.0rc1 urllib3<=2.0.0 openssl-python>=0.1.1 -sphinx-notfound-page +sphinx-notfound-page>=1.0.4 Pygments>=2.4.0 sphinx-favicon>=1.0.1 pdftex From 272818501b2118ee878c8442fde578379f6c8697 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:06:19 +0300 Subject: [PATCH 1525/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index 92a5d6fd1..1440b58c0 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -10,11 +10,6 @@ This guide is designed to assist those who wish to migrate their database system :local: :depth: 2 -Before You Begin -================ - - - Using SQream Commands, Statements, and UDFs =========================================== From e03dd23c23c3118e5600ea3e542aee88f6b059c6 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:19:07 +0300 Subject: [PATCH 1526/1892] Update conf.py --- conf.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conf.py b/conf.py index 2263f8bbd..186ad7575 100644 --- a/conf.py +++ b/conf.py @@ -22,6 +22,7 @@ html_context["READTHEDOCS"] = True import sphinx_rtd_theme +html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] # -- Project information ----------------------------------------------------- From ad09a52fdc72752a210b05853d769a761966cd39 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 08:25:25 +0300 Subject: [PATCH 1527/1892] Create 404.rst --- 404.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 404.rst diff --git a/404.rst b/404.rst new file mode 100644 index 000000000..44f92acfd --- /dev/null +++ b/404.rst @@ -0,0 +1,14 @@ +:orphan: + +************************** +Page Cannot Be Found - 404 +************************** + +Use the **Search docs** bar, or use the navigation sidebar to find what you're looking for. + +.. rubric:: Need help? + +If you couldn't find what you're looking for, we're always happy to help. + +Visit the `SQreamDB support portal <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ for additional help. + From af6637793fc6cb2e19f188db0bf7b518800b7357 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 09:28:56 +0300 Subject: [PATCH 1528/1892] 4.6 RN --- reference/cli/sqream_sql.rst | 22 +++++++++++++--------- releases/4.6.rst | 12 +++++++----- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index 23ba59255..baf80e208 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -16,19 +16,23 @@ SQreamDB SQL Java-based CLI allows SQL statements to be executed interactively o Before You Begin ================ -It is essential that you have the following installed: +* It is essential that you have the following installed: -* `SQreamDB Java CLI <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ -* Java 8 + * `SQreamDB Java CLI <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ + * Java 8 -It is essential you have the Java home path configured in your ``sqream`` file: +* It is essential you have the Java home path configured in your ``sqream`` file: -.. code-block:: none + #. Open the ``sqream`` file using any text editor. - if [[ "$@" =~ "access-token" ]]; then - JAVA_CMD="/usr/lib/jvm/jdk-8.0.0/bin/java" - else - JAVA_CMD="/usr/lib/jvm/java-1.8.0/bin/java" + #. Set the default path ``/usr/lib/jvm/jdk-8.0.0/bin/java`` to the local Java 8 path on your machine: + + .. code-block:: none + + if [[ "$@" =~ "access-token" ]]; then + JAVA_CMD="/usr/lib/jvm/jdk-8.0.0/bin/java" + else + JAVA_CMD="/usr/lib/jvm/java-1.8.0/bin/java" Using SQreamDB SQL ================== diff --git a/releases/4.6.rst b/releases/4.6.rst index 1cd9b4711..70fcc79a5 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -16,9 +16,9 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * RHEL - 7.x / 8.x | +| Supported OS | * RHEL - 8.x. | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4 | +| supported Nvidia driver | CUDA version 11.x | +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ @@ -34,9 +34,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► REHL 8.x is now officially supported. +► Announcing a new cross-platform :ref:`SQream SQL CLI<sqream_sql_cli_reference>` which is Java-based. This new CLI is fully compatible with the old and soon to be :ref:`deprecated Haskell CLI<deprecations>`. It also supports a neat looking result ``table view``. -► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. +► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. This means that you can now search by these attributes using your SQreamDB web interface. ► The ``TOP`` clause can now take a **subtraction** arithmetic operator when used in a :ref:`select` statement. @@ -92,12 +92,14 @@ Version 4.6 resolved Issues | SQ-16592 | Fixed a discrepancy issue following ``OR`` condition execution | +--------------------+---------------------------------------------------------------------------------------------------------------------+ +.. _deprecations: + Deprecations ------------ ► **Haskell CLI** -Starting February 2025, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. +Starting February 2025, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB. ► **CentOS Linux 7.x** From b819107a46916904da8bcd53218ca959182575e9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:28:38 +0300 Subject: [PATCH 1529/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 37956db3e..cc2b3579d 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -27,7 +27,7 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CONNECT`` | Connect to the database | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | Create schemas in the database | +| ``CREATE`` | Create and drop schemas in the database (the schema must be empty for ``DROP`` operation to succeed | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATEFUNCTION`` | Create and drop functions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ From 6e8889a06161071505c0ba5e6f4be6354708570b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 11:38:35 +0300 Subject: [PATCH 1530/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index cc2b3579d..c0e0b9d4f 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -27,7 +27,7 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CONNECT`` | Connect to the database | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``CREATE`` | Create and drop schemas in the database (the schema must be empty for ``DROP`` operation to succeed | +| ``CREATE`` | Create and drop schemas in the database (the schema must be empty for ``DROP`` operation to succeed) | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``CREATEFUNCTION`` | Create and drop functions | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ From b63e230d94033b5563194052f31a51c7ea053f3d Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 12:39:44 +0300 Subject: [PATCH 1531/1892] Update len.rst --- reference/sql/sql_functions/scalar_functions/string/len.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/len.rst b/reference/sql/sql_functions/scalar_functions/string/len.rst index 2dee61a61..276ad62be 100644 --- a/reference/sql/sql_functions/scalar_functions/string/len.rst +++ b/reference/sql/sql_functions/scalar_functions/string/len.rst @@ -18,7 +18,8 @@ Syntax .. code-block:: postgres - LEN( expr ) --> INT + LEN( expr ) + LENGTH( expr ) Arguments ============ From 8545a3df37d73e49afa677e096f55cab677dd380 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 7 Aug 2024 12:50:20 +0300 Subject: [PATCH 1532/1892] Maintenance --- data_ingestion/ingesting_from_databases.rst | 1 + data_ingestion/parquet.rst | 33 --------------------- data_ingestion/sqloader_as_a_service.rst | 4 +-- 3 files changed, 3 insertions(+), 35 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index 251255f76..a35d9257d 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -318,6 +318,7 @@ Please note that any customization done through the CLI will override configurat * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata Please note that ``cdc``, and ``inc`` are supported only for Oracle + * - ``-use_dbms_lob`` - Optional - ``true`` diff --git a/data_ingestion/parquet.rst b/data_ingestion/parquet.rst index 0fd82f923..fb51a49f4 100644 --- a/data_ingestion/parquet.rst +++ b/data_ingestion/parquet.rst @@ -32,50 +32,17 @@ Prepare your source Parquet files according to the requirements described in the :header-rows: 1 * - SQream Type → - - :: - Parquet Source ↓ - ``BOOL`` - - :: - - ``TINYINT`` - - :: - - ``SMALLINT`` - - :: - - ``INT`` - - :: - - ``BIGINT`` - - :: - - ``REAL`` - - :: - - ``DOUBLE`` - - :: - - ``TEXT`` [#f0]_ - - :: - - ``DATE`` - - :: - - ``DATETIME`` - - :: - * - ``BOOLEAN`` - Supported - diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 0b22a28a7..d4b878d23 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -43,7 +43,7 @@ Minimum Hardware Requirements * - RAM - 32GB -.. _sqloader_thread_sizing_guidelines: +.. _sqloader_thread_sizing_guideline: Sizing Guidelines ------------------ @@ -584,7 +584,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``threadCount`` - Optional - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guideline>` * - ``truncate`` - Optional - ``false`` From 780a094ff72136fa6dad7a3912b31a1583d040ff Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Aug 2024 08:02:19 +0300 Subject: [PATCH 1533/1892] pysqream 5.1.0 --- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.7.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 29d0c7f39..61ae7f3e4 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -49,7 +49,7 @@ Client Driver Downloads - - All * - **Python** - - `pysqream v5.0.0 <https://github.com/SQream/pysqream/releases/tag/v5.0.0>`_ + - `pysqream v5.1.0 <https://github.com/SQream/pysqream/releases>`_ - :ref:`pysqream` - Recommended installation via ``pip`` - All diff --git a/releases/4.7.rst b/releases/4.7.rst index be8f8816a..4c5b22743 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -26,7 +26,7 @@ Compatibility Matrix | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | -| | * Pysqream 5.0.0 | +| | * Pysqream 5.1.0 | | | * Spark 5.0.0 | | | * SQLoader 8.0 (compatible with v4.6.1 or later) | +-------------------------+------------------------------------------------------------------------+ From 10b3b3e6008d1afa8e7dca8d32f2bf8ca21f6d51 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 8 Aug 2024 16:17:24 +0300 Subject: [PATCH 1534/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index d4b878d23..986b223ee 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -64,7 +64,7 @@ Extract the ``.tar`` file using the following command: .. code-block:: bash - tar -xf sqloader_srv_v8.0.tar.gz + tar -xf sqloader_srv_v8.1.tar.gz A folder named ``sqloader`` with the following files is created: @@ -73,7 +73,7 @@ A folder named ``sqloader`` with the following files is created: ├── sqloader-v1.sh ├── bin │ ├── sqloader-admin-server-1.0.jar - │ └── sqloader-service-8.0.jar + │ └── sqloader-service-8.1.jar ├── config ├── reserved_words.txt ├── sqload-jdbc.properties @@ -91,7 +91,7 @@ A folder named ``sqloader`` with the following files is created: - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. - * - ``sqloader-service-8.0.jar`` + * - ``sqloader-service-8.1.jar`` - The SQLoader service JAR file * - ``sqloader-admin-server-1.0.jar`` - The SQLoader admin server JAR file @@ -121,32 +121,32 @@ All deployment flags are not dynamically adjustable at runtime. * - ``configDir`` - Optional - ``config`` - - ``java -jar sqloaderService-8.0.jar --configDir=</path/to/directory/>`` + - ``java -jar sqloaderService-8.1.jar --configDir=</path/to/directory/>`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file * - ``hzClusterName=<TEXT>`` - Optional - - - ``java -jar sqloader-service-8.0.jar --hzClusterName=<TEXT>`` + - ``java -jar sqloader-service-8.1.jar --hzClusterName=<TEXT>`` - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. * - ``LOG_DIR`` - Optional - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.0.jar`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.1.jar`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``spring.boot.admin.client.url`` - Optional - ``http://localhost:7070`` - - ``java -jar sqloader-service-8.0.jar --spring.boot.admin.client.url=http://IP:PORT`` + - ``java -jar sqloader-service-8.1.jar --spring.boot.admin.client.url=http://IP:PORT`` - SQLoader admin server connection flag * - ``Xmx`` - Optional - - - ``java -jar -Xmx<number>g sqloader-service-8.0.jar`` + - ``java -jar -Xmx<number>g sqloader-service-8.1.jar`` - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` * - ``DEFAULT_PROPERTIES`` - Mandatory - ``sqload-jdbc.properties`` - - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.0.jar`` + - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.1.jar`` - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. Installing the Admin Server and SQLoader Service @@ -252,7 +252,7 @@ Output: BINDIR=/usr/local/sqloader/bin LOG_DIR=/var/log/sqloader-service CONFDIR=/usr/local/sqloader/config - JAR=sqloader-service-8.0.jar + JAR=sqloader-service-8.1.jar PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties PORT=6060 ADMINIP=192.168.5.234 From 24b26932f0162e34543dcda865972865aa89c642 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 11 Aug 2024 12:51:15 +0300 Subject: [PATCH 1535/1892] Update preparing_your_machine_to_install_sqream.rst --- getting_started/preparing_your_machine_to_install_sqream.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index e3487c725..b11542b95 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -14,7 +14,7 @@ To prepare your machine to install SQreamDB, do the following: * Red Hat Enterprise Linux v7.x / v8.6 - 8.9 - * Amazon Linux 7 + * Amazon Linux 2 * Verify that you have the following: From d70c11d7626d421bc6f985bd0f3204d1c62437e4 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 11 Aug 2024 13:01:24 +0300 Subject: [PATCH 1536/1892] Update hardware_guide.rst --- getting_started/hardware_guide.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index c9d4fc1c5..3fb2b7a7a 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -62,9 +62,9 @@ An average single-node cluster can be a rackmount server or workstation, contain * - GPU - NVIDIA 2x A100, H100, or L40S - + * - Operating System - - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux + - Red Hat Enterprise Linux v8.9 or Amazon Linux 2 .. note:: If you are using internal storage, your volumes must be formatted as xfs. @@ -108,11 +108,11 @@ The following table shows SQreamDB's recommended hardware specifications: * - GPU - NVIDIA 2x A100, H100, or L40S * - Operating System - - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux - + - Red Hat Enterprise Linux v8.9 or Amazon Linux 2 + Metadata Server --------------- - + The following table shows SQreamDB's recommended metadata server specifications: .. list-table:: @@ -134,7 +134,7 @@ The following table shows SQreamDB's recommended metadata server specifications: * - Network Card (Client) - 2x 1 GbE cards or similar * - Operating System - - Red Hat Enterprise Linux v7.9 / v8.9 or Amazon Linux + - Red Hat Enterprise Linux v8.9 or Amazon Linux 2 .. note:: With a NAS connected over GPFS, Lustre, Weka, or VAST, each SQreamDB worker can read data at 5GB/s or more. @@ -158,7 +158,7 @@ The following table shows SQreamDB's recommended Studio server specifications: * - Onboard storage - 50 GB SSD 2.5in Hot-plug for OS, RAID1 * - Operating System - - Red Hat Enterprise Linux v7.9 / v8.9 or CentOS v7.9 + - Red Hat Enterprise Linux v8.9 Cluster Design Considerations ============================= @@ -231,8 +231,8 @@ Operating System SQreamDB can run on the following 64-bit Linux operating systems: - * Red Hat Enterprise Linux (RHEL) v7.9 / v8.9 - * Amazon Linux 2018.03 + * Red Hat Enterprise Linux v8.9 + * Amazon Linux 2 Storage @@ -241,4 +241,3 @@ Storage For clustered scale-out installations, SQreamDB relies on NAS storage. For stand-alone installations, SQreamDB relies on redundant disk configurations, such as RAID 5, 6, or 10. These RAID configurations replicate blocks of data between disks to avoid data loss or system unavailability. SQreamDB recommends using enterprise-grade SAS SSD or NVMe drives. For a 32-user configuration, the number of GPUs should roughly match the number of users. SQreamDB recommends 1 Tesla A100 / H100 or L40S GPU per 2 users, for full, uninterrupted dedicated access. - From 8dcfee5b3d0be451c4b89d6e7ff84bb022b71068 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 11 Aug 2024 14:46:48 +0300 Subject: [PATCH 1537/1892] Update ingesting_from_databases.rst --- data_ingestion/ingesting_from_databases.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst index a35d9257d..e631eac41 100644 --- a/data_ingestion/ingesting_from_databases.rst +++ b/data_ingestion/ingesting_from_databases.rst @@ -54,13 +54,13 @@ Getting the SQLoader Configuration and JAR Files .. code-block:: console - curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.12.tar + curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.13.tar 2. Extract the ``.tar`` file using the following command: .. code-block:: console - tar -xf sqloader-7.12.tar.gz + tar -xf sqloader-7.13.tar.gz A folder named ``sqloader`` with the following files is created: From 2bdb356aeddd75da568f70110db0ef6897b26b14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Aug 2024 15:31:52 +0300 Subject: [PATCH 1538/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index ddafd8d75..255c1c483 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -103,7 +103,7 @@ Installing via PIP without an internet connection #Install all packages with --no-index --find-links . python3 -m pip install *.whl -U --no-index --find-links . python3.9 -m pip install pysqream-5.0.0.zip -U --no-index --find-links . - python3.9 -m pip install pysqream-sqlalchemy-1.0.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-sqlalchemy-1.3.zip -U --no-index --find-links . Upgrading an Existing Installation ---------------------------------- @@ -121,6 +121,11 @@ SQLAlchemy SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the SQream dialect (``pysqream-sqlalchemy``) you can use frameworks such as Pandas, TensorFlow, and Alembic to query SQream directly. +Before You Begin +---------------- + +Download :ref:`pysqream-sqlalchemy<https://pypi.org/project/pysqream-sqlalchemy/1.3/>` + .. contents:: :local: :depth: 1 From d33125cb1955859b56b2700883a89396ceeb4a9f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:01:09 +0300 Subject: [PATCH 1539/1892] SQLoader --- data_ingestion/sqloader_as_a_service.rst | 16 +++++++++++----- releases/4.7.rst | 5 +++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 986b223ee..90c123b56 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -60,19 +60,25 @@ Installation and Connectivity Getting All Configuration and JAR Files --------------------------------------- -Extract the ``.tar`` file using the following command: +#. Download the SQLoader zip file: -.. code-block:: bash + .. code-block:: console + + https://storage.cloud.google.com/cicd-storage/sqloader_release/sqloader-release-v1.1.zip + +#. Extract the ``.tar`` file using the following command: + + .. code-block:: bash tar -xf sqloader_srv_v8.1.tar.gz -A folder named ``sqloader`` with the following files is created: + A folder named ``sqloader`` with the following files is created: -.. code-block:: + .. code-block:: ├── sqloader-v1.sh ├── bin - │ ├── sqloader-admin-server-1.0.jar + │ ├── sqloader-admin-server-1.1.jar │ └── sqloader-service-8.1.jar ├── config ├── reserved_words.txt diff --git a/releases/4.7.rst b/releases/4.7.rst index 4c5b22743..7bae6da79 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -26,9 +26,10 @@ Compatibility Matrix | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | -| | * Pysqream 5.1.0 | +| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | | | * Spark 5.0.0 | -| | * SQLoader 8.0 (compatible with v4.6.1 or later) | +| | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | +| | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From f125a06223065971a280665d59787d20a89f5de6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:14:12 +0300 Subject: [PATCH 1540/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 255c1c483..823362ea3 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -124,13 +124,9 @@ SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the Before You Begin ---------------- -Download :ref:`pysqream-sqlalchemy<https://pypi.org/project/pysqream-sqlalchemy/1.3/>` +Download `pysqream-sqlalchemy <https://pypi.org/project/pysqream-sqlalchemy/1.3/>`_ -.. contents:: - :local: - :depth: 1 - -Limitations +Limitation ----------- * Supports `Pysqream 3.2.5 <https://pypi.org/project/pysqream/3.2.5/>`_ From ce64cabd675aa20be6f68a58a65a548438bcbd94 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:26:29 +0300 Subject: [PATCH 1541/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 823362ea3..f5d1ac5e8 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -98,11 +98,11 @@ Installing via PIP without an internet connection .. code-block:: console - tar -xf pysqream_connector_5.0.0.tar.gz - cd pysqream_connector_5.0.0 + tar -xf pysqream_connector_5.1.0.tar.gz + cd pysqream_connector_5.1.0 #Install all packages with --no-index --find-links . python3 -m pip install *.whl -U --no-index --find-links . - python3.9 -m pip install pysqream-5.0.0.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-5.1.0.zip -U --no-index --find-links . python3.9 -m pip install pysqream-sqlalchemy-1.3.zip -U --no-index --find-links . Upgrading an Existing Installation From a2dc1d0747446d1f04a0a689366d866447c61535 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 12 Aug 2024 16:29:28 +0300 Subject: [PATCH 1542/1892] Maintenance --- releases/4.5.rst | 38 +++++++++++++++++++------------------- releases/4.6.rst | 6 +++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/releases/4.5.rst b/releases/4.5.rst index 753418b99..5110a77ae 100644 --- a/releases/4.5.rst +++ b/releases/4.5.rst @@ -13,25 +13,25 @@ The 4.5 release notes were released on December 5th, 2023 Compatibility Matrix -------------------- -+---------------------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=================================+========================================================================+ -| Supported OS | * CentOS 7.x | -| | * RHEL 7.x / 8.x | -+---------------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | -+---------------------------------+------------------------------------------------------------------------+ -| Storage version | 50 | -+---------------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.3.1 | -| | * ODBC 4.4.4 | -| | * NodeJS | -| | * .NET 5.0.0 | -| | * Pysqream 5.0.0 | -| | * Spark | -+---------------------------------+------------------------------------------------------------------------+ -| SQream Acceleration Studio | Version 5.7.0 | -+---------------------------------+------------------------------------------------------------------------+ ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | * CentOS 7.x | +| | * RHEL 7.x / 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 50 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.3.1 | +| | * ODBC 4.4.4 | +| | * NodeJS | +| | * .NET 5.0.0 | +| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | +| | * Spark 5.0.0 | +| | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | +| | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | ++-------------------------+------------------------------------------------------------------------+ New Features and Enhancements ----------------------------- diff --git a/releases/4.6.rst b/releases/4.6.rst index 70fcc79a5..cc9e1c486 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -25,10 +25,10 @@ Compatibility Matrix | Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | -| | * .NET 5.0.0 | -| | * Pysqream 5.0.0 | +| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | | | * Spark 5.0.0 | -| | * SQLoader 8.0 (compatible with v4.6.1 or later) | +| | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | +| | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From eebfab26b00d9822838c6b0483a705e1135045a5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Aug 2024 08:24:05 +0300 Subject: [PATCH 1543/1892] Removing RHEL7 and centOS --- .../client_drivers/odbc/index.rst | 8 +-- ...eparing_your_machine_to_install_sqream.rst | 4 +- .../pre-installation_configurations.rst | 62 +------------------ 3 files changed, 7 insertions(+), 67 deletions(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 6aefc4600..8a9ce77f8 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -12,7 +12,7 @@ ODBC install_configure_odbc_windows install_configure_odbc_linux -SQreamDB has an ODBC driver to connect to SQreamDB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. +SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to install the ODBC driver for Linux or Windows for use with applications like Tableau, PHP, and others that use ODBC. .. list-table:: :widths: auto @@ -31,15 +31,15 @@ SQreamDB has an ODBC driver to connect to SQreamDB. This tutorial shows how to i * Windows Server 2019 * - Linux - - * Red Hat Enterprise Linux (RHEL) 7/8 + - * Red Hat Enterprise Linux (RHEL) 8.9 -Other distributions may also work, but are not officially supported by SQreamDB. +Other distributions may also work, but are not officially supported by SQream. Getting the ODBC driver ======================= -The SQreamDB ODBC driver is distributed by your SQreamDB account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQreamDB Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQreamDB account manager to get the driver. +The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQream account manager to get the driver. The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: diff --git a/getting_started/preparing_your_machine_to_install_sqream.rst b/getting_started/preparing_your_machine_to_install_sqream.rst index b11542b95..01dc3560d 100644 --- a/getting_started/preparing_your_machine_to_install_sqream.rst +++ b/getting_started/preparing_your_machine_to_install_sqream.rst @@ -7,12 +7,10 @@ Preparing Your Machine to Install SQreamDB To prepare your machine to install SQreamDB, do the following: * Set up your local machine according to SQreamDB's recommended pre-installation configurations. - - :: * Verify you have an NVIDIA-capable server, either on-premise or on supported cloud platforms: - * Red Hat Enterprise Linux v7.x / v8.6 - 8.9 + * Red Hat Enterprise Linux v8.9 * Amazon Linux 2 diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 557b7d120..d60b77240 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -93,9 +93,9 @@ Before You Begin * Once the BIOS settings have been set, you must install the operating system. -* A typical SQreamDB installation requires RHEL7.9 or RHEL8.X (RHEL8.9 recommended) +* A typical SQreamDB installation requires RHEL8.9 -* Verify the exact RHEL7/RHEL8 version with your storage vendor to avoid driver incompatibility. +* Verify the exact RHEL8 version with your storage vendor to avoid driver incompatibility. Installation ---------------- @@ -212,20 +212,6 @@ Installing Required Software Installing EPEL Repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**CentOS7/RHEL8** - - .. code-block:: console - - sudo yum install epel-release - -**RHEL7** - - .. code-block:: console - - sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - -**RHEL8** - .. code-block:: console sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm @@ -235,14 +221,6 @@ Enabling Additional Red Hat Repositories Enabling additional Red Hat repositories is essential to install the required packages in the subsequent procedures. -**RHEL7** - - .. code-block:: console - - sudo subscription-manager repos --enable rhel-7-server-optional-rpms - -**RHEL8** - .. code-block:: console sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms @@ -252,14 +230,6 @@ Enabling additional Red Hat repositories is essential to install the required pa Installing Required Packages ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**RHEL7/CentOS7** - - .. code-block:: console - - sudo yum install ntp pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel gdbm-devel tk-devel xz-devel sqlite-devel readline-devel bzip2-devel ncurses-devel zlib-devel - -**RHEL8** - .. code-block:: console sudo dnf install chrony pciutils monit zlib-devel openssl-devel kernel-devel-$(uname -r) kernel-headers-$(uname -r) gcc net-tools wget jq libffi-devel xz-devel ncurses-compat-libs libnsl gdbm-devel tk-devel sqlite-devel readline-devel texinfo @@ -267,14 +237,6 @@ Installing Required Packages Installing Recommended Tools ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -**RHEL7/CentOS7** - - .. code-block:: console - - sudo yum install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils deltarpm dos2unix - -**RHEL8** - .. code-block:: console sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix @@ -821,14 +783,6 @@ Installing the CUDA driver from the Repository is the recommended installation m 1. Install the CUDA dependencies for one of the following operating systems: - * For RHEL7: - - .. code-block:: console - - sudo rpm -Uvh http://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm - - * For RHEL8: - .. code-block:: console sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm @@ -843,18 +797,6 @@ Installing the CUDA driver from the Repository is the recommended installation m 3. Download and install the required local repository: - * **CentOS7/RHEL7 CUDA 11.4.3 repository (INTEL) installation (Required for A-Series GPU models):** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/11.4.3/local_installers/cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - sudo yum localinstall cuda-repo-rhel7-11-4-local-11.4.3_470.82.01-1.x86_64.rpm - - .. code-block:: console - - sudo yum clean all - sudo yum -y install nvidia-driver-latest-dkms - * **RHEL8.9 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** From 9cf3383ca732382f8f366b75866f30e52585adf2 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 13 Aug 2024 09:17:52 +0300 Subject: [PATCH 1544/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index d60b77240..fe221e8bd 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -93,7 +93,7 @@ Before You Begin * Once the BIOS settings have been set, you must install the operating system. -* A typical SQreamDB installation requires RHEL8.9 +* A SQreamDB installation requires RHEL8.8/8.9 * Verify the exact RHEL8 version with your storage vendor to avoid driver incompatibility. @@ -798,7 +798,7 @@ Installing the CUDA driver from the Repository is the recommended installation m 3. Download and install the required local repository: - * **RHEL8.9 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** + * **RHEL8.8/8.9 CUDA 12.3.2 repository ( INTEL ) installation ( Required for H/L Series GPU models ):** .. code-block:: console From 439653c60d8579659a3cf9a78b644a0498160a60 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:30:40 +0300 Subject: [PATCH 1545/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index fe221e8bd..42ef4f51e 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -240,53 +240,6 @@ Installing Recommended Tools .. code-block:: console sudo dnf install bash-completion.noarch vim-enhanced vim-common net-tools iotop htop psmisc screen xfsprogs wget yum-utils dos2unix - -Installing Python -^^^^^^^^^^^^^^^^^^^ - -**For SQreamDb version 4.3 or older, install Python 3.6.7.** - -1. Download the Python 3.6.7 source code tarball file from the following URL into the ``/home/sqream`` directory: - - .. code-block:: console - - wget https://www.python.org/ftp/python/3.6.7/Python-3.6.7.tar.xz - -2. Extract the Python 3.6.7 source code into your current directory: - - .. code-block:: console - - tar -xf Python-3.6.7.tar.xz - -3. Navigate to the Python 3.6.7 directory: - - .. code-block:: console - - cd Python-3.6.7 - -4. Run the ``./configure`` script: - - .. code-block:: console - - ./configure --enable-loadable-sqlite-extensions - -5. Build the software: - - .. code-block:: console - - make -j30 - -6. Install the software: - - .. code-block:: console - - sudo make install - -7. Verify that Python 3.6.7 has been installed: - - .. code-block:: console - - python3 --version **For SQreamDB version 4.4 or newer, install Python 3.9.13.** From dacb3e810b512a336d3ad03c28655ff349469361 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:33:40 +0300 Subject: [PATCH 1546/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 73 ------------------- 1 file changed, 73 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 42ef4f51e..44e11f41b 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -385,79 +385,6 @@ NodeJS is necessary only when the UI runs on the same server as SqreamDB. If not .. code-block:: console node --version - -Configuring the Network Time Protocol --------------------------------------- - -This Network Time Protocol (NTP) configuration is intended for use on systems running RHEL7 and CentOS7 exclusively. - -If you don't have internet access, see `Configure NTP Client to Synchronize with NTP Server <https://www.thegeekstuff.com/2014/06/linux-ntp-server-client/>`__. - -1. Install the NTP file. - - .. code-block:: console - - sudo yum install ntp - -2. Enable the **ntpd** program. - - .. code-block:: console - - sudo systemctl enable ntpd - -3. Start the **ntdp** program. - - .. code-block:: console - - sudo systemctl start ntpd - -4. Print a list of peers known to the server and a summary of their states. - - .. code-block:: console - - sudo ntpq -p - -Configuring the Network Time Protocol Server --------------------------------------------- - -If your organization has a Network Time Protocol (NTP) server, configure it by adding records to ``/etc/ntpd.conf``, reloading the service, and checking that synchronization is enabled. - -1. Output your NTP server address and append ``/etc/ntpd.conf`` to the output: - - .. code-block:: console - - echo -e "\nserver <your NTP server address>\n" | sudo tee -a /etc/ntp.conf - -2. Restart the service: - - .. code-block:: console - - sudo systemctl restart ntpd - -3. Check that synchronization is enabled: - - .. code-block:: console - - sudo timedatectl - - Checking that synchronization is enabled generates the following output: - - .. code-block:: console - - Local time: Sat 2019-10-12 17:26:13 EDT - Universal time: Sat 2019-10-12 21:26:13 UTC - RTC time: Sat 2019-10-12 21:26:13 - Time zone: America/New_York (EDT, -0400) - NTP enabled: yes - NTP synchronized: yes - RTC in local TZ: no - DST active: yes - Last DST change: DST began at - Sun 2019-03-10 01:59:59 EST - Sun 2019-03-10 03:00:00 EDT - Next DST change: DST ends (the clock jumps one hour backwards) at - Sun 2019-11-03 01:59:59 EDT - Sun 2019-11-03 01:00:00 EST Configuring Chrony for RHEL8 Only ---------------------------------- From 9b0893d950b6242be90b3b6f77f843382d616f72 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 13:35:15 +0300 Subject: [PATCH 1547/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 44e11f41b..7f7d2a6d1 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -446,12 +446,6 @@ Configuring the Kernel Parameters sysctl -n fs.file-max -3. **Only** if the maximum value of the ``fs.file`` is smaller than ``2097152``, run the following command: - - .. code-block:: console - - echo "fs.file-max=2097152" >> /etc/sysctl.conf - Configuring the Firewall -------------------------- From 72c61f5cfb2391eef4d465a0b85c70ebe3a21f22 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:13:12 +0300 Subject: [PATCH 1548/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 7f7d2a6d1..e4afd7bee 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -683,17 +683,6 @@ Installing the CUDA driver from the Repository is the recommended installation m sudo dnf clean all sudo dnf -y module install nvidia-driver:latest-dkms - -Power9 with V100 GPUs supports only cuda 10.1 driver on RHEL7 - - * **IBM Power9 - CUDA 10.1 for RHEL7:** - - .. code-block:: console - - wget https://developer.download.nvidia.com/compute/cuda/10.1/Prod/local_installers/cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - sudo yum localinstall cuda-repo-rhel7-10-1-local-10.1.243-418.87.00-1.0-1.ppc64le.rpm - -If you are installing the CUDA driver on IBM Power9, please follow the `NVIDIA documentation <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`_ for additionally required steps. Tuning Up NVIDIA Performance ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -772,30 +761,12 @@ Tune Up NVIDIA Performance when Driver Installed from the Runfile nvidia-persistenced - * **For IBM (mandatory)**: - - .. code-block:: console - - sudo systemctl start nvidia-persistenced - sudo systemctl enable nvidia-persistenced - - * **For K80**: - - .. code-block:: console - - nvidia-persistenced - nvidia-smi -pm 1 - nvidia-smi -acp 0 - nvidia-smi --auto-boost-permission=0 - nvidia-smi --auto-boost-default=0 - 4. Reboot the server and run the ``NVIDIA System Management Interface (NVIDIA SMI)``: .. code-block:: console nvidia-smi - Enabling Core Dumps =================== From 7aeebbb2adab44452c9512eef627e0c1998a15a9 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:18:08 +0300 Subject: [PATCH 1549/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index e4afd7bee..ca45da54c 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -693,8 +693,6 @@ The following procedures exclusively relate to Intel. :local: :depth: 1 -.. note:: Setting up the NVIDIA POWER9 CUDA driver includes additional set-up requirements. The NVIDIA POWER9 CUDA driver will not function properly if the additional set-up requirements are not followed. See `POWER9 Setup <https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#power9-setup>`__ for the additional set-up requirements. - Tune Up NVIDIA Performance when Driver Installed from the Repository """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" From f53eac840284f6c6ef1c519edb38098ba93773e9 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 14 Aug 2024 14:21:41 +0300 Subject: [PATCH 1550/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index ca45da54c..030a9ab77 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -223,6 +223,7 @@ Enabling additional Red Hat repositories is essential to install the required pa .. code-block:: console + sudo subscription-manager release --set=8.9 sudo subscription-manager repos --enable codeready-builder-for-rhel-8-x86_64-rpms sudo subscription-manager repos --enable rhel-8-for-x86_64-appstream-rpms sudo subscription-manager repos --enable rhel-8-for-x86_64-baseos-rpms From c0d716e663fd2dba5bc57d407b90be3206892e16 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:09:42 +0300 Subject: [PATCH 1551/1892] Update executing_statements_and_running_queries_from_the_editor.rst --- ...tements_and_running_queries_from_the_editor.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index c57bd7d58..ea4fa824e 100644 --- a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -334,14 +334,14 @@ While Studio's default functionality is to open a new tab for each executed stat The following shows the syntax for running parallel statements: -.. code-block:: console +.. code-block:: mysql - $ @@ parallel - $ $$ - $ select 1; - $ select 2; - $ select 3; - $ $$ + @@ parallel + $$ + SELECT 1; + SELECT 2; + SELECT 3; + $$ From deb41d0af2bed237277ac21916e278cf2cf76d86 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 09:13:36 +0300 Subject: [PATCH 1552/1892] Update executing_statements_and_running_queries_from_the_editor.rst --- ...executing_statements_and_running_queries_from_the_editor.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index ea4fa824e..6bc2d8f90 100644 --- a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -334,7 +334,7 @@ While Studio's default functionality is to open a new tab for each executed stat The following shows the syntax for running parallel statements: -.. code-block:: mysql +.. code-block:: psql @@ parallel $$ From 0b7fd8a02bd4f8c1c4c04e07a5c2c833b661892b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 11:23:55 +0300 Subject: [PATCH 1553/1892] View Activity Report --- ...ts_and_running_queries_from_the_editor.rst | 2 +- sqream_studio/getting_started.rst | 20 ++++++++++++------- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst index 6bc2d8f90..895b05671 100644 --- a/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst +++ b/sqream_studio/executing_statements_and_running_queries_from_the_editor.rst @@ -334,7 +334,7 @@ While Studio's default functionality is to open a new tab for each executed stat The following shows the syntax for running parallel statements: -.. code-block:: psql +.. code-block:: cry @@ parallel $$ diff --git a/sqream_studio/getting_started.rst b/sqream_studio/getting_started.rst index 3ddf1a236..e5f1903c7 100644 --- a/sqream_studio/getting_started.rst +++ b/sqream_studio/getting_started.rst @@ -1,8 +1,8 @@ .. _getting_started: -****************************************************** +*********************************************** Getting Started with SQream Acceleration Studio -****************************************************** +*********************************************** Setting Up and Starting Studio ------------------------------ @@ -10,9 +10,7 @@ Setting Up and Starting Studio When starting Studio, it listens on the local machine on port 8080. Logging In to Studio ------------------------ - -**To log in to SQream Studio:** +-------------------- 1. Open a browser to the host on **port 8080**. @@ -29,7 +27,7 @@ Logging In to Studio .. _monitoring_workers_and_services_from_the_dashboard: Navigating Studio's Main Features ------------------------------------ +--------------------------------- When you log in, you are automatically taken to the **Editor** screen. The Studio's main functions are displayed in the **Navigation** pane on the left side of the screen. @@ -50,7 +48,7 @@ From here you can navigate between the main areas of the Studio: * - :ref:`Configuration<configuring_your_instance_of_sqream>` - Lets you configure your instance of SQream. -By clicking the user icon, you can also use it for logging out and viewing the following: +By clicking the user icon, you can view the following: * User information * Connection type @@ -58,4 +56,12 @@ By clicking the user icon, you can also use it for logging out and viewing the f * SQream Studio version * License expiration date * License storage capacity +* :ref:`Activity report<view_activity_report>` * Log out + +.. _view_activity_report: + +View Activity Report +-------------------- + +The **View activity report** menu item enables you to monitor storage and resource usage, including GPUs, workers, and machines. You can select different time frames to view cluster activity and export the data as a PDF for use in financial records, briefings, or quarterly and yearly reports. \ No newline at end of file From 230a7bfed7dd146149a49302173b8b565b81f47e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:08:42 +0300 Subject: [PATCH 1554/1892] Update pentaho.rst --- .../client_platforms/pentaho.rst | 51 ++----------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/connecting_to_sqream/client_platforms/pentaho.rst b/connecting_to_sqream/client_platforms/pentaho.rst index 64cd8f81b..89ae1e759 100644 --- a/connecting_to_sqream/client_platforms/pentaho.rst +++ b/connecting_to_sqream/client_platforms/pentaho.rst @@ -60,8 +60,6 @@ After installing Pentaho you can create a transformation. $ spoon.bat 2. Open the spoon.bat file from its folder location. - -:: 3. In the **View** tab, right-click **Transformations** and click **New**. @@ -69,48 +67,28 @@ After installing Pentaho you can create a transformation. 4. In the **Design** tab, click **Input** to show its file contents. -:: - 5. Drag and drop the **CSV file input** item to the new transformation tab that you created. -:: - 6. Double-click **CSV file input**. The **CSV file input** panel is displayed. -:: - 7. In the **Step name** field, type a name. -:: - 8. To the right of the **Filename** field, click **Browse**. -:: - 9. Select the file that you want to read from and click **OK**. -:: - 10. In the CSV file input window, click **Get Fields**. -:: - 11. In the **Sample data** window, enter the number of lines you want to sample and click **OK**. The default setting is **100**. The tool reads the file and suggests the field name and type. 12. In the CSV file input window, click **Preview**. -:: - 13. In the **Preview size** window, enter the number of rows you want to preview and click **OK**. The default setting is **1000**. -:: - 14. Verify that the preview data is correct and click **Close**. -:: - 15. Click **OK** in the **CSV file input** window. :ref:`Back to Overview <pentaho_top>` @@ -130,12 +108,8 @@ After creating your transformation you must define your output. 2. Drag and drop **Table output** item to the Transformation window. -:: - 3. Double-click **Table output** to open the **Table output** dialog box. -:: - 4. From the **Table output** dialog box, type a **Step name** and click **New** to create a new connection. Your **steps** are the building blocks of a transformation, such as file input or a table output. The **Database Connection** window is displayed with the **General** tab selected by default. @@ -191,52 +165,35 @@ For more information about backing up users, permissions, or schedules, see `Bac 1. Double-click the **Table output** connection that you just created. -:: - 2. To the right of the **Target schema** field, click **Browse** and select a schema name. -:: - 3. Click **OK**. The selected schema name is displayed in the **Target schema** field. -:: - 4. Create a new hop connection between the **CSV file input** and **Table output** steps: - 1. On the CSV file input step item, click the **new hop connection** icon. + a. On the CSV file input step item, click the **new hop connection** icon. - 2. Drag an arrow from the **CSV file input** step item to the **Table output** step item. + b. Drag an arrow from the **CSV file input** step item to the **Table output** step item. - 3. Release the mouse button. The following options are displayed. + c. Release the mouse button. The following options are displayed. - 4. Select **Main output of step**. - - -:: + d. Select **Main output of step**. 5. Double-click **Table output** to open the **Table output** dialog box. -:: - 6. In the **Target table** field, define a target table name. -:: - 7. Click **SQL** to open the **Simple SQL editor.** -:: - 8. In the **Simple SQL editor**, click **Execute**. The system processes and displays the results of the SQL statements. 9. Close all open dialog boxes. -:: - 10. Click the play button to execute the transformation. From 2e6cf21bd5b50777396966394ea1debf30f7e2e8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 14:54:15 +0300 Subject: [PATCH 1555/1892] Maintenance --- configuration_guides/is_healer_on.rst | 2 +- installation_guides/installing_monit.rst | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst index 1399682df..ba359ec36 100644 --- a/configuration_guides/is_healer_on.rst +++ b/configuration_guides/is_healer_on.rst @@ -12,4 +12,4 @@ The ``is_healer_on`` flag enables the Query Healer, which periodically examines * **Default value** - ``true`` * **Allowed values** - ``true``, ``false`` -For related flags, see :ref:`healer_max_statement_inactivity_seconds`. \ No newline at end of file +For related flags, see :ref:`max_statement_inactivity_seconds`. \ No newline at end of file diff --git a/installation_guides/installing_monit.rst b/installation_guides/installing_monit.rst index 7f2568e25..51260f0b5 100644 --- a/installation_guides/installing_monit.rst +++ b/installation_guides/installing_monit.rst @@ -15,7 +15,7 @@ You can install Monit in one of the following ways: Getting Started =============== -Before installing SQreamDB with Monit, verify that you have followed the required :ref:`recommended pre-installation configurations <recommended_pre-installation_configurations>`. +Before installing SQreamDB with Monit, verify that you have followed the required :ref:`pre-installation_configurations` section. The procedures in the **Installing Monit** guide must be performed on each SQreamDB cluster node. @@ -113,9 +113,8 @@ Building Monit from Pre-Built Binaries $ cp conf/monitrc /etc/ .. - _**Comment - please review this procedure.** -For examples of pre-built Monit binarties, see :ref:`Download Precompiled Binaries<https://mmonit.com/monit/#download>`. +For examples of pre-built Monit binarties, see `Download Precompiled Binaries <https://mmonit.com/monit/#download>`_. Configuring Monit From c31739519258ae1c16b1a76f52376fe62091b123 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:01:35 +0300 Subject: [PATCH 1556/1892] Update sqream_sql_haskell_cli.rst --- reference/cli/sqream_sql_haskell_cli.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/reference/cli/sqream_sql_haskell_cli.rst b/reference/cli/sqream_sql_haskell_cli.rst index c4264c58a..3f910801a 100644 --- a/reference/cli/sqream_sql_haskell_cli.rst +++ b/reference/cli/sqream_sql_haskell_cli.rst @@ -8,8 +8,6 @@ Sqream SQL Haskell CLI SQreamDB comes with a built-in client for executing SQL statements either interactively or from the command-line. -This page serves as a reference for the options and parameters. Learn more about using SQreamDB SQL with the CLI by visiting the :ref:`first_steps` tutorial. - .. contents:: :local: :depth: 1 From bd91f158161baf3a7d646a561f7d4a1760b2fde8 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:27:51 +0300 Subject: [PATCH 1557/1892] Update execute_saved_query.rst --- .../sql/sql_statements/utility_commands/execute_saved_query.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index dd84348e9..f8210b75e 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -103,7 +103,7 @@ Use parameters to replace them later at execution time. .. tip:: Use dollar quoting (`$$`) to avoid escaping strings. -.. code-block:: sql +.. code-block:: psql SELECT SAVE_QUERY('select_by_weight_and_team',$$SELECT * FROM nba WHERE Weight > ? AND Team = ?$$); From 54d156a1e40eaf9e7f4c8ba5394a754433584195 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:42:55 +0300 Subject: [PATCH 1558/1892] Maintenance --- getting_started/hardware_guide.rst | 10 ---------- operational_guides/monitoring_query_performance.rst | 2 +- reference/sql/sql_syntax/common_table_expressions.rst | 2 ++ reference/sql/sql_syntax/cross_database_query.rst | 2 ++ reference/sql/sql_syntax/joins.rst | 2 +- reference/sql/sql_syntax/keywords_and_identifiers.rst | 2 ++ reference/sql/sql_syntax/literals.rst | 2 ++ reference/sql/sql_syntax/null_handling.rst | 2 ++ reference/sql/sql_syntax/scalar_expressions.rst | 2 ++ reference/sql/sql_syntax/sqream_scripting.rst | 2 ++ reference/sql/sql_syntax/subqueries.rst | 2 ++ reference/sql/sql_syntax/window_functions.rst | 2 ++ 12 files changed, 20 insertions(+), 12 deletions(-) diff --git a/getting_started/hardware_guide.rst b/getting_started/hardware_guide.rst index 3fb2b7a7a..b1df6d969 100644 --- a/getting_started/hardware_guide.rst +++ b/getting_started/hardware_guide.rst @@ -26,12 +26,8 @@ A typical SQreamDB cluster includes one or more nodes, consisting of: * Two-socket enterprise processors, such as Intel® Xeon® Gold processors or the IBM® POWER9 processors, providing the high performance required for compute-bound database workloads. - :: - * NVIDIA Tesla GPU accelerators, with up to 5,120 CUDA and Tensor cores, running on PCIe or fast NVLINK busses, delivering high core count, and high-throughput performance on massive datasets. - :: - * High density chassis design, offering between 2 and 4 GPUs in a 1U, 2U, or 3U package, for best-in-class performance per cm\ :sup:`2`. Single-Node Cluster @@ -167,16 +163,10 @@ This section describes the following cluster design considerations: * In a SQreamDB installation, the storage and computing are logically separated. While they may reside on the same machine in a standalone installation, they may also reside on different hosts, providing additional flexibility and scalability. - :: - * SQreamDB uses all resources in a machine, including CPU, RAM, and GPU to deliver the best performance. At least 256GB of RAM per physical GPU is recommended. - :: - * Local disk space is required for good temporary spooling performance, particularly when performing intensive operations exceeding the available RAM, such as sorting. SQreamDB recommends an SSD or NVMe drive in RAID0 configuration with about twice the RAM size available for temporary storage. This can be shared with the operating system drive if necessary. - :: - * When using NAS devices, SQreamDB recommends approximately 5GB/s of burst throughput from storage per GPU. Balancing Cost and Performance diff --git a/operational_guides/monitoring_query_performance.rst b/operational_guides/monitoring_query_performance.rst index 51552a921..81050e03b 100644 --- a/operational_guides/monitoring_query_performance.rst +++ b/operational_guides/monitoring_query_performance.rst @@ -201,7 +201,7 @@ See the examples below to understand how the query execution plan is instrumenta Information Presented in the Execution Plan ------------------------------------------- -.. include:: /reference/sql/sql_statements/monitoring_commands/show_node_info.rst +.. include:: /reference/sql/sql_statements/utility_commands/show_node_info.rst :start-line: 47 :end-line: 78 diff --git a/reference/sql/sql_syntax/common_table_expressions.rst b/reference/sql/sql_syntax/common_table_expressions.rst index a1958f02e..63b2a1b2b 100644 --- a/reference/sql/sql_syntax/common_table_expressions.rst +++ b/reference/sql/sql_syntax/common_table_expressions.rst @@ -1,3 +1,5 @@ +:orphan: + .. _common_table_expressions: ************************ diff --git a/reference/sql/sql_syntax/cross_database_query.rst b/reference/sql/sql_syntax/cross_database_query.rst index 57bc92c85..822cf4920 100644 --- a/reference/sql/sql_syntax/cross_database_query.rst +++ b/reference/sql/sql_syntax/cross_database_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _cross_database_query: *************************** diff --git a/reference/sql/sql_syntax/joins.rst b/reference/sql/sql_syntax/joins.rst index 94f61291a..e14b69495 100644 --- a/reference/sql/sql_syntax/joins.rst +++ b/reference/sql/sql_syntax/joins.rst @@ -1,4 +1,4 @@ -.. _joins: +:orphan: ***** Joins diff --git a/reference/sql/sql_syntax/keywords_and_identifiers.rst b/reference/sql/sql_syntax/keywords_and_identifiers.rst index 24611d8cf..8d35e7bea 100644 --- a/reference/sql/sql_syntax/keywords_and_identifiers.rst +++ b/reference/sql/sql_syntax/keywords_and_identifiers.rst @@ -1,3 +1,5 @@ +:orphan: + .. _keywords_and_identifiers: ************************ diff --git a/reference/sql/sql_syntax/literals.rst b/reference/sql/sql_syntax/literals.rst index 8891c303a..8dff12132 100644 --- a/reference/sql/sql_syntax/literals.rst +++ b/reference/sql/sql_syntax/literals.rst @@ -1,3 +1,5 @@ +:orphan: + .. _literals: ********* diff --git a/reference/sql/sql_syntax/null_handling.rst b/reference/sql/sql_syntax/null_handling.rst index c8ef596a2..83403a980 100644 --- a/reference/sql/sql_syntax/null_handling.rst +++ b/reference/sql/sql_syntax/null_handling.rst @@ -1,3 +1,5 @@ +:orphan: + .. _null_handling: *************************** diff --git a/reference/sql/sql_syntax/scalar_expressions.rst b/reference/sql/sql_syntax/scalar_expressions.rst index 21cb38ab2..dc86debf6 100644 --- a/reference/sql/sql_syntax/scalar_expressions.rst +++ b/reference/sql/sql_syntax/scalar_expressions.rst @@ -1,3 +1,5 @@ +:orphan: + .. _scalar_expressions: *************************** diff --git a/reference/sql/sql_syntax/sqream_scripting.rst b/reference/sql/sql_syntax/sqream_scripting.rst index 72a274cee..c32d7331b 100644 --- a/reference/sql/sql_syntax/sqream_scripting.rst +++ b/reference/sql/sql_syntax/sqream_scripting.rst @@ -1,3 +1,5 @@ +:orphan: + .. _sqream_scripting: **************** diff --git a/reference/sql/sql_syntax/subqueries.rst b/reference/sql/sql_syntax/subqueries.rst index 74dee538a..7325b0924 100644 --- a/reference/sql/sql_syntax/subqueries.rst +++ b/reference/sql/sql_syntax/subqueries.rst @@ -1,3 +1,5 @@ +:orphan: + .. _subqueries: ********** diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index b236c73b2..6b428d98f 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -1,3 +1,5 @@ +:orphan: + .. _window_functions: ******************** From 3902f8021f02a0d89d391601a2e4c18e9e99c79e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:51:50 +0300 Subject: [PATCH 1559/1892] Maintenance --- architecture/aws_architecture.rst | 2 ++ getting_started/creating_a_database.rst | 2 ++ 2 files changed, 4 insertions(+) diff --git a/architecture/aws_architecture.rst b/architecture/aws_architecture.rst index f9f2c50f7..378be596e 100644 --- a/architecture/aws_architecture.rst +++ b/architecture/aws_architecture.rst @@ -1,3 +1,5 @@ +:orphan: + .. _aws_architecture: **************** diff --git a/getting_started/creating_a_database.rst b/getting_started/creating_a_database.rst index c55f077d4..c7378b5c3 100644 --- a/getting_started/creating_a_database.rst +++ b/getting_started/creating_a_database.rst @@ -1,3 +1,5 @@ +:orphan: + .. _creating_a_database: **************************** From f4782d99066b88ed91d4ac8f06fd2438b0d85b14 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 15:57:06 +0300 Subject: [PATCH 1560/1892] Maintenance --- .../sql/sql_statements/utility_commands/drop_saved_query.rst | 2 ++ .../sql/sql_statements/utility_commands/dump_database_ddl.rst | 2 ++ .../sql/sql_statements/utility_commands/execute_saved_query.rst | 2 ++ reference/sql/sql_statements/utility_commands/explain.rst | 2 ++ .../sql_statements/utility_commands/export_open_snapshots.rst | 2 ++ .../utility_commands/get_all_roles_global_ddl.rst | 2 ++ reference/sql/sql_statements/utility_commands/get_ddl.rst | 2 ++ .../sql/sql_statements/utility_commands/get_function_ddl.rst | 2 ++ .../sql/sql_statements/utility_commands/get_license_info.rst | 2 ++ .../sql/sql_statements/utility_commands/get_open_snapshots.rst | 2 ++ .../sql_statements/utility_commands/get_role_database_ddl.rst | 2 ++ .../sql/sql_statements/utility_commands/get_role_global_ddl.rst | 2 ++ .../sql_statements/utility_commands/get_role_permissions.rst | 2 ++ .../sql_statements/utility_commands/get_total_chunks_size.rst | 2 ++ reference/sql/sql_statements/utility_commands/get_view_ddl.rst | 2 ++ reference/sql/sql_statements/utility_commands/ldap_get_attr.rst | 2 ++ .../sql/sql_statements/utility_commands/list_saved_queries.rst | 2 ++ reference/sql/sql_statements/utility_commands/rechunk.rst | 2 ++ .../sql_statements/utility_commands/recompile_saved_query.rst | 2 ++ .../sql/sql_statements/utility_commands/recompile_view.rst | 2 ++ reference/sql/sql_statements/utility_commands/save_query.rst | 2 ++ .../sql/sql_statements/utility_commands/select_gpu_metrics.rst | 2 ++ .../utility_commands/select_health_check_monitoring.rst | 2 ++ .../sql/sql_statements/utility_commands/show_connections.rst | 2 ++ reference/sql/sql_statements/utility_commands/show_locks.rst | 2 ++ .../sql/sql_statements/utility_commands/show_node_info.rst | 2 ++ .../sql/sql_statements/utility_commands/show_saved_query.rst | 2 ++ .../sql/sql_statements/utility_commands/show_server_status.rst | 2 ++ reference/sql/sql_statements/utility_commands/show_version.rst | 2 ++ .../sql_statements/utility_commands/shutdown_server_command.rst | 2 ++ .../sql/sql_statements/utility_commands/stop_statement.rst | 2 ++ .../sql/sql_statements/utility_commands/swap_table_names.rst | 2 ++ 32 files changed, 64 insertions(+) diff --git a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst index f03bb831d..af69bf715 100644 --- a/reference/sql/sql_statements/utility_commands/drop_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/drop_saved_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _drop_saved_query: ******************** diff --git a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst index 2be276ef7..131b65f52 100644 --- a/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/dump_database_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _dump_database_ddl: ***************** diff --git a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst index f8210b75e..cb3205be1 100644 --- a/reference/sql/sql_statements/utility_commands/execute_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/execute_saved_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _execute_saved_query: ******************** diff --git a/reference/sql/sql_statements/utility_commands/explain.rst b/reference/sql/sql_statements/utility_commands/explain.rst index e9b7e7ee9..cbdb1e4a8 100644 --- a/reference/sql/sql_statements/utility_commands/explain.rst +++ b/reference/sql/sql_statements/utility_commands/explain.rst @@ -1,3 +1,5 @@ +:orphan: + .. _explain: ***************** diff --git a/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst b/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst index 368b6f233..fefd5dffe 100644 --- a/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst +++ b/reference/sql/sql_statements/utility_commands/export_open_snapshots.rst @@ -1,3 +1,5 @@ +:orphan: + .. _export_open_snapshots: ********************* diff --git a/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst index 498713ddd..794e37faa 100644 --- a/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_all_roles_global_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_all_roles_global_ddl: ************************ diff --git a/reference/sql/sql_statements/utility_commands/get_ddl.rst b/reference/sql/sql_statements/utility_commands/get_ddl.rst index 07a25951a..fc8ce9f1a 100644 --- a/reference/sql/sql_statements/utility_commands/get_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_ddl: ******* diff --git a/reference/sql/sql_statements/utility_commands/get_function_ddl.rst b/reference/sql/sql_statements/utility_commands/get_function_ddl.rst index 4327ba33f..c3a4ba7f6 100644 --- a/reference/sql/sql_statements/utility_commands/get_function_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_function_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_function_ddl: ***************** diff --git a/reference/sql/sql_statements/utility_commands/get_license_info.rst b/reference/sql/sql_statements/utility_commands/get_license_info.rst index b9622804d..226009edb 100644 --- a/reference/sql/sql_statements/utility_commands/get_license_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_license_info.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_license_info: ******************** diff --git a/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst index 32de6c151..7cbb01798 100644 --- a/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst +++ b/reference/sql/sql_statements/utility_commands/get_open_snapshots.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_open_snapshots: ****************** diff --git a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst index 5a557f690..410559d82 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_database_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_role_database_ddl: ********************* diff --git a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst index d622654d9..0d0e4b5f0 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_global_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_role_global_ddl: ******************* diff --git a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst index cccc7d78f..94a19e075 100644 --- a/reference/sql/sql_statements/utility_commands/get_role_permissions.rst +++ b/reference/sql/sql_statements/utility_commands/get_role_permissions.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_role_permissions: ******************** diff --git a/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst index daf241a16..4398432e8 100644 --- a/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst +++ b/reference/sql/sql_statements/utility_commands/get_total_chunks_size.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_total_chunks_size: ********************** diff --git a/reference/sql/sql_statements/utility_commands/get_view_ddl.rst b/reference/sql/sql_statements/utility_commands/get_view_ddl.rst index 6ae5d4328..ac8962edb 100644 --- a/reference/sql/sql_statements/utility_commands/get_view_ddl.rst +++ b/reference/sql/sql_statements/utility_commands/get_view_ddl.rst @@ -1,3 +1,5 @@ +:orphan: + .. _get_view_ddl: ************ diff --git a/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst b/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst index a9bf67aff..c33068fc8 100644 --- a/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst +++ b/reference/sql/sql_statements/utility_commands/ldap_get_attr.rst @@ -1,3 +1,5 @@ +:orphan: + .. _ldap_get_attr: ************* diff --git a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst index f57183de9..46ef1f8f3 100644 --- a/reference/sql/sql_statements/utility_commands/list_saved_queries.rst +++ b/reference/sql/sql_statements/utility_commands/list_saved_queries.rst @@ -1,3 +1,5 @@ +:orphan: + .. _list_saved_queries: ******************** diff --git a/reference/sql/sql_statements/utility_commands/rechunk.rst b/reference/sql/sql_statements/utility_commands/rechunk.rst index 1313caae5..ef69ca3ed 100644 --- a/reference/sql/sql_statements/utility_commands/rechunk.rst +++ b/reference/sql/sql_statements/utility_commands/rechunk.rst @@ -1,3 +1,5 @@ +:orphan: + .. _rechunk: ******* diff --git a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst index 97b1139e9..524f892b3 100644 --- a/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/recompile_saved_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _recompile_saved_query: ************************** diff --git a/reference/sql/sql_statements/utility_commands/recompile_view.rst b/reference/sql/sql_statements/utility_commands/recompile_view.rst index 1abea0d8c..769d27daf 100644 --- a/reference/sql/sql_statements/utility_commands/recompile_view.rst +++ b/reference/sql/sql_statements/utility_commands/recompile_view.rst @@ -1,3 +1,5 @@ +:orphan: + .. _recompile_view: ***************** diff --git a/reference/sql/sql_statements/utility_commands/save_query.rst b/reference/sql/sql_statements/utility_commands/save_query.rst index 9310e7ce8..8bc9507cb 100644 --- a/reference/sql/sql_statements/utility_commands/save_query.rst +++ b/reference/sql/sql_statements/utility_commands/save_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _save_query: ***************** diff --git a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst index 8a89d6195..474b05ad8 100644 --- a/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst +++ b/reference/sql/sql_statements/utility_commands/select_gpu_metrics.rst @@ -1,3 +1,5 @@ +:orphan: + .. _select_gpu_metrics: ************************* diff --git a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst index 4e274ab8a..c5e3bf773 100644 --- a/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst +++ b/reference/sql/sql_statements/utility_commands/select_health_check_monitoring.rst @@ -1,3 +1,5 @@ +:orphan: + .. _select_health_check_monitoring: .. role:: red diff --git a/reference/sql/sql_statements/utility_commands/show_connections.rst b/reference/sql/sql_statements/utility_commands/show_connections.rst index 1bd320a4c..3a498caeb 100644 --- a/reference/sql/sql_statements/utility_commands/show_connections.rst +++ b/reference/sql/sql_statements/utility_commands/show_connections.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_connections: ******************** diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index 2f032b414..4e4c2216f 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_locks: ********** diff --git a/reference/sql/sql_statements/utility_commands/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst index 47e43be5b..7337ddb6c 100644 --- a/reference/sql/sql_statements/utility_commands/show_node_info.rst +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_node_info: ******************** diff --git a/reference/sql/sql_statements/utility_commands/show_saved_query.rst b/reference/sql/sql_statements/utility_commands/show_saved_query.rst index b85265747..2062dcb3a 100644 --- a/reference/sql/sql_statements/utility_commands/show_saved_query.rst +++ b/reference/sql/sql_statements/utility_commands/show_saved_query.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_saved_query: ******************** diff --git a/reference/sql/sql_statements/utility_commands/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst index 73902a046..6d30c07ac 100644 --- a/reference/sql/sql_statements/utility_commands/show_server_status.rst +++ b/reference/sql/sql_statements/utility_commands/show_server_status.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_server_status: ******************** diff --git a/reference/sql/sql_statements/utility_commands/show_version.rst b/reference/sql/sql_statements/utility_commands/show_version.rst index 8c3e7565e..3a6769569 100644 --- a/reference/sql/sql_statements/utility_commands/show_version.rst +++ b/reference/sql/sql_statements/utility_commands/show_version.rst @@ -1,3 +1,5 @@ +:orphan: + .. _show_version: ***************** diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index a5996a5ef..bc3b3a14d 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -1,3 +1,5 @@ +:orphan: + .. _shutdown_server_command: ******************** diff --git a/reference/sql/sql_statements/utility_commands/stop_statement.rst b/reference/sql/sql_statements/utility_commands/stop_statement.rst index 64256d681..dff97720b 100644 --- a/reference/sql/sql_statements/utility_commands/stop_statement.rst +++ b/reference/sql/sql_statements/utility_commands/stop_statement.rst @@ -1,3 +1,5 @@ +:orphan: + .. _stop_statement: ******************** diff --git a/reference/sql/sql_statements/utility_commands/swap_table_names.rst b/reference/sql/sql_statements/utility_commands/swap_table_names.rst index 226ab1166..5aba6933a 100644 --- a/reference/sql/sql_statements/utility_commands/swap_table_names.rst +++ b/reference/sql/sql_statements/utility_commands/swap_table_names.rst @@ -1,3 +1,5 @@ +:orphan: + .. _swap_table_names: **************** From ef879760f666a202f791609633e83d2f152fd441 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 15 Aug 2024 16:16:54 +0300 Subject: [PATCH 1561/1892] Update sqream_scripting.rst --- reference/sql/sql_syntax/sqream_scripting.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/reference/sql/sql_syntax/sqream_scripting.rst b/reference/sql/sql_syntax/sqream_scripting.rst index c32d7331b..7a14e9aa6 100644 --- a/reference/sql/sql_syntax/sqream_scripting.rst +++ b/reference/sql/sql_syntax/sqream_scripting.rst @@ -11,11 +11,11 @@ The Java- based SQreamDB scripting enhances your interaction with SQL by providi Syntax ====== -.. code-block:: postgres +.. code-block:: psql -- Double curly brackets - {{ … }} + {{ ... }} -- Parallel: @@ -78,7 +78,7 @@ Examples Double Curly Brackets --------------------- -.. code-block:: console +.. code-block:: cry {{ return 1; @@ -87,7 +87,7 @@ Double Curly Brackets ``Parallel`` ------------ -.. code-block:: console +.. code-block:: cry @@ Parallel $$ @@ -99,7 +99,7 @@ Double Curly Brackets ``Declare`` ----------- -.. code-block:: console +.. code-block:: psql @@ Declare myVar = 3; SELECT '${myVar}'; @@ -107,7 +107,7 @@ Double Curly Brackets ``SetResults`` -------------- -.. code-block:: console +.. code-block:: cry @@ SetResults tableAverage SELECT AVG(col1) AS avg_salary FROM my_table; @@ -118,7 +118,7 @@ Double Curly Brackets ``SplitQueryByDateTime`` ------------------------ -.. code-block:: console +.. code-block:: psql @@ SplitQueryByDateTime instances = 4, from = '2021-01-01 00:00:00', to = '2022-01-01 00:00:00' SELECT ${from}, ${to}; @@ -127,7 +127,7 @@ Double Curly Brackets ``SplitQueryByDate`` -------------------- -.. code-block:: console +.. code-block:: psql @@ SplitQueryByDateTime instances = 4, from = '2021-01-01', to = '2022-01-01' SELECT ${from}, ${to}; @@ -136,7 +136,7 @@ Double Curly Brackets ``SplitQueryByNumber`` ---------------------- -.. code-block:: console +.. code-block:: cry @@ SplitQueryByDateTime instances = 4, from = 0, to = 100 SELECT ${from}, ${to}; From 47ca15bdfb2f5f72856b5bda4640daef26cc2ee6 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 18 Aug 2024 13:58:37 +0300 Subject: [PATCH 1562/1892] Update 4.6.rst --- releases/4.6.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/releases/4.6.rst b/releases/4.6.rst index cc9e1c486..d8efb5f1e 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -34,6 +34,8 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► Announcing a new :ref:`Activity Report<view_activity_report>` reflecting your storage and resource usage within a defined time frame. You can export your activity report as a PDF for use in financial records, briefings, or quarterly and yearly reports. + ► Announcing a new cross-platform :ref:`SQream SQL CLI<sqream_sql_cli_reference>` which is Java-based. This new CLI is fully compatible with the old and soon to be :ref:`deprecated Haskell CLI<deprecations>`. It also supports a neat looking result ``table view``. ► A new :ref:`ldap` configuration flag allows including LDAP user attributes in your SQreamDB metadata by associating these attributes with SQreamDB roles. This means that you can now search by these attributes using your SQreamDB web interface. From 3e6aa4203e76d5ad48a0c4bfb90536b6a88b0efe Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Aug 2024 08:42:55 +0300 Subject: [PATCH 1563/1892] Update 4.6.rst --- releases/4.6.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index d8efb5f1e..fca99f850 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -16,7 +16,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * RHEL - 8.x. | +| Supported OS | RHEL - 8.x | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 11.x | +-------------------------+------------------------------------------------------------------------+ From d55576e5343eeeded98285382dc6779f1065408f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Aug 2024 11:01:24 +0300 Subject: [PATCH 1564/1892] SQLoader 8.2 + RN --- data_ingestion/sqloader_as_a_service.rst | 24 +-- releases/4.7.rst | 82 ++++------ releases/4.8.rst | 186 +++++++++++++++++++++++ 3 files changed, 228 insertions(+), 64 deletions(-) create mode 100644 releases/4.8.rst diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 90c123b56..393a04edd 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -70,7 +70,7 @@ Getting All Configuration and JAR Files .. code-block:: bash - tar -xf sqloader_srv_v8.1.tar.gz + tar -xf sqloader_srv_v8.2.tar.gz A folder named ``sqloader`` with the following files is created: @@ -79,7 +79,7 @@ Getting All Configuration and JAR Files ├── sqloader-v1.sh ├── bin │ ├── sqloader-admin-server-1.1.jar - │ └── sqloader-service-8.1.jar + │ └── sqloader-service-8.2.jar ├── config ├── reserved_words.txt ├── sqload-jdbc.properties @@ -97,7 +97,7 @@ Getting All Configuration and JAR Files - Used for defining a connection string and may also be used to reconfigure data loading * - ``reserved_words.txt`` - A list of reserved words which cannot be used as table and/or column names. - * - ``sqloader-service-8.1.jar`` + * - ``sqloader-service-8.2.jar`` - The SQLoader service JAR file * - ``sqloader-admin-server-1.0.jar`` - The SQLoader admin server JAR file @@ -127,32 +127,32 @@ All deployment flags are not dynamically adjustable at runtime. * - ``configDir`` - Optional - ``config`` - - ``java -jar sqloaderService-8.1.jar --configDir=</path/to/directory/>`` + - ``java -jar sqloaderService-8.2.jar --configDir=</path/to/directory/>`` - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file * - ``hzClusterName=<TEXT>`` - Optional - - - ``java -jar sqloader-service-8.1.jar --hzClusterName=<TEXT>`` + - ``java -jar sqloader-service-8.2.jar --hzClusterName=<TEXT>`` - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. * - ``LOG_DIR`` - Optional - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.1.jar`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.2.jar`` - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file * - ``spring.boot.admin.client.url`` - Optional - ``http://localhost:7070`` - - ``java -jar sqloader-service-8.1.jar --spring.boot.admin.client.url=http://IP:PORT`` + - ``java -jar sqloader-service-8.2.jar --spring.boot.admin.client.url=http://IP:PORT`` - SQLoader admin server connection flag * - ``Xmx`` - Optional - - - ``java -jar -Xmx<number>g sqloader-service-8.1.jar`` + - ``java -jar -Xmx<number>g sqloader-service-8.2.jar`` - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` * - ``DEFAULT_PROPERTIES`` - Mandatory - ``sqload-jdbc.properties`` - - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.1.jar`` + - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.2.jar`` - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. Installing the Admin Server and SQLoader Service @@ -258,7 +258,7 @@ Output: BINDIR=/usr/local/sqloader/bin LOG_DIR=/var/log/sqloader-service CONFDIR=/usr/local/sqloader/config - JAR=sqloader-service-8.1.jar + JAR=sqloader-service-8.2.jar PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties PORT=6060 ADMINIP=192.168.5.234 @@ -711,7 +711,9 @@ The following summary table DDL uses Oracle syntax. ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, - HOST TEXT (200 BYTE) DEFAULT NULL, + ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL; + ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL; + ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL; REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL ); diff --git a/releases/4.7.rst b/releases/4.7.rst index 7bae6da79..72275ca9a 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -16,9 +16,9 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | * RHEL - 7.x / 8.x | +| Supported OS | RHEL 8.x | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version from 10.1 up to 11.4.3 | +| supported Nvidia driver | CUDA version 11.x | +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ @@ -35,56 +35,18 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. +► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require :ref:`Health Monitoring<health_monitoring_release>`, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. .. note:: - The ``logFormat`` flag must be configured identically in both your legacy_config_file and your metadata_config_file + The ``logFormat`` flag must be configured identically in both your ``legacy_config_file`` and your ``metadata_config_file`` - - - - -► Multi-platform CLI - -► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. - -:ref:`metadata_server_cli_reference` - -* Using the ``metadata_server_config.json`` file: - - .. code-block:: json - - { - "logPath": "<home/logs/my_logs>" - } +.. _health_monitoring_release: -* Using the CLI: - - .. code-block:: console - - ./metadata_server --log_path=<home/logs/my_logs> - -:ref:`server_picker_cli_reference` - - Using the CLI: - - .. code-block:: console - - ./server_picker --log_path=<home/logs/my_logs> - -:ref:`Worker<current_method_modification_methods>` - - Using the ``sqream_config_legacy.json``: - - .. code-block:: json - - { - "DefaultPathToLogs": "<home/logs/my_logs>" - } - ► :ref:`health_monitoring` +► Lift&Shift + ► ALL log files should reside under the same folder ► Release locks @@ -104,18 +66,32 @@ New Features and Enhancements Known Issues ------------ -* :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` Version 4.7 resolved Issues --------------------------- -+--------------------+---------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+====================+=====================================================================================================================+ -| SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | -+--------------------+---------------------------------------------------------------------------------------------------------------------+ ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16937 | Fixed schema corruption following default permission altering issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17149 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17270 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17457 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17502 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17520 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17944 | Fixed ``UNION`` query result issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ Deprecations diff --git a/releases/4.8.rst b/releases/4.8.rst new file mode 100644 index 000000000..1b69f410d --- /dev/null +++ b/releases/4.8.rst @@ -0,0 +1,186 @@ +.. _4.8: + +***************** +Release Notes 4.8 +***************** + +The 4.8 release notes were released on March XX, 2024 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | RHEL 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 11.x | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 51 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.3.1 | +| | * ODBC 4.4.4 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | +| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | +| | * Spark 5.0.0 | +| | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | +| | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- + + + + +► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. + +.. note:: + + The ``logFormat`` flag must be configured identically in both your ``legacy_config_file`` and your ``metadata_config_file`` + + + + +► Lift&Shift + +► :ref:`health_monitoring` + +► ALL log files should reside under the same folder + +► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. + +:ref:`metadata_server_cli_reference` + +* Using the ``metadata_server_config.json`` file: + + .. code-block:: json + + { + "logPath": "<home/logs/my_logs>" + } + +* Using the CLI: + + .. code-block:: console + + ./metadata_server --log_path=<home/logs/my_logs> + +:ref:`server_picker_cli_reference` + + Using the CLI: + + .. code-block:: console + + ./server_picker --log_path=<home/logs/my_logs> + +:ref:`Worker<current_method_modification_methods>` + + Using the ``sqream_config_legacy.json``: + + .. code-block:: json + + { + "DefaultPathToLogs": "<home/logs/my_logs>" + } + +► Release locks + +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + +► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + +► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.8 resolved Issues +--------------------------- + ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16937 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17149 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17270 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17457 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17502 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17520 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17944 | | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + +Deprecations +------------------- + +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +* REHL 8.x is now officially supported. + +Upgrading to Version 4.8 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + +7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. + +There are two methods of granting back access to services: + + * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function + * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 18c7dcf003cd24eef42b295cde6bdbe828b7500a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Aug 2024 14:31:25 +0300 Subject: [PATCH 1565/1892] SQLoader service --- data_ingestion/sqloader_as_a_service.rst | 6 ++++++ releases/4.7.rst | 12 ++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 393a04edd..02dc5ea95 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -369,6 +369,12 @@ It is recommended that the ``sqload-jdbc.properties`` file will contain a connec SQLoader Service Interface ========================== +The SQLoader service automatically detects the IP addresses of incoming HTTP requests, even if the request originates from the same IP address as the one hosting the service. If you are accessing the service using a proxy server, you can include the client IP address in the request itself by using the ``X-Forwarded-For`` HTTP header, as in the following example: + +.. code-block:: + + curl -X POST -H 'X-Forwarded-For: 192.168.1.2' -H 'Content-Type: application/json' --data '{"loadTypeName": "inc", "sourceSchema": "QA", "sourceTable": "MY_TABLE", "sqreamTable": "MY_TABLE", "sqreamSchema": "QA"}' http://MyPc:6060/load + Supported HTTP Requests ----------------------- diff --git a/releases/4.7.rst b/releases/4.7.rst index 72275ca9a..6b27e65f6 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -80,22 +80,18 @@ Version 4.7 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16937 | Fixed schema corruption following default permission altering issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17149 | | +| SQ-17149 | Created a new ``SWAP_TABLE_NAMES`` utility function to address issue with views affected by SQLoader loads | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17270 | | +| SQ-17270 | Enhanced orphan snapshot cleaning mechanism | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17457 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17502 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17520 | | +| SQ-17520 | Fixed a SQLoader ``cleanup_extents`` related issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-17944 | Fixed ``UNION`` query result issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ Deprecations -------------------- +------------ ► **Haskell CLI** From 019f014d91e6b0190c91c68a6b237ef00dabcf2b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:12:28 +0300 Subject: [PATCH 1566/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 02dc5ea95..f47e18543 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -682,11 +682,13 @@ The following summary table DDL uses Oracle syntax. .. code-block:: sql - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL .. code-block:: sql - CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, @@ -717,9 +719,9 @@ The following summary table DDL uses Oracle syntax. ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, - ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL; - ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL; - ALTER TABLE QACTLG.SQLOAD_SUMMARY ADD ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL; + CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, + REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, + ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL ); From d3d24d5d0cd1bb4cb27a688baf3470e7f67cb21b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 19 Aug 2024 15:25:28 +0300 Subject: [PATCH 1567/1892] RTD version --- conf.py | 1 + requirements.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 186ad7575..73a1fb113 100644 --- a/conf.py +++ b/conf.py @@ -101,6 +101,7 @@ , 'navigation_depth': -1 , 'collapse_navigation': False , 'titles_only': True + , 'flyout_display': 'attached' } diff --git a/requirements.txt b/requirements.txt index 9a5b53fe3..d3137b1cb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # Defining the exact version will make sure things don't break sphinx==7.2.6 -sphinx-rtd-theme>=2.1.0rc1 +sphinx-rtd-theme>=2.1.0rc2 urllib3<=2.0.0 openssl-python>=0.1.1 sphinx-notfound-page>=1.0.4 From ead2df9153bcb9534ca94dd5861d82b60d482640 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:25:57 +0300 Subject: [PATCH 1568/1892] Update 4.8.rst --- releases/4.8.rst | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index 1b69f410d..b1fbc306e 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -37,20 +37,6 @@ New Features and Enhancements - -► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require Health Monitoring, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. - -.. note:: - - The ``logFormat`` flag must be configured identically in both your ``legacy_config_file`` and your ``metadata_config_file`` - - - - -► Lift&Shift - -► :ref:`health_monitoring` - ► ALL log files should reside under the same folder ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. @@ -89,19 +75,7 @@ New Features and Enhancements "DefaultPathToLogs": "<home/logs/my_logs>" } -► Release locks - -► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. - -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. - -► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. - -► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. - -► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. -► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. Known Issues ------------ From be32e2a2655413ea6e25d536a7c21ba6df724c70 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 20 Aug 2024 13:53:39 +0300 Subject: [PATCH 1569/1892] Update current_method_modification_methods.rst --- .../current_method_modification_methods.rst | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/configuration_guides/current_method_modification_methods.rst b/configuration_guides/current_method_modification_methods.rst index b248320b4..ab07c1a6c 100644 --- a/configuration_guides/current_method_modification_methods.rst +++ b/configuration_guides/current_method_modification_methods.rst @@ -66,4 +66,58 @@ The following is an example of the default cluster and session configuration fil "logMaxFileSizeMB": 20, "logFileRotateTimeFrequency": "daily", "waitForClientSeconds": 18000 - } \ No newline at end of file + } + + +Metadata Configuration File +--------------------------- + +When attempting to free up disk space in Oracle Object Store by executing ``DELETE``, ``cleanup``, ``TRUNCATE``, or ``DROP``, ensure that the following four flags are consistently configured in both the :ref:`Worker<modifying_your_configuration_using_the_worker_configuration_file>` and Metadata configuration files. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag Name + - Who May Configure + - Description + - Data Type + - Default Value + * - ``OciBaseRegion`` + - SUPERUSER + - Sets your Oracle Cloud Infrastructure (OCI) region + - String + - NA + * - ``OciVerifySsl`` + - SUPERUSER + - Controls whether SSL certificates are verified. By default, verification is enabled. To disable it, set the variable to ``FALSE`` + - boolean + - ``TRUE`` + * - ``OciAccessKey`` + - SUPERUSER + - Sets your Oracle Cloud Infrastructure (OCI) access key + - String + - NA + * - ``OciAccessSecret`` + - SUPERUSER + - Sets your Oracle Cloud Infrastructure (OCI) access secret + - String + - NA + +The following is an example of the metadata configuration file: + +.. code-block:: json + + { + "OciBaseRegion": "us-ashburn-1", + "OciVerifySsl": false, + "OciAccessKey": "587f59dxxxxxxxxxxxxxxxxxxxxxxxxx", + "OciAccessSecret": "LrSEb+RZgxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + } + + + + + + + From 5541b89266bae50f5ada79cfe70367185f32051e Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 10:06:52 +0300 Subject: [PATCH 1570/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index 1440b58c0..b4722640b 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -4,7 +4,7 @@ Oracle Migration Guide ********************** -This guide is designed to assist those who wish to migrate their database systems from Oracle to SQreamDB. Use this guide to learn how to use the most commonly used Oracle functions with their equivalents in SQreamDB. For functions that do not have direct equivalents in SQreamDB, we provide User-Defined Functions (UDFs). If you need further assistance, our `SQream support team <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ is available to help with any custom UDFs or additional migration questions. +This guide is designed to assist those who wish to migrate their database systems from Oracle to SQreamDB. Use this guide to learn how to use the most commonly used Oracle functions with their equivalents in SQreamDB. For functions that do not have direct equivalents in SQreamDB, we provide :ref:`User-Defined Functions (UDFs)<python_functions>`. If you need further assistance, our `SQream support team <https://sqream.atlassian.net/servicedesk/customer/portal/2/group/8/create/26>`_ is available to help with any custom UDFs or additional migration questions. .. contents:: :local: @@ -420,9 +420,6 @@ Character Functions Returning Number Values * - ``REGEXP_INSTR`` - ``REGEXP_INSTR`` - Returns the start position of a regular expression match in an argument - * - NA - - ``REGEXP_REPLACE`` - - Datetime Functions ------------------ From af78882baec52b7cf63b630fabb589db232222ac Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 11:59:24 +0300 Subject: [PATCH 1571/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index b4722640b..a5a268be5 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -109,7 +109,7 @@ Conversion Functions - SQream - Description * - ``TO_DATE`` - - ``+`` (unary) + - ``CAST`` - Converts a string to a date * - ``TO_NUMBER`` - .. code-block:: postgres From f7c67236c948880d755b04a297f7da5b7729356b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:04:08 +0300 Subject: [PATCH 1572/1892] Update datediff.rst --- .../sql_functions/scalar_functions/date_and_time/datediff.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index 1af8827de..f5b37c79e 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -4,7 +4,7 @@ DATEDIFF ************************** -Calculates the difference between to ``DATE`` or ``DATETIME`` expressions, in terms of a specific date part. +Calculates the difference between two ``DATE`` or ``DATETIME`` expressions, in terms of a specific date part. .. note:: Results are given in integers, rather than ``INTERVAL``, which SQream DB does not support. From d8e3b284e05bc886f69e3987e847942bcc86f8c6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:11:01 +0300 Subject: [PATCH 1573/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index a5a268be5..d85a2133c 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -459,7 +459,7 @@ Datetime Functions - ``CURRENT_TIMESTAMP`` - Returns the current date and time in the session time zone * - ``MONTHS_BETWEEN`` - - NA + - ``DATEDIFF`` - Returns the number of months between specified date values * - ``NEW_TIME`` - NA @@ -523,7 +523,7 @@ Datetime Functions - * - NA - ``DATEDIFF`` - - + - Calculates the difference between two DATE or DATETIME expressions, in terms of a specific date part * - NA - ``DATEPART`` - From 0ed185a8e8db542e05744fcb27a4b07f83917796 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:19:33 +0300 Subject: [PATCH 1574/1892] Update oracle_migration.rst --- operational_guides/oracle_migration.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/operational_guides/oracle_migration.rst b/operational_guides/oracle_migration.rst index d85a2133c..92fbd3a2a 100644 --- a/operational_guides/oracle_migration.rst +++ b/operational_guides/oracle_migration.rst @@ -520,22 +520,22 @@ Datetime Functions - Returns the time zone offset * - NA - ``DATEADD`` - - + - Adds or subtracts an interval to ``DATE`` or ``DATETIME`` value. * - NA - ``DATEDIFF`` - Calculates the difference between two DATE or DATETIME expressions, in terms of a specific date part * - NA - ``DATEPART`` - - + - Extracts a date or time part from a ``DATE`` or ``DATETIME`` value * - NA - ``GETDATE`` - - + - Returns the current date and time of the system * - NA - ``TO_UNIXTS``, ``TO_UNIXTSMS`` - - + - Converts a ``DATETIME`` value to a ``BIGINT`` representing a ``UNIX`` timestamp * - NA - ``FROM_UNIXTS``, ``FROM_UNIXTSMS`` - - + - Converts a ``BIGINT`` representing a ``UNIX`` timestamp to a ``DATETIME`` value General Comparison Functions @@ -712,7 +712,7 @@ Analytic Functions - Description * - NA - ``MODE`` - - + - The ``MODE`` function returns the most common value in the selected column. If there are no repeating values, or if there is the same frequency of multiple values, this function returns the top value based on the ``ORDER BY`` clause * - ``FEATURE_DETAILS`` - NA - Returns feature details for each row in the selection From 059e9505c8eec5f82536f9b497b34ea41249c67f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 21 Aug 2024 14:45:42 +0300 Subject: [PATCH 1575/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index c0e0b9d4f..809954c17 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -75,6 +75,10 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``DDL`` | Column DDL operations | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``INSERT`` | :ref:`insert` into the column | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ +| ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | ++----------------------+-------------------------------------------------------------------------------------------------------------------------+ | **View** | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from view | @@ -189,7 +193,9 @@ GRANT GRANT { { SELECT - | DDL } [, ...] + | DDL + | INSERT + | UPDATE } [, ...] | ALL [PERMISSIONS] } ON @@ -309,6 +315,8 @@ REVOKE { { SELECT | DDL } [, ...] + | INSERT + | UPDATE } [, ...] | ALL [PERMISSIONS]} ON { From c112a6d5937ffeb0c42dc1d87a87db34b1040ecd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Aug 2024 08:36:46 +0300 Subject: [PATCH 1576/1892] Update access_control_permissions.rst --- operational_guides/access_control_permissions.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 809954c17..19e5d033f 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -200,10 +200,8 @@ GRANT } ON { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] - | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <foreign_table_name> [, ...] + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> + | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> } TO <role> [, ...] @@ -320,9 +318,7 @@ REVOKE | ALL [PERMISSIONS]} ON { - COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> [,<table_name2>] | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> [,<table_name2>] - | ALL COLUMNS IN TABLE <schema_name.table_name> [, ...] - | ALL COLUMNS IN FOREIGN TABLE <schema_name.foreign_table_name> [, ...] + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> } FROM <role> [, ...] @@ -385,7 +381,7 @@ schema statement is run. | COLUMNS | CATALOGS | SERVICES - | SAVED_QUERIES + | SAVED QUERIES } { grant_clause | DROP grant_clause } From bd808d5d27f9e7b30fb3ee6b83084fd13fe19b2a Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Aug 2024 08:44:07 +0300 Subject: [PATCH 1577/1892] COLUMN permissions --- .../access_control_commands/grant.rst | 16 ++++++++++++++++ .../access_control_commands/revoke.rst | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/reference/sql/sql_statements/access_control_commands/grant.rst b/reference/sql/sql_statements/access_control_commands/grant.rst index 7668604aa..758bf7c84 100644 --- a/reference/sql/sql_statements/access_control_commands/grant.rst +++ b/reference/sql/sql_statements/access_control_commands/grant.rst @@ -83,6 +83,22 @@ Syntax ON FUNCTION <function_name> TO <role> + -- Grant permissions at the column level: + GRANT + { + { SELECT + | DDL + | INSERT + | UPDATE } [, ...] + | ALL [PERMISSIONS] + } + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> + | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> + } + TO <role> [, ...] + -- Grant permissions on the view level GRANT { {SELECT diff --git a/reference/sql/sql_statements/access_control_commands/revoke.rst b/reference/sql/sql_statements/access_control_commands/revoke.rst index fb383a59a..786d55836 100644 --- a/reference/sql/sql_statements/access_control_commands/revoke.rst +++ b/reference/sql/sql_statements/access_control_commands/revoke.rst @@ -82,6 +82,20 @@ Syntax | DDL } ON FUNCTION <function_name> FROM <role> + + -- Revoke permissions at the column level: + REVOKE + { + { SELECT + | DDL } [, ...] + | INSERT + | UPDATE } [, ...] + | ALL [PERMISSIONS]} + ON + { + COLUMN <column_name> [,<column_name_2>] IN TABLE <table_name> | COLUMN <column_name> [,<column_name_2>] IN FOREIGN TABLE <table_name> + } + FROM <role> [, ...] -- Revoke permissions on the view level REVOKE { From 66893025cf6d68e6ed35b725561e56155f9dda9c Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:37:02 +0300 Subject: [PATCH 1578/1892] remove locks --- feature_guides/concurrency_and_locks.rst | 26 ++++--- operational_guides/health_monitoringrst.rst | 2 - reference/sql/sql_statements/index.rst | 4 + .../remove__statement_locks.rst | 32 ++++++++ .../utility_commands/remove_lock.rst | 76 +++++++++++++++++++ 5 files changed, 127 insertions(+), 13 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/remove__statement_locks.rst create mode 100644 reference/sql/sql_statements/utility_commands/remove_lock.rst diff --git a/feature_guides/concurrency_and_locks.rst b/feature_guides/concurrency_and_locks.rst index 2a85d2642..af300b7c6 100644 --- a/feature_guides/concurrency_and_locks.rst +++ b/feature_guides/concurrency_and_locks.rst @@ -4,7 +4,7 @@ Concurrency and Locks *********************** -Locks are used in SQream DB to provide consistency when there are multiple concurrent transactions updating the database. +Locks are used in SQreamDB to provide consistency when there are multiple concurrent transactions updating the database. Read only transactions are never blocked, and never block anything. Even if you drop a database while concurrently running a query on it, both will succeed correctly (as long as the query starts running before the drop database commits). @@ -13,7 +13,7 @@ Read only transactions are never blocked, and never block anything. Even if you Locking Modes ================ -SQream DB has two kinds of locks: +SQreamDB has two kinds of locks: * ``exclusive`` - this lock mode prevents the resource from being modified by other statements @@ -71,18 +71,22 @@ Monitoring locks across the cluster can be useful when transaction contention ta The utility :ref:`show_locks` can be used to see the active locks. -In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE`` which also :ref:`drops the table<drop_table>`). Thus, SQream DB applies locks during the table creation process to prevent the table from being altered during it's creation. +In this example, we create a table based on results (:ref:`create_table_as`), but we are also effectively dropping the previous table (by using ``OR REPLACE`` which also :ref:`drops the table<drop_table>`). Thus, SQreamDB applies locks during the table creation process to prevent the table from being altered during it's creation. .. code-block:: psql - t=> SELECT SHOW_LOCKS(); - statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time - -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 - 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + SELECT SHOW_LOCKS(); + statement_id | statement_string | username | server | port | locked_object | lockmode | statement_start_time | lock_start_time + -------------+-------------------------------------------------------------------------------------------------+----------+--------------+------+---------------------------------+-----------+----------------------+-------------------- + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | database$t | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | globalpermission$ | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | schema$t$public | Inclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Insert | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + 287 | CREATE OR REPLACE TABLE nba2 AS SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | sqream | 192.168.1.91 | 5000 | table$t$public$nba2$Update | Exclusive | 2019-12-26 00:03:30 | 2019-12-26 00:03:30 + +.. note:: A ``SUPERUSER`` can remove :ref:`unaccounted-for locks<remove_lock>` and has the ability to :ref:`clear all locks<remove_statement_locks>` in the system. + + For more information on troubleshooting lock related issues, see :ref:`lock_related_issues`. \ No newline at end of file diff --git a/operational_guides/health_monitoringrst.rst b/operational_guides/health_monitoringrst.rst index bcd8e3bc0..6d1bdebf1 100644 --- a/operational_guides/health_monitoringrst.rst +++ b/operational_guides/health_monitoringrst.rst @@ -17,8 +17,6 @@ It is essential that you follow these prerequisites: * :ref:`Log files<log_structure>` must be saved as ``JSON`` files -* :ref:`Set the path<export_open_snapshots>` to where you wish your open snapshot information be saved - * Configure `Grafana authentication <https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/grafana/>`_, even if you're using `LDAP <https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/ldap/>`_ for authentication management diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index b368e8399..95dc24372 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -149,6 +149,10 @@ The following table shows the Utility commands: - Recompiles a saved query that has been invalidated due to a schema change * - :ref:`RECOMPILE VIEW<recompile_view>` - Recreate a view after schema changes + * - :ref:`REMOVE LOCK<remove_lock>` + - Clears locks + * - :ref:`REMOVE STATEMENT LOCKS<remove_statement_locks>` + - Clears all locks in the system * - :ref:`SHOW CONNECTIONS<show_connections>` - Returns a list of active sessions on the current worker * - :ref:`SHOW LOCKS<show_locks>` diff --git a/reference/sql/sql_statements/utility_commands/remove__statement_locks.rst b/reference/sql/sql_statements/utility_commands/remove__statement_locks.rst new file mode 100644 index 000000000..69c8988d7 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/remove__statement_locks.rst @@ -0,0 +1,32 @@ +:orphan: + +.. _remove_statement_locks: + +********************** +REMOVE STATEMENT LOCKS +********************** + +The ``REMOVE STATEMENT LOCKS`` utility function clears all orphaned locks that block file cleanup and prevent operations on locked objects within the system. + +To remove specific locks, see :ref:`remove_lock` + +Read more about locks in :ref:`concurrency_and_locks`. + +Syntax +====== + +.. code-block:: postgres + + SELECT REMOVE_STATEMENT_LOCK(<stmt_id> [, <ignore_stmt_exists> ]) + +Example +======= + +.. code-block:: postgres + + SELECT REMOVE_STATEMENT_LOCKS (0); + +Permissions +=========== + +This utility function requires a ``SUPERUSER`` permission on the database level. diff --git a/reference/sql/sql_statements/utility_commands/remove_lock.rst b/reference/sql/sql_statements/utility_commands/remove_lock.rst new file mode 100644 index 000000000..5acf3b210 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/remove_lock.rst @@ -0,0 +1,76 @@ +:orphan: + +.. _remove_lock: + +*********** +REMOVE LOCK +*********** + +The ``REMOVE LOCK`` utility function clears orphaned locks that block file cleanup and prevent operations on locked objects within the system. + +To remove all existing locks, see :ref:`remove_statement_locks` + +Read more about locks in :ref:`concurrency_and_locks`. + +Syntax +====== + +.. code-block:: postgres + + SELECT REMOVE_LOCK(<locked_object>, <stmt_id> [, <ignore_stmt_exists> ]) + +Example +======= + +#. Get locked object names: + + .. code-block:: postgres + + SELECT SHOW_LOCKS(); + + Output: + + .. code-block:: console + + statement id |statement string |username |server |port |locked object |lock mode |statement start time |lock start time |is_statement_active |is_snapshot_active + -------------+----------------------------------+---------+-------------+-----+--------------------------+----------+---------------------+--------------------+--------------------+------------------ + 0 |COPY schema.table FROM WRAPPER .. |sqream |192.168.4.35 |5000 |database$master |Inclusive |29-10-2023 14:20:08 |2023-10-29 14:20:08 |1 |1 + 0 |COPY schema.table FROM WRAPPER .. |sqream |192.168.4.35 |5000 |schema$master$schema |Inclusive |29-10-2023 14:20:08 |2023-10-29 14:20:08 |1 |1 + 0 |COPY schema.table FROM WRAPPER .. |sqream |192.168.4.35 |5000 |table$master$schema$table |Inclusive |29-10-2023 14:20:08 |2023-10-29 14:20:08 |1 |1 + +#. Show server status: + + .. code-block:: postgres + + SELECT SHOW_SERVER_STATUS(); + + Output: + + .. code-block:: console + + service |instanceid |connection_id |serverip |serverport |database_name |user_name |clientip |statementid |statement |statementstarttime |statementstatus |statementstatusstart + --------+-----------+--------------+-------------+-----------+--------------+----------+-------------+------------+-------------------------------------------------------------------------------------------------------------------------------+--------------------+----------------+-------------------- + sqream |node_9383 |1 |192.168.4.35 |5000 |master |sqream |192.168.4.35 |0 |COPY schema.table FROM WRAPPER parquet_fdw OPTIONS (location='/abc/*.c000', CONTINUE_ON_ERROR=true, ERROR_LOG='/abc/log_out'); |29-10-2023 14:20:08 |Executing |29-10-2023 14:20:08 + +#. Remove a specific lock: + + .. code-block:: postgres + + SELECT REMOVE_LOCK ('database$master', 0); + + .. code-block:: postgres + + SELECT REMOVE_LOCK ('schema$master$schema', 0); + + .. code-block:: postgres + + SELECT REMOVE_LOCK ('table$master$schema$table', 0); + + + + + +Permissions +=========== + +This utility function requires a ``SUPERUSER`` permission on the database level. From 50c78665f2c314956e2feb483b7b59d5b689c416 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:43:32 +0300 Subject: [PATCH 1579/1892] RN --- releases/4.6.rst | 2 +- releases/4.7.rst | 2 +- releases/index.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index fca99f850..a45411a62 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -4,7 +4,7 @@ Release Notes 4.6 ***************** -The 4.6 release notes were released on xxxxx xx, 2024 +The 4.6 release notes were released on August 20, 2024 .. contents:: :local: diff --git a/releases/4.7.rst b/releases/4.7.rst index 6b27e65f6..08edbdbe8 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -49,7 +49,7 @@ New Features and Enhancements ► ALL log files should reside under the same folder -► Release locks +► A ``SUPERUSER`` may now release a :ref:`specific lock<remove_lock>` or :ref:`all locks<remove_statement_locks>` blocking file cleanup and preventing operations on locked objects within the system. ► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. diff --git a/releases/index.rst b/releases/index.rst index 43ad86e08..6be1e870e 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -9,7 +9,7 @@ Release Notes * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. * Safely cast data types with the new :ref:`IsCastable<is_castable>` function. -:ref:`Version 4.6 - XXXXX XX, 2024<4.6>` +:ref:`Version 4.6 - August 20, 2024<4.6>` From 7436d71e7587b405ad588312c06ba2f7332148f1 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 22 Aug 2024 13:45:21 +0300 Subject: [PATCH 1580/1892] RN --- releases/4.6.rst | 3 ++- releases/index.rst | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index a45411a62..b0e1251ed 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -4,7 +4,7 @@ Release Notes 4.6 ***************** -The 4.6 release notes were released on August 20, 2024 +The 4.6 release notes were released on August 20th, 2024 .. contents:: :local: @@ -25,6 +25,7 @@ Compatibility Matrix | Driver compatibility | * JDBC 5.3.1 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | | | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | diff --git a/releases/index.rst b/releases/index.rst index 6be1e870e..cc74991a4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -11,7 +11,15 @@ Release Notes :ref:`Version 4.6 - August 20, 2024<4.6>` +* You can now sign in to SQreamDB Studio using your universal :ref:`Single Sign-On (SSO)<sso>` provider authentication +* Announcing a new :ref:`Activity Report<view_activity_report>` reflecting your storage and resource usage + +* Announcing a new Java-based cross-platform :ref:`SQream SQL CLI<sqream_sql_cli_reference>` + +* ``TOP`` clause enhancements + +* :ref:`Saved Query<saved_queries>` command permission enhancements :ref:`Version 4.5 - December 5, 2023<4.5>` From 5b5aecbe87cbab92b1c1cd030f9daffdb2644c4f Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Aug 2024 10:44:16 +0300 Subject: [PATCH 1581/1892] Update 4.7.rst --- releases/4.7.rst | 61 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 08edbdbe8..1b768396e 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,6 +35,31 @@ Compatibility Matrix New Features and Enhancements ----------------------------- +► For any new SQreamDB installation or upgrade, your default :ref:`legacy configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` will include the following cluster flags: + +.. code-block:: json + + { + + "logMaxFileSizeMB": 20, + "logFileRotateTimeFrequency": "daily", + + } + +.. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. Ensure that any code referencing log file names is updated accordingly. + + * When using the ``logFileRotateTimeFrequency`` flag, log file names will follow these patterns: + + ``Daily``: ``sqream_yyyyMMdd_000.log`` + + ``Weekly``: ``sqream_yyyyMMWW_000.log`` (WW = week number within the month) + + ``Monthly``: ``sqream_yyyyMM_000.log`` + + * When using the ``logMaxFileSizeMB`` flag, log files will follow the pattern: + + ``sqream_N.log`` (N = 1 to 13) + ► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require :ref:`Health Monitoring<health_monitoring_release>`, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. .. note:: @@ -47,7 +72,41 @@ New Features and Enhancements ► Lift&Shift -► ALL log files should reside under the same folder +► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. + +:ref:`metadata_server_cli_reference` + +* Using the ``metadata_server_config.json`` file: + + .. code-block:: json + + { + "logPath": "<home/logs/my_logs>" + } + +* Using the CLI: + + .. code-block:: console + + ./metadata_server --log_path=<home/logs/my_logs> + +:ref:`server_picker_cli_reference` + + Using the CLI: + + .. code-block:: console + + ./server_picker --log_path=<home/logs/my_logs> + +:ref:`Worker<current_method_modification_methods>` + + Using the ``sqream_config_legacy.json``: + + .. code-block:: json + + { + "DefaultPathToLogs": "<home/logs/my_logs>" + } ► A ``SUPERUSER`` may now release a :ref:`specific lock<remove_lock>` or :ref:`all locks<remove_statement_locks>` blocking file cleanup and preventing operations on locked objects within the system. From b4aca7819972e22beb0acfe758e6056fd167aaa5 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Aug 2024 10:49:35 +0300 Subject: [PATCH 1582/1892] Update 4.7.rst --- releases/4.7.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 1b768396e..7beb6050b 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -40,10 +40,8 @@ New Features and Enhancements .. code-block:: json { - "logMaxFileSizeMB": 20, "logFileRotateTimeFrequency": "daily", - } .. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. Ensure that any code referencing log file names is updated accordingly. From 56f4972a9013bb168da7d9845afcb56f40238aa7 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 25 Aug 2024 11:02:05 +0300 Subject: [PATCH 1583/1892] Update 4.7.rst --- releases/4.7.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 7beb6050b..928b3fac1 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -44,7 +44,7 @@ New Features and Enhancements "logFileRotateTimeFrequency": "daily", } -.. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. Ensure that any code referencing log file names is updated accordingly. +.. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. **Ensure that any code referencing log file names is updated accordingly**. * When using the ``logFileRotateTimeFrequency`` flag, log file names will follow these patterns: From ade7a0abb207343abf398c29302fb4c83f8447f1 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Aug 2024 13:18:41 +0300 Subject: [PATCH 1584/1892] Update pre-installation_configurations.rst --- .../pre-installation_configurations.rst | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 030a9ab77..3036d1257 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -190,17 +190,11 @@ Setting Up A Locale SQreamDB enables you to set up a locale using your own location. To find out your current time-zone, run the ``timedatectl list-timezones`` command. -1. Set the language of the locale: +Set the language of the locale: - .. code-block:: console - - sudo localectl set-locale LANG=en_US.UTF-8 - -2. Set the time stamp (time and date) of the locale: - - .. code-block:: console +.. code-block:: console - sudo timedatectl set-timezone Asia/Jerusalem + sudo localectl set-locale LANG=en_US.UTF-8 Installing Required Software --------------------------------- From b29ddbfacf36f49addbcaead36504f82c22812ee Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Tue, 27 Aug 2024 14:36:03 +0300 Subject: [PATCH 1585/1892] SHOW commands timestamp --- .../utility_commands/show_locks.rst | 2 +- .../utility_commands/show_node_info.rst | 4 ++-- .../utility_commands/show_server_status.rst | 22 +++++++++++-------- .../utility_commands/stop_statement.rst | 6 ++--- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/show_locks.rst b/reference/sql/sql_statements/utility_commands/show_locks.rst index 4e4c2216f..30e5c3589 100644 --- a/reference/sql/sql_statements/utility_commands/show_locks.rst +++ b/reference/sql/sql_statements/utility_commands/show_locks.rst @@ -65,7 +65,7 @@ Output: statement id |statement string |username |server |port |locked object |lock mode |statement start time |lock start time |is_statement_active |is_snapshot_active -------------+----------------------------------+---------+---------+-----+---------------+----------+---------------------+-------------------+--------------------+------------------ - 2 |create or replace table t (x int);|sqream |127.0.0.1|5000 |database$master|Inclusive |04-07-2024 15:07:02 |2024-07-04 15:07:02|1 |1 + 2 |create or replace table t (x int);|sqream |127.0.0.1|5000 |database$master|Inclusive |2024-07-04 15:07:02 |2024-07-04 15:07:02|1 |1 Permissions diff --git a/reference/sql/sql_statements/utility_commands/show_node_info.rst b/reference/sql/sql_statements/utility_commands/show_node_info.rst index 7337ddb6c..2672153af 100644 --- a/reference/sql/sql_statements/utility_commands/show_node_info.rst +++ b/reference/sql/sql_statements/utility_commands/show_node_info.rst @@ -285,8 +285,8 @@ Getting execution details for a statement t=> SELECT SHOW_SERVER_STATUS(); service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart --------+------------+---------------+--------------+------------+---------------+-----------+--------------+-------------+-----------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 25-12-2019 23:53:13 | Executing | 25-12-2019 23:53:13 - sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 25-12-2019 23:51:31 | Executing | 25-12-2019 23:53:13 + sqream | | 152 | 192.168.1.91 | 5000 | t | sqream | 192.168.1.91 | 176 | SELECT "Name" FROM nba WHERE REGEXP_COUNT("Name", '( )+', 8)>1; | 2019-12-25 23:53:13 | Executing | 2019-12-25 23:53:13 + sqream | | 151 | 192.168.1.91 | 5000 | t | sqream | 192.168.0.1 | 177 | SELECT show_server_status() | 2019-12-25 23:51:31 | Executing | 2019-12-25 23:53:13 The statement ID we want to reserach is ``176``, running on worker ``192.168.1.91``. diff --git a/reference/sql/sql_statements/utility_commands/show_server_status.rst b/reference/sql/sql_statements/utility_commands/show_server_status.rst index 6d30c07ac..c5090765c 100644 --- a/reference/sql/sql_statements/utility_commands/show_server_status.rst +++ b/reference/sql/sql_statements/utility_commands/show_server_status.rst @@ -5,26 +5,28 @@ ******************** SHOW_SERVER_STATUS ******************** + ``SHOW_SERVER_STATUS`` returns a list of active sessions across the cluster. To list active statements on the current worker only, see :ref:`show_connections`. Syntax ========== + The following is the correct syntax when showing your server status: .. code-block:: postgres - show_server_status_statement ::= - SELECT SHOW_SERVER_STATUS() - ; + SELECT SHOW_SERVER_STATUS() Parameters ============ + The Parameters section is not relevant for the ``SHOW_SERVER_STATUS`` statement. Returns ========= + The ``SHOW_SERVER_STATUS`` function returns a list of active sessions. If no sessions are active across the cluster, the result set will be empty. The following table shows the ``SHOW_SERVER_STATUS`` result columns; @@ -85,6 +87,7 @@ The following table shows the statement status values: Notes =========== + This utility shows the active sessions. Some sessions may be actively connected, but not running any statements. Example @@ -96,15 +99,16 @@ The following example shows how to use the ``SHOW_SERVER_STATUS`` statement to g .. code-block:: psql - t=> SELECT SHOW_SERVER_STATUS(); - service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart - --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 17-01-2022 16:19:31 | Executing | 17-01-2022 16:19:32 - sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 17-01-2022 16:19:39 | Executing | 17-01-2022 16:19:39 - sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 17-01-2022 15:55:01 | In Queue | 17-01-2022 15:55:02 + SELECT SHOW_SERVER_STATUS(); + service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart + --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- + sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 2022-01-17 16:19:31 | Executing | 2022-01-17 16:19:32 + sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 2022-01-17 16:19:39 | Executing | 2022-01-17 16:19:39 + sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 2022-01-17 15:55:01 | In Queue | 2022-01-17 15:55:02 The statement ID is ``128``, running on worker ``192.168.1.91``. Permissions ============= + The role must have the ``SUPERUSER`` permissions. diff --git a/reference/sql/sql_statements/utility_commands/stop_statement.rst b/reference/sql/sql_statements/utility_commands/stop_statement.rst index dff97720b..a49865065 100644 --- a/reference/sql/sql_statements/utility_commands/stop_statement.rst +++ b/reference/sql/sql_statements/utility_commands/stop_statement.rst @@ -46,9 +46,9 @@ Example SELECT SHOW_SERVER_STATUS(); service | instanceid | connection_id | serverip | serverport | database_name | user_name | clientip | statementid | statement | statementstarttime | statementstatus | statementstatusstart --------+------------+---------------+---------------+------------+---------------+------------------+---------------+-------------+-------------------------------------------------------------------------------------------------------+---------------------+-----------------+--------------------- - sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 17-01-2022 16:19:31 | Executing | 17-01-2022 16:19:32 - sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 17-01-2022 16:19:39 | Executing | 17-01-2022 16:19:39 - sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 17-01-2022 15:55:01 | In Queue | 17-01-2022 15:55:02 + sqream | sqream_2 | 19 | 192.168.0.111 | 5000 | master | etl | 192.168.0.011 |2484923 | SELECT t1.account, t1.msisd from table a t1 join table b t2 on t1.id = t2.id where t1.msid='123123'; | 2022-01-17 16:19:31 | Executing | 2022-01-17 16:19:32 + sqream | sqream_1 | 2 | 192.168.1.112 | 5000 | master | etl | 192.168.1.112 |2484924 | select show_server_status(); | 2022-01-17 16:19:39 | Executing | 2022-01-17 16:19:39 + sqream | None | 248 | 192.168.1.112 | 5007 | master | maintenance_user | 192.168.1.112 |2484665 | select * from sqream_catalog.tables; | 2022-01-17 15:55:01 | In Queue | 2022-01-17 15:55:02 2. Retrieve stuck statement ID: From 5f10ec3f69d7252bea4f2e6893cd78d000397dca Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:05:03 +0300 Subject: [PATCH 1586/1892] AWS lift and shift --- index.rst | 2 +- installation_guides/index.rst | 3 +- .../upgrade_guide}/index.rst | 0 .../upgrade_guide}/version_upgrade.rst | 0 .../version_upgrade_configurations.rst | 0 sqreamdb_on_aws/index.rst | 119 ++++++++++++++++++ 6 files changed, 122 insertions(+), 2 deletions(-) rename {upgrade_guide => installation_guides/upgrade_guide}/index.rst (100%) rename {upgrade_guide => installation_guides/upgrade_guide}/version_upgrade.rst (100%) rename {upgrade_guide => installation_guides/upgrade_guide}/version_upgrade_configurations.rst (100%) create mode 100644 sqreamdb_on_aws/index.rst diff --git a/index.rst b/index.rst index 98c3ab087..bc01767ec 100644 --- a/index.rst +++ b/index.rst @@ -67,7 +67,7 @@ If you couldn't find what you're looking for, we're always happy to help. Visit getting_started/index installation_guides/index - upgrade_guide/index + sqreamdb_on_aws/index operational_guides/index configuration_guides/index architecture/index diff --git a/installation_guides/index.rst b/installation_guides/index.rst index 216fde62d..09bc68023 100644 --- a/installation_guides/index.rst +++ b/installation_guides/index.rst @@ -13,4 +13,5 @@ The **Installation Guides** section describes the following installation guide s :glob: installing_and_launching_sqream - sqream_studio_installation \ No newline at end of file + sqream_studio_installation + upgrade_guide/index \ No newline at end of file diff --git a/upgrade_guide/index.rst b/installation_guides/upgrade_guide/index.rst similarity index 100% rename from upgrade_guide/index.rst rename to installation_guides/upgrade_guide/index.rst diff --git a/upgrade_guide/version_upgrade.rst b/installation_guides/upgrade_guide/version_upgrade.rst similarity index 100% rename from upgrade_guide/version_upgrade.rst rename to installation_guides/upgrade_guide/version_upgrade.rst diff --git a/upgrade_guide/version_upgrade_configurations.rst b/installation_guides/upgrade_guide/version_upgrade_configurations.rst similarity index 100% rename from upgrade_guide/version_upgrade_configurations.rst rename to installation_guides/upgrade_guide/version_upgrade_configurations.rst diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst new file mode 100644 index 000000000..9a366c565 --- /dev/null +++ b/sqreamdb_on_aws/index.rst @@ -0,0 +1,119 @@ +.. _sqreamdb_on_aws: + +*************** +SQreamDB on AWS +*************** + +The SQreamDB Data Processing and Analytics Acceleration Platform on AWS marketplace is available `here <https://aws.amazon.com/marketplace/pp/prodview-ytpp4pwjcxdca>`_. + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following: + +* An AWS account +* AWS **Key Pairs** +* AWS permissions (verify specific permissions) + +Configuration on AWS +==================== + +Specify stack details +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``environment`` + - The name used for all objects created + * - ``region`` + - Region where we want the machines to be created. The bucket we store sqream contents in should also use the same region for better performance and price + * - ``availability_zones`` + - Availability zone to place the machines inside the region. Should be a zone with GPU machines + * - ``key_name`` + - The name of an EC2 key pair already present in the account that will be used by all created machines to log into them + * - ``office_cidrs`` + - A list of IPs which will be given access to the product and to ssh to the machines (for security) + * - ``sqream_ami`` + - The AMI with Sqream product on it. Currently for Sqream 4.7 use ``ami07d82637b2dab962e`` + * - ``ui_instance_type`` + - Machine type of the UI. Recommended is 16G RAM and some medium CPU such as in ``t2.xlarge`` + * - ``md_instance_type`` + - Machine type of the metadata and server picker machine. Depends on the workflow, but a good starting point is ``t2.2xlarge`` + * - ``workers_instance_type`` + - Machine type of the Workers machines. Must be a GPU machine. Recommended machines are ``g5.xlarge`` or ``g4dn.xlarge`` + * - ``workers_count`` + - Number of worker machines to create + * - ``tablespaceURL`` + - Where the database will be stored. Should be at the same Region as the machine to reduce costs. PAY ATTENTION that a folder terraform_important dir will also be created here and shouldn't be deleted as long as the installation wasn't deleted. Deleting it will cause upgrades and changes to reinstall a new environment instead of using the existing. Uninstall also uses this data, so only after uninstall it should be manually removed + * - ``tempPath`` + - Should typically be ``/mnt/ephemeral``, though it can also be a path in S3. Temp storage used for running queries and is auto-deleted when they are done + +Parameters table (read me) + +License +======= + +#. Get the list of machines: + + * Using the CLI: + + **Terraform:** run Terraform script: + + .. code-block:: console + + ./get_machines.sh + + **AWS Console:** filter EC2 instances using the keyword **worker** and the environment name given. + +#. Send the machines to Sqream to generate license. + +#. Install on each machine the license by: + + a. Connecting to the machine (check "connect to AWS machine" section above) - only available from IPs given access by parameter ``office_cidrs``. + b. Create a new file **in this path:** + + .. code-block:: console + + sudo vi /etc/sqream/license.enc + +#. Place the license given by Sqream in it. + +#. Wait 1-2 minutes for the worker to automatically start. + + +Connecting to the Machine +========================= + +For security purposes, all machines are assigned private IP addresses. To enable connections, an EC2 endpoint is configured during installation. You can connect either via the AWS Console UI or through the CLI. + +Connecting Using the CLI +------------------------ + +You'll need your machine ID and region and the type of key file. + +Run the following command: + +.. code-block:: console + + ssh -i <key file> ec2-user@i-<ID> -o ProxyCommand="aws ec2-instance-connect opentunnel --instance-id i-<ID> --region=<region>" + +Connecting to SQreamDB +====================== + +During installation, a Network Load Balancer (NLB) named ``sqream-<environment>-nlb`` is created to route traffic to various machines. After installation, SqreamDB is accessible via the NLB's DNS name. For the SqreamDB UI, use this URL in any browser, or connect to it from third-party software components. + +#. To get the URL using SQreamDB CLI, run the following script: + + .. code-block:: console + + ./get_url.sh + +#. To get the URL using AWS Console, copy the DNS of the Network Load Balancer. From 9eb443573442d7001f7824abe6bd8e787ad078d6 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:25:53 +0300 Subject: [PATCH 1587/1892] Update index.rst --- sqreamdb_on_aws/index.rst | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index 9a366c565..ddc703959 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -16,14 +16,13 @@ Before You Begin It is essential that you have the following: * An AWS account -* AWS **Key Pairs** -* AWS permissions (verify specific permissions) +* An existing EC2 key pair +* AWS administrator permissions Configuration on AWS ==================== -Specify stack details ------------------------ +Under the **Specify stack details** tab, configure the following parameters: .. list-table:: :widths: auto @@ -32,29 +31,29 @@ Specify stack details * - Parameter - Description * - ``environment`` - - The name used for all objects created + - The identifier used for naming all created resources * - ``region`` - - Region where we want the machines to be created. The bucket we store sqream contents in should also use the same region for better performance and price + - The AWS region where the machines will be deployed. For optimal performance and cost efficiency, the S3 bucket storing Sqream data should be in the same region * - ``availability_zones`` - - Availability zone to place the machines inside the region. Should be a zone with GPU machines + - The availability zone within the specified region to place the machines. It should support GPU-enabled instances * - ``key_name`` - - The name of an EC2 key pair already present in the account that will be used by all created machines to log into them + - The name of an existing EC2 key pair in your AWS account, used to log into all created instances * - ``office_cidrs`` - - A list of IPs which will be given access to the product and to ssh to the machines (for security) + - A list of IP ranges (CIDRs) that are allowed access to the product and SSH access to the machines for security purposes * - ``sqream_ami`` - - The AMI with Sqream product on it. Currently for Sqream 4.7 use ``ami07d82637b2dab962e`` + - The Amazon Machine Image (AMI) pre-configured with Sqream. For Sqream 4.7, use ``ami-07d82637b2dab962e`` * - ``ui_instance_type`` - - Machine type of the UI. Recommended is 16G RAM and some medium CPU such as in ``t2.xlarge`` + - The instance type for the UI server. A machine with 16GB of RAM and moderate CPU resources, such as a ``t2.xlarge``, is recommended * - ``md_instance_type`` - - Machine type of the metadata and server picker machine. Depends on the workflow, but a good starting point is ``t2.2xlarge`` + - The instance type for the metadata and server picker machine. Recommended starting point is a ``t2.2xlarge``, but it may vary depending on your workload * - ``workers_instance_type`` - - Machine type of the Workers machines. Must be a GPU machine. Recommended machines are ``g5.xlarge`` or ``g4dn.xlarge`` + - The instance type for the worker machines, which must be GPU-enabled. Recommended options include ``g5.xlarge`` or ``g4dn.xlarge`` * - ``workers_count`` - - Number of worker machines to create + - The number of worker machines to be created * - ``tablespaceURL`` - - Where the database will be stored. Should be at the same Region as the machine to reduce costs. PAY ATTENTION that a folder terraform_important dir will also be created here and shouldn't be deleted as long as the installation wasn't deleted. Deleting it will cause upgrades and changes to reinstall a new environment instead of using the existing. Uninstall also uses this data, so only after uninstall it should be manually removed + - The location where the database will be stored, ideally in the same region as the instances to minimize costs. Important: A ``terraform_important`` directory will also be created here and should not be deleted unless the installation is completely removed. Deleting this directory prematurely may cause issues during upgrades or changes, leading to a full reinstall of the environment * - ``tempPath`` - - Should typically be ``/mnt/ephemeral``, though it can also be a path in S3. Temp storage used for running queries and is auto-deleted when they are done + - The temporary storage path, usually set to ``/mnt/ephemeral``, though it can also point to an S3 bucket. This storage is used for running queries and is automatically cleared once the queries are completed Parameters table (read me) From f4725a566ae62eb910d1ffe79e76dc1268023a59 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:28:45 +0300 Subject: [PATCH 1588/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index f47e18543..dfe8c597c 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -523,7 +523,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows * - ``drop`` - Optional - - ``true`` + - ``false`` - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter * - ``fetchSize`` - Optional From f26d7bb56c04ae75ac0012cf2ce93f6580e7af57 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:25:51 +0300 Subject: [PATCH 1589/1892] AWS lift & shift --- ...onitoringrst.rst => health_monitoring.rst} | 0 sqreamdb_on_aws/index.rst | 34 +++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-) rename operational_guides/{health_monitoringrst.rst => health_monitoring.rst} (100%) diff --git a/operational_guides/health_monitoringrst.rst b/operational_guides/health_monitoring.rst similarity index 100% rename from operational_guides/health_monitoringrst.rst rename to operational_guides/health_monitoring.rst diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index ddc703959..d72d7abab 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -19,6 +19,11 @@ It is essential that you have the following: * An existing EC2 key pair * AWS administrator permissions +Usage Notes +=========== + +If you need to access data from an external bucket (one that is not part of the SqreamDB installation or used for ``tablespaceURL`` or ``tempPath``), you must manually grant access. Alternatively, you can copy data to and from the bucket using the AWS_ID and AWS_Secret parameters. + Configuration on AWS ==================== @@ -43,11 +48,11 @@ Under the **Specify stack details** tab, configure the following parameters: * - ``sqream_ami`` - The Amazon Machine Image (AMI) pre-configured with Sqream. For Sqream 4.7, use ``ami-07d82637b2dab962e`` * - ``ui_instance_type`` - - The instance type for the UI server. A machine with 16GB of RAM and moderate CPU resources, such as a ``t2.xlarge``, is recommended + - The instance type for the UI server. A machine with 16GB of RAM and moderate CPU resources, such as a ``r6i.2xlarge``, is recommended * - ``md_instance_type`` - - The instance type for the metadata and server picker machine. Recommended starting point is a ``t2.2xlarge``, but it may vary depending on your workload + - The instance type for the metadata and server picker machine. Recommended starting point is a ``r6i.2xlarge``, but it may vary depending on your workload * - ``workers_instance_type`` - - The instance type for the worker machines, which must be GPU-enabled. Recommended options include ``g5.xlarge`` or ``g4dn.xlarge`` + - The instance type for the worker machines, which must be GPU-enabled. Recommended options include ``g6.8xlarge`` or ``g5.8xlarge`` * - ``workers_count`` - The number of worker machines to be created * - ``tablespaceURL`` @@ -116,3 +121,26 @@ During installation, a Network Load Balancer (NLB) named ``sqream-<environment>- ./get_url.sh #. To get the URL using AWS Console, copy the DNS of the Network Load Balancer. + +Connection Troubleshooting +-------------------------- + +If you are unable to connect, please ensure the following: + +* The license file has been generated and distributed to all Worker nodes. +* Your IP address is included in the ``office_cidrs`` parameter, as only the specified IPs are allowed access to the cluster. + +Adding a Signed Certificate to the Cluster +========================================== + +To add your signed certificate to the Sqream cluster, follow these steps: + +#. Create a new listener for the Network Load Balancer (sqreamdb-<environment>-nlb) using the TLS protocol. + +#. A TLS target group that points to the UI machine has already been created for your convenience. You can use it for the new listener. The group name is ``sqream-<environment>-nlb-ui-443``. + +#. If you require a new DNS, you can retrieve the public IP of the Network Load Balancer by either: + + * Running the host CLI command with the NLB's URL + + * Finding it in the AWS console \ No newline at end of file From 7bf661fa10172874904f9050d3c18a9d734a3046 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 13:29:29 +0300 Subject: [PATCH 1590/1892] Update index.rst --- sqreamdb_on_aws/index.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index d72d7abab..0951afb51 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -60,8 +60,6 @@ Under the **Specify stack details** tab, configure the following parameters: * - ``tempPath`` - The temporary storage path, usually set to ``/mnt/ephemeral``, though it can also point to an S3 bucket. This storage is used for running queries and is automatically cleared once the queries are completed -Parameters table (read me) - License ======= @@ -69,17 +67,17 @@ License * Using the CLI: - **Terraform:** run Terraform script: + **Terraform:** run Terraform script: .. code-block:: console ./get_machines.sh - **AWS Console:** filter EC2 instances using the keyword **worker** and the environment name given. + **AWS Console:** filter EC2 instances using the keyword **worker** and the environment name given. -#. Send the machines to Sqream to generate license. +#. Send the machines to SqreamDB to generate license. -#. Install on each machine the license by: +#. On each machine, install the license by: a. Connecting to the machine (check "connect to AWS machine" section above) - only available from IPs given access by parameter ``office_cidrs``. b. Create a new file **in this path:** @@ -88,9 +86,9 @@ License sudo vi /etc/sqream/license.enc -#. Place the license given by Sqream in it. +#. Place the license given by SqreamDB in it. -#. Wait 1-2 minutes for the worker to automatically start. +#. Wait 1-2 minutes for the Worker to automatically start. Connecting to the Machine From 4ea423268fa3631bb0a460ff6bbcd6553c7a6744 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:11:08 +0300 Subject: [PATCH 1591/1892] 2 new utility functions --- reference/sql/sql_statements/index.rst | 4 + .../utility_commands/get_chunk_info.rst | 78 +++++++++++++++++++ .../utility_commands/get_extent_info.rst | 77 ++++++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/get_chunk_info.rst create mode 100644 reference/sql/sql_statements/utility_commands/get_extent_info.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 95dc24372..0d4ec85c1 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -123,8 +123,12 @@ The following table shows the Utility commands: - Returns a static query plan, which can be used to debug query plans * - :ref:`export_open_snapshots` - Lists and saves information about all currently open snapshots to a specified file + * - :ref:`get_chunk_info` + - Retrieves information of specific chunks * - :ref:`GET DDL<get_ddl>` - View the ``CREATE TABLE`` statement for a table + * - :ref:`get_extent_info` + - Retrieves information of specific extents * - :ref:`GET FUNCTION DDL<get_function_ddl>` - View the ``CREATE FUNCTION`` statement for a UDF * - :ref:`GET LICENSE INFO<get_license_info>` diff --git a/reference/sql/sql_statements/utility_commands/get_chunk_info.rst b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst new file mode 100644 index 000000000..a81624954 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst @@ -0,0 +1,78 @@ +:orphan: + +.. _get_chunk_info: + +************** +GET CHUNK INFO +************** + +The ``GET CHUNK INFO`` utility command allows you to retrieve information of specific chunks. + +Syntax +====== + +.. code-block:: sql + + SELECT get_chunk_info(<database_name>, <table_id>, [ chunck_id ]) + +Parameters +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The database within to search for chunk + * - ``table_id`` + - The id of the table related to the chunk + * - ``chunck_id`` + - The id of a specific chunk to search for + +Returns +======= + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The database within the chunk exists + * - ``table_id`` + - The id of the table related to the chunk + * - ``column_id`` + - The id of the column related to the chunk + * - ``chunk_id`` + - The id of the chunk + * - ``extent_id`` + - + * - ``compressed_size`` + - + * - ``uncompressed_size`` + - + +Examples +======== + +.. code-block:: sql + + SELECT get_chunk_info(mfg_ldc_lake, 17271948, 143); + +Output: + +.. code-block:: console + + database_name |table_id |column_id |chunk_id |extent_id |compressed_size |uncompressed_size + --------------+---------+----------+---------+----------+----------------+----------------- + mfg_ldc |17271948 |16 |143 |142 |9892 |9892 + mfg_ldc |17271948 |17 |143 |142 |8 |39568 + + +Permissions +=========== + +This \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_extent_info.rst b/reference/sql/sql_statements/utility_commands/get_extent_info.rst new file mode 100644 index 000000000..93a308c9d --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get_extent_info.rst @@ -0,0 +1,77 @@ +:orphan: + +.. _get_extent_info: + +*************** +GET EXTENT INFO +*************** + +The ``GET EXTENT INFO`` utility command allows you to retrieve information of specific extents. + +Syntax +====== + +.. code-block:: sql + + SELECT get_extent_info(<database_name>, <table_id>, [ column_id ]) + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The database within to search for extent + * - ``table_id`` + - The id of the table related to the extent + * - ``column_id`` + - The id of a specific extent to search for + +Returns +======= + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``database_name`` + - The database within the chunk exists + * - ``table_id`` + - The id of the table related to the chunk + * - ``column_id`` + - The id of the column related to the chunk + * - ``chunk_id`` + - The id of the chunk + * - ``extent_id`` + - + * - ``compressed_size`` + - + * - ``uncompressed_size`` + - + +Examples +======== + +.. code-block:: sql + + SELECT get_extent_info(mfg_ldc_lake, 17271948, 143); + +Output: + +.. code-block:: console + + database_name |table_id |column_id |chunk_id |extent_id |compressed_size |uncompressed_size + --------------+---------+----------+---------+----------+----------------+----------------- + mfg_ldc |17271948 |16 |143 |142 |9892 |9892 + mfg_ldc |17271948 |17 |143 |142 |8 |39568 + + +Permissions +=========== + From e410807c95c8762297411d26c056e5fe2a41c8ef Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 15:29:38 +0300 Subject: [PATCH 1592/1892] 2 new utility functions --- .../sql/sql_statements/utility_commands/get_chunk_info.rst | 2 +- .../sql/sql_statements/utility_commands/get_extent_info.rst | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/get_chunk_info.rst b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst index a81624954..7341fad63 100644 --- a/reference/sql/sql_statements/utility_commands/get_chunk_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst @@ -75,4 +75,4 @@ Output: Permissions =========== -This \ No newline at end of file +This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/get_extent_info.rst b/reference/sql/sql_statements/utility_commands/get_extent_info.rst index 93a308c9d..57c958164 100644 --- a/reference/sql/sql_statements/utility_commands/get_extent_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_extent_info.rst @@ -75,3 +75,4 @@ Output: Permissions =========== +This utility function requires a ``SUPERUSER`` permission. \ No newline at end of file From f14fb3e5a18aa388a00fae097559fda3a39da05b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:08:53 +0300 Subject: [PATCH 1593/1892] Update index.rst --- sqreamdb_on_aws/index.rst | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index 0951afb51..4e5ad8b95 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -27,7 +27,7 @@ If you need to access data from an external bucket (one that is not part of the Configuration on AWS ==================== -Under the **Specify stack details** tab, configure the following parameters: +Under the **CloudFormation** > **Stacks** > **Specify stack details** tab, configure the following parameters: .. list-table:: :widths: auto @@ -63,17 +63,7 @@ Under the **Specify stack details** tab, configure the following parameters: License ======= -#. Get the list of machines: - - * Using the CLI: - - **Terraform:** run Terraform script: - - .. code-block:: console - - ./get_machines.sh - - **AWS Console:** filter EC2 instances using the keyword **worker** and the environment name given. +#. Get a list of machines using your AWS console by filtering EC2 instances with the **worker** keyword and the environment name given. #. Send the machines to SqreamDB to generate license. @@ -112,12 +102,6 @@ Connecting to SQreamDB During installation, a Network Load Balancer (NLB) named ``sqream-<environment>-nlb`` is created to route traffic to various machines. After installation, SqreamDB is accessible via the NLB's DNS name. For the SqreamDB UI, use this URL in any browser, or connect to it from third-party software components. -#. To get the URL using SQreamDB CLI, run the following script: - - .. code-block:: console - - ./get_url.sh - #. To get the URL using AWS Console, copy the DNS of the Network Load Balancer. Connection Troubleshooting @@ -133,7 +117,7 @@ Adding a Signed Certificate to the Cluster To add your signed certificate to the Sqream cluster, follow these steps: -#. Create a new listener for the Network Load Balancer (sqreamdb-<environment>-nlb) using the TLS protocol. +#. `Create a new listener <https://docs.aws.amazon.com/elasticloadbalancing/latest/network/create-listener.html>`_ for the Network Load Balancer (sqream-<environment>-nlb) using the TLS protocol. #. A TLS target group that points to the UI machine has already been created for your convenience. You can use it for the new listener. The group name is ``sqream-<environment>-nlb-ui-443``. From 9a7fa944ce41b9a76df1f8b2ac98939e0845ea86 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Wed, 28 Aug 2024 16:43:12 +0300 Subject: [PATCH 1594/1892] Update index.rst --- sqreamdb_on_aws/index.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index 4e5ad8b95..bb9c43342 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -4,7 +4,9 @@ SQreamDB on AWS *************** -The SQreamDB Data Processing and Analytics Acceleration Platform on AWS marketplace is available `here <https://aws.amazon.com/marketplace/pp/prodview-ytpp4pwjcxdca>`_. +Private cloud deployment on AWS provides the ability to maintain control and security similar to traditional private clouds, while utilizing AWS's scalable infrastructure, flexible resource management, and cost-efficient services. + +The SQreamDB data processing and analytics acceleration platform on AWS marketplace is available `here <https://aws.amazon.com/marketplace/pp/prodview-ytpp4pwjcxdca>`_. .. contents:: :local: From 0383051fb9af3f15b8431c4e3738d8fc7c96fcd9 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Aug 2024 11:13:23 +0300 Subject: [PATCH 1595/1892] 2 new functions --- .../sql/sql_statements/utility_commands/get_chunk_info.rst | 6 +++--- .../sql/sql_statements/utility_commands/get_extent_info.rst | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get_chunk_info.rst b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst index 7341fad63..b01e84814 100644 --- a/reference/sql/sql_statements/utility_commands/get_chunk_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_chunk_info.rst @@ -49,11 +49,11 @@ Returns * - ``chunk_id`` - The id of the chunk * - ``extent_id`` - - + - The id of the extent * - ``compressed_size`` - - + - The size of the chunk's compressed data * - ``uncompressed_size`` - - + - The size of the chunk's uncompressed data Examples ======== diff --git a/reference/sql/sql_statements/utility_commands/get_extent_info.rst b/reference/sql/sql_statements/utility_commands/get_extent_info.rst index 57c958164..5fe998b85 100644 --- a/reference/sql/sql_statements/utility_commands/get_extent_info.rst +++ b/reference/sql/sql_statements/utility_commands/get_extent_info.rst @@ -49,11 +49,11 @@ Returns * - ``chunk_id`` - The id of the chunk * - ``extent_id`` - - + - The id of the extent * - ``compressed_size`` - - + - The size of the extent's compressed data * - ``uncompressed_size`` - - + - The size of the extent's uncompressed data Examples ======== From 90594c84b4d46d4251cd4104d5cb1675b607002b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:51:57 +0300 Subject: [PATCH 1596/1892] pysqream --- connecting_to_sqream/client_drivers/index.rst | 2 +- connecting_to_sqream/client_drivers/python/index.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 61ae7f3e4..a9a74fe4d 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -49,7 +49,7 @@ Client Driver Downloads - - All * - **Python** - - `pysqream v5.1.0 <https://github.com/SQream/pysqream/releases>`_ + - `pysqream v5.2.0 <https://github.com/SQream/pysqream/releases>`_ - :ref:`pysqream` - Recommended installation via ``pip`` - All diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index f5d1ac5e8..591ae8544 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -98,11 +98,11 @@ Installing via PIP without an internet connection .. code-block:: console - tar -xf pysqream_connector_5.1.0.tar.gz - cd pysqream_connector_5.1.0 + tar -xf pysqream_connector_5.2.0.tar.gz + cd pysqream_connector_5.2.0 #Install all packages with --no-index --find-links . python3 -m pip install *.whl -U --no-index --find-links . - python3.9 -m pip install pysqream-5.1.0.zip -U --no-index --find-links . + python3.9 -m pip install pysqream-5.2.0.zip -U --no-index --find-links . python3.9 -m pip install pysqream-sqlalchemy-1.3.zip -U --no-index --find-links . Upgrading an Existing Installation From 678acb0998117a7322306ca5ab027dd6054317ce Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Thu, 29 Aug 2024 14:53:07 +0300 Subject: [PATCH 1597/1892] pysqream --- releases/4.6.rst | 2 +- releases/4.7.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.6.rst b/releases/4.6.rst index b0e1251ed..8d3a60f47 100644 --- a/releases/4.6.rst +++ b/releases/4.6.rst @@ -26,7 +26,7 @@ Compatibility Matrix | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | -| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | +| | * Pysqream 5.2.0 | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | | | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | diff --git a/releases/4.7.rst b/releases/4.7.rst index 928b3fac1..f702cd4b4 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -26,7 +26,7 @@ Compatibility Matrix | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | -| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | +| | * Pysqream 5.2.0 | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | | | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | From 61c545f6fab8b6b7d2c0c1598258dc43f727e209 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:10:55 +0300 Subject: [PATCH 1598/1892] Update 4.7.rst --- releases/4.7.rst | 66 +++++++++++++++++++++++++----------------------- 1 file changed, 35 insertions(+), 31 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index f702cd4b4..e200f22ad 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -35,28 +35,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► For any new SQreamDB installation or upgrade, your default :ref:`legacy configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` will include the following cluster flags: - -.. code-block:: json - - { - "logMaxFileSizeMB": 20, - "logFileRotateTimeFrequency": "daily", - } - -.. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. **Ensure that any code referencing log file names is updated accordingly**. - * When using the ``logFileRotateTimeFrequency`` flag, log file names will follow these patterns: - - ``Daily``: ``sqream_yyyyMMdd_000.log`` - - ``Weekly``: ``sqream_yyyyMMWW_000.log`` (WW = week number within the month) - - ``Monthly``: ``sqream_yyyyMM_000.log`` - - * When using the ``logMaxFileSizeMB`` flag, log files will follow the pattern: - - ``sqream_N.log`` (N = 1 to 13) ► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require :ref:`Health Monitoring<health_monitoring_release>`, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. @@ -70,6 +49,22 @@ New Features and Enhancements ► Lift&Shift + + +► A ``SUPERUSER`` may now release a :ref:`specific lock<remove_lock>` or :ref:`all locks<remove_statement_locks>` blocking file cleanup and preventing operations on locked objects within the system. + +► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. + +► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. + +► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + +► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + +► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + +► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. + ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. :ref:`metadata_server_cli_reference` @@ -106,19 +101,28 @@ New Features and Enhancements "DefaultPathToLogs": "<home/logs/my_logs>" } -► A ``SUPERUSER`` may now release a :ref:`specific lock<remove_lock>` or :ref:`all locks<remove_statement_locks>` blocking file cleanup and preventing operations on locked objects within the system. - -► SQreamDB operates with utmost efficiency when processing tables containing large data chunks. Introducing a new :ref:`rechunk` utility function, it simplifies the management of tables with small data chunks. This feature enables users to merge small data chunks into larger ones and simultaneously eliminating any deleted records present. +► For any new SQreamDB installation or upgrade, your default :ref:`legacy configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` will include the following cluster flags: -► Enable automatic termination of queries that exceed a pre-defined time limit in the queue. The introduction of the :ref:`queueTimeoutMinutes <current_method_configuration_levels>` flag empowers you to set time constraints for queries in the queue, ranging from a few minutes to a maximum of 72 hours. +.. code-block:: json + + { + "logMaxFileSizeMB": 20, + "logFileRotateTimeFrequency": "daily", + } + +.. note:: Starting with SQreamDB version 4.6, log file naming conventions have changed. **Ensure that any code referencing log file names is updated accordingly**. -► Safely cast data types with the new :ref:`IsCastable<is_castable>` function. This function allows you to check whether a cast operation is possible or supported for a given column and data type and provides an alternative when an exception occurs when used within a ``CASE`` statement. + * When using the ``logFileRotateTimeFrequency`` flag, log file names will follow these patterns: -► JDBC enhancements have been implemented to facilitate the retrieval of the record count for the updated number of rows during ``INSERT`` and ``DELETE`` operations when connecting to a third-party platform via JDBC. Use the SQreamDB JDBC connector as usual; the sole distinction is in the ability to now observe the updated number of rows. + ``Daily``: ``sqream_yyyyMMdd_000.log`` + + ``Weekly``: ``sqream_yyyyMMWW_000.log`` (WW = week number within the month) + + ``Monthly``: ``sqream_yyyyMM_000.log`` -► Enhance your :ref:`COPY FROM<copy_from>` operations with the new ``DELETE_SOURCE_ON_SUCCESS`` parameter, which automatically deletes the source file being copied into SQreamDB. This not only saves time and effort in cleaning storage but also helps conserve storage space. + * When using the ``logMaxFileSizeMB`` flag, log files will follow the pattern: -► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. + ``sqream_N.log`` (N = 1 to 13) Known Issues ------------ @@ -152,11 +156,11 @@ Deprecations ► **Haskell CLI** -Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. +Starting February 2025, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB. ► **CentOS Linux 7.x** -* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. +CentOS Linux 7.x has reached its end of life and is not supported by SQreamDB. * REHL 8.x is now officially supported. From 9439371414f59cc309676873695a78fa37ac5f75 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 13:19:16 +0300 Subject: [PATCH 1599/1892] Update index.rst --- sqreamdb_on_aws/index.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sqreamdb_on_aws/index.rst b/sqreamdb_on_aws/index.rst index bb9c43342..724745ec5 100644 --- a/sqreamdb_on_aws/index.rst +++ b/sqreamdb_on_aws/index.rst @@ -4,7 +4,7 @@ SQreamDB on AWS *************** -Private cloud deployment on AWS provides the ability to maintain control and security similar to traditional private clouds, while utilizing AWS's scalable infrastructure, flexible resource management, and cost-efficient services. +Private cloud deployment on AWS provides the AWS's scalable infrastructure, flexible resource management, and cost-efficient services. The SQreamDB data processing and analytics acceleration platform on AWS marketplace is available `here <https://aws.amazon.com/marketplace/pp/prodview-ytpp4pwjcxdca>`_. @@ -65,7 +65,11 @@ Under the **CloudFormation** > **Stacks** > **Specify stack details** tab, confi License ======= -#. Get a list of machines using your AWS console by filtering EC2 instances with the **worker** keyword and the environment name given. +#. Get a list of machines using your AWS console by filtering EC2 instances with: + + * The **worker** keyword + * The environment name given + * The `AWS instance ID for each EC2 <https://docs.aws.amazon.com/managedservices/latest/userguide/find-instance-id.html>`_ #. Send the machines to SqreamDB to generate license. From 982d7e03f2cfffc1aed3df74256729cb4cb81121 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 15:27:27 +0300 Subject: [PATCH 1600/1892] Update health_monitoring.rst --- operational_guides/health_monitoring.rst | 374 +++++++++++++++++++---- 1 file changed, 320 insertions(+), 54 deletions(-) diff --git a/operational_guides/health_monitoring.rst b/operational_guides/health_monitoring.rst index 6d1bdebf1..77eb44fd1 100644 --- a/operational_guides/health_monitoring.rst +++ b/operational_guides/health_monitoring.rst @@ -28,136 +28,378 @@ All Health Monitoring-related installations are on a stand-alone installations. Grafana ------- -Grafana is an open-source analytics and monitoring platform that visualizes data and is used to create dashboards that display real-time and historical data. +Grafana is an open-source analytics and monitoring platform designed for visualizing and analyzing real-time and historical data through customizable dashboards. It offers both an open-source version and an enterprise edition, catering to varying needs and scales of deployment. -You may use both Grafana's open source version and its enterprise version, depending on your needs. +For more details, refer to the `Grafana specification <https://grafana.com/docs/grafana/latest/setup-grafana/installation/#hardware-recommendations>`_. -See `Grafana specification <https://grafana.com/docs/grafana/latest/setup-grafana/installation/#hardware-recommendations>`_ +.. note:: Log in as root user. -Manual Execution -~~~~~~~~~~~~~~~~ - -#. Download Grafana. +Disabling SELinux +~~~~~~~~~~~~~~~~~ -#. Start the Grafana server: +#. Check for the current SELinux status: .. code-block:: console - /usr/share/grafana/bin/grafana server --config=/etc/grafana/grafana.ini --pidfile=/var/run/grafana/grafana-server.pid --packaging=rpm cfg:default.paths.logs=/var/log/grafana cfg:default.paths.data=/var/lib/grafana cfg:default.paths.plugins=/var/lib/grafana/plugins cfg:default.paths.provisioning=/etc/grafana/provisioning + getenforce -Setting Linux Service -~~~~~~~~~~~~~~~~~~~~~ +#. Open the SELinux configuration file: -#. Create Service: + .. code-block:: console + + vim /etc/sysconfig/selinux + +#. Configure ``SELINUX`` to be ``disabled``: .. code-block:: console + + SELINUX=disabled -(Set the command above (case 2) as a linux service) -Slavi - -#. Start the Grafa service: +#. Reboot your system: .. code-block:: console + + reboot - sudo systemctl <start / stop / restart> grafana-server.service +Installing Grafana via YUM Repository +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -#. To view logs: +#. Create a repo file: .. code-block:: console + + vim /etc/yum.repos.d/grafana.repo + +#. Add the following flags to the repo file: - journalctl -xe + .. code-block:: console + + [grafana] + name=grafana + baseurl=https://packages.grafana.com/oss/rpm + repo_gpgcheck=1 + enabled=1 + gpgcheck=1 + gpgkey=https://packages.grafana.com/gpg.key + sslverify=1 + sslcacert=/etc/pki/tls/certs/ca-bundle.crt + +#. Install Grafana -Prometheus ----------- + .. code-block:: console + + sudo yum install grafana + + The installed package performs the following actions: -Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. Prometheus can be used to scrape and store metrics, enabling real-time monitoring, alerting, and analysis of performance and health. + * Installs the Grafana server binary at ``/usr/sbin/grafana-server`` + * Copies the init.d script to ``/etc/init.d/grafana-server`` + * Places the default configuration file in ``/etc/sysconfig/grafana-server`` + * Copies the main configuration file to ``/etc/grafana/grafana.ini`` + * Installs the systemd service file (if systemd is supported) as ``grafana-server.service`` + * By default, logs are written to ``/var/log/grafana/grafana.log`` -#. Download Prometheus. +#. Install free type and urw fonts: -#. (Prometheus Exporter installation) -Slavi + .. code-block:: console + + yum install fontconfig + yum install freetype* + yum install urw-fonts -#. Set the YML path: +Enabling the Grafana Service +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - .. code-block:: console +#. Check for the service status: - PROMETHEUS_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/prometheus.yml + .. code-block:: console + + systemctl status grafana-server + +#. If not active, start the service: -#. Start Prometheus server: + .. code-block:: console + + systemctl start grafana-server + +#. Enable the Grafana service on system boot: .. code-block:: console + + systemctl enable grafana-server.service + +Modifying your Firewall +~~~~~~~~~~~~~~~~~~~~~~~ - sudo /usr/local/bin/prometheus --config.file <PROMETHEUS_YML_PATH> --storage.tsdb.path /var/lib/prometheus/ --web.console.templates=/etc/prometheus/consoles --web.console.libraries=/etc/prometheus/console_libraries &> prometheus.out & +#. Enabling the Grafana port: -Loki and Promtail ------------------ + .. code-block:: console + + firewall-cmd --zone=public --add-port=3000/tcp --permanent + +#. Reload Firewall service: -Loki is a log aggregation system designed to store and query logs, while Promtail is an agent that collects logs and forwards them to Loki. + .. code-block:: console + + firewall-cmd --reload -#. Download Loki and Promtail to ``<LOKI_PROJECT_PATH>``. +Prometheus +---------- -#. Set the Loki YML path: +Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. Prometheus can be used to scrape and store metrics, enabling real-time monitoring, alerting, and analysis of performance and health. - .. code-block:: console +Your sqream installation includes a Prometheus ``yml`` file. - LOKI_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/loki-local-config.yaml +#. Download Prometheus. -#. Set the Promtail YML path: +#. Set the YML path: .. code-block:: console - PROMTAIL_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/promtail-local-config.yml + PROMETHEUS_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/prometheus.yml -#. Start Loki server: +#. Run the following script: .. code-block:: console + + Prometheus_Server_install () { + echo "Prometheus_Server_install" + sudo useradd --no-create-home --shell /bin/false prometheus + sudo mkdir /etc/prometheus + sudo mkdir /var/lib/prometheus + sudo touch /etc/prometheus/prometheus.yml + cat <<EOF | sudo tee /etc/prometheus/prometheus.yml + + #node_exporter port : 9100 + #nvidia_exporter port: 9445 + #process-exporter port: 9256 + + global: + scrape_interval: 10s + + scrape_configs: + - job_name: 'prometheus' + scrape_interval: 5s + static_configs: + - targets: + - 0.0.0.0:9090 + - job_name: 'prosesses' + scrape_interval: 5s + static_configs: + - targets: + - <process exporters iP>:9256 + - <another process exporters iP>:9256 + - job_name: 'nvidia' + scrape_interval: 5s + static_configs: + - targets: + - <nvidia exporter IP>:9445 + - <another nvidia exporter IP>:9445 + - job_name: 'nodes' + scrape_interval: 5s + static_configs: + - targets: + - <node exporter IP>:9100 + - <another node exporter IP>:9100 + EOF + # Assign ownership of the files above to prometheus user + sudo chown -R prometheus:prometheus /etc/prometheus + sudo chown prometheus:prometheus /var/lib/prometheus + + # Download prometheus and copy utilities to where they should be in the filesystem + #VERSION=2.2.1 + #VERSION=$(curl https://raw.githubusercontent.com/prometheus/prometheus/master/VERSION) + #wget https://github.com/prometheus/prometheus/releases/download/v2.31.1/prometheus-2.31.1.linux-amd64.tar.gz + wget ftp://drivers:drivers11@ftp.sq.l/IT-Scripts+Packages/prometheus-2.31.1.linux-amd64.tar.gz + + tar xvzf prometheus-2.31.1.linux-amd64.tar.gz + + sudo cp prometheus-2.31.1.linux-amd64/prometheus /usr/local/bin/ + sudo cp prometheus-2.31.1.linux-amd64/promtool /usr/local/bin/ + sudo cp -r prometheus-2.31.1.linux-amd64/consoles /etc/prometheus + sudo cp -r prometheus-2.31.1.linux-amd64/console_libraries /etc/prometheus + + # Assign the ownership of the tools above to prometheus user + sudo chown -R prometheus:prometheus /etc/prometheus/consoles + sudo chown -R prometheus:prometheus /etc/prometheus/console_libraries + sudo chown prometheus:prometheus /usr/local/bin/prometheus + sudo chown prometheus:prometheus /usr/local/bin/promtool + + # Populate configuration files + #cat ./prometheus/prometheus.yml | sudo tee /etc/prometheus/prometheus.yml + #cat ./prometheus/prometheus.rules.yml | sudo tee /etc/prometheus/prometheus.rules.yml + cat <<EOF | sudo tee /etc/systemd/system/prometheus.service + [Unit] + Description=Prometheus + Wants=network-online.target + After=network-online.target + + [Service] + User=prometheus + Group=prometheus + Type=simple + ExecStart=/usr/local/bin/prometheus \ + --config.file /etc/prometheus/prometheus.yml \ + --storage.tsdb.path /var/lib/prometheus/ \ + --web.console.templates=/etc/prometheus/consoles \ + --web.console.libraries=/etc/prometheus/console_libraries + + [Install] + WantedBy=multi-user.target + EOF + # systemd + sudo systemctl daemon-reload + sudo systemctl enable prometheus + sudo systemctl start prometheus + + # Installation cleanup + #rm prometheus-${VERSION}.linux-amd64.tar.gz + #rm -rf prometheus-${VERSION}.linux-amd64 + } + + Prometheus_Server_install + + This script generates a Prometheus service. + +#. Ensure the user mentioned in the ``/etc/systemd/system/prometheus.service`` Prometheus service has permissions to trigger Prometheus. - sudo <LOKI_PROJECT_PATH>/loki-linux-amd64 -config.file=<LOKI_YML_PATH> &> ~/loki.out & -#. Start Promtail server: +Loki and Promtail +----------------- + +Loki is a log aggregation system designed to store and query logs, while Promtail is an agent that collects logs and forwards them to Loki. + +#. Download Loki: .. code-block:: console + + wget https://github.com/grafana/loki/releases/download/v3.0.0/loki-3.0.0.x86_64.rpm - sudo <LOKI_PROJECT_PATH>/promtail-linux-amd64 -config.file=<PROMTAIL_YML_PATH> &> ~/promtail.out & +#. Download Promtail: -Tempo ------ + .. code-block:: console + + wget https://github.com/grafana/loki/releases/download/v3.0.0/promtail-3.0.0.x86_64.rpm -Tempo is an open-source distributed tracing system designed to handle high volumes of trace data. Tempo can be used to trace database transactions and operations across distributed systems, providing insights into performance bottlenecks and aiding in troubleshooting complex queries. +#. Extract the RPM files onto the appropriate machines: -#. `Download and install <https://grafana.com/docs/tempo/latest/setup/linux/>`_ Tempo. + .. code-block:: console + + sudo rpm -i ~/loki-3.0.0.x86_64.rpm + rpm -i promtail-3.0.0.x86_64.rpm + +#. Open the ``loki.service`` file: -#. Set the Tempo YML path: + .. code-block:: console + + sudo vim /etc/systemd/system/loki.service + +#. Configure the service file: .. code-block:: console + + [Unit] + Description=Loki - TEMPO_YML_PATH=<GRAFANA_PROJECT_PATH>/ymls/tempo.yml + [Service] + ExecStart=/usr/bin/loki -config.file=<LOKI_YML> + User=root + Group=<GROUP> -#. Start Tempo server: + [Install] + WantedBy=multi-user.target + +#. Reload systemd to recognize the new service: .. code-block:: console + + systemctl daemon-reload + +#. Restart the Promtail service: - /usr/bin/tempo -config.file /etc/tempo/config.yml &> ~/tempo.out & + .. code-block:: console +sudo systemctl restart promtail + Exporters --------- An Exporter is a software component that gathers metrics from various sources (such as hardware, software, or services) and exposes them in a format that Prometheus can scrape and store. -GPU Exporter -~~~~~~~~~~~~ +#. Download `Exporters<https://github.com/utkuozdemir/nvidia_gpu_exporter/releases>`_. +#. Install Exporters: + .. code-block:: console + + rpm -i <rpm_file> + +#. Reload your system: + + .. code-block:: console + + sudo systemctl daemon-reload + +#. Restart Exporters service: + .. code-block:: console + + sudo systemctl restart nvidia_gpu_exporter + CPU Exporter ~~~~~~~~~~~~ -#. Download the `CPU Exporter <https://github.com/prometheus/node_exporter/releases/download/v1.8.0/node_exporter-1.8.0.linux-386.tar.gz>`_. +#. Download the `CPU Exporter <https://github.com/prometheus/node_exporter/releases/>`_. -#. Start the Exporter: +#. Extract package content: + + .. code-block:: console + + tar -xvf <package> + +#. Move the ``node_exporter`` binary to the ``/usr/bin directory``: .. code-block:: console + + sudo mv <node_exporter_folder>/node_exporter /usr/bin + +#. Open the ``/etc/systemd/system/node_exporter.service`` file: - /usr/bin/node_exporter &> ~/node_exporter.out & + .. code-block:: console + + sudo vim /etc/systemd/system/node_exporter.service + +Add the following to the service file: + + .. code-block:: console + + [Unit] + Description=Node Exporter + Wants=network-online.target + After=network-online.target + + [Service] + User=prometheus + Group=prometheus + Restart=always + SyslogIdentifier=prometheus + ExecStart=/usr/bin/node_exporter + + [Install] + WantedBy=default.target + +#. Reload the **systemd** manager configuration: + .. code-block:: console + + sudo systemctl daemon-reload + +#. Restart the **Node Exporter** service managed by **systemd** + + .. code-block:: console + + sudo systemctl restart node_exporter + Process Exporter ~~~~~~~~~~~~~~~~ @@ -169,6 +411,30 @@ Process Exporter /usr/bin/process-exporter --config.path /etc/process-exporter/all.yaml --web.listen-address=:9256 &> process_exporter.out & +Deployment +========== + +Grafana +------- + +#. Access the Grafana web interface by entering your server IP or host name to the following URL: + + .. code-block:: console + + http://<server ip or host name>:3000/ + +#. Type in ``admin`` for both user name and password. + +#. Change your password. + +#. Go to **Data Sources** and choose **Prometheus**. + +#. Set **URL** as your Prometheus server ip. + +#. Go to **Dashboards** and choose **Import**. + +#. Import dashboards one by one. + SQream Dashboards ================= From 5c49d94037005634d57c8b5e4d44f1671f6b7f6b Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 16:31:29 +0300 Subject: [PATCH 1601/1892] Health Monitor --- _static/images/monitor_service_example.png | Bin 0 -> 377005 bytes operational_guides/health_monitoring.rst | 169 ++++++++++++++++----- 2 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 _static/images/monitor_service_example.png diff --git a/_static/images/monitor_service_example.png b/_static/images/monitor_service_example.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8623ab1749eb8139f85c99718aba6d6812aa74 GIT binary patch literal 377005 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 literal 0 HcmV?d00001 diff --git a/operational_guides/health_monitoring.rst b/operational_guides/health_monitoring.rst index 77eb44fd1..fca1fe10f 100644 --- a/operational_guides/health_monitoring.rst +++ b/operational_guides/health_monitoring.rst @@ -319,7 +319,7 @@ Loki is a log aggregation system designed to store and query logs, while Promtai .. code-block:: console -sudo systemctl restart promtail + sudo systemctl restart promtail Exporters --------- @@ -435,40 +435,135 @@ Grafana #. Import dashboards one by one. -SQream Dashboards -================= - -https://sqream.atlassian.net/wiki/spaces/~477790253/pages/3134488697/RCA+-+Grafana+installation - --Slavi - -Best Practices -============== - -Daily Usage ------------ - -Grafana Alerts --------------- - -Investigating Health Issues ---------------------------- - -Dealing with Open Snapshots ---------------------------- - -Dealing with Unreleased Locks ------------------------------ - -Dealing with Slow Metadata --------------------------- - -Dealing with Growing Statement Queue ------------------------------------- - -Dealing with Slow Workers -------------------------- - -Dealing with Hung Workers -------------------------- +Using the Monitor Service +========================= + +The Monitor service package includes two files (which must be placed in the same folder): + +* ``monitor_service`` (an executable) +* ``monitor_input.json`` + +Configuring the Monitor Service Worker +-------------------------------------- + +Before running the monitor service worker, ensure the following Sqream configuration flags are properly set: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag + - Description + * - ``"cudaMemQuota": 0`` + - This setting disables GPU memory usage for the monitor service. Consequently, the Worker must be a non-GPU Worker to avoid exceptions from the monitor service. + * - ``"initialSubscribedServices": "monitor"`` + - This configuration specifies that the monitor service should run on a non-GPU Worker. To avoid mixing with GPU Worker processes, the monitor service is set to operate on a designated non-GPU Worker. By default, it runs under the service name ``monitor``, but this can be adjusted if needed. + * - ``"enableNvprofMarkers" : false`` + - Enabling this flag while using a non-GPU Worker results in exceptions. Ensure this flag is turned off to avoid issues since there are no GPU instances involved. + +Execution Arguments +------------------- + +When executing the Monitor service, you can configure the following flags: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag + - Type + - Description + - State + - Default + * - ``-h``, ``--help`` + - option + - + - Shows help message + - + * - ``--host`` + - string + - The SQreamDB host address + - Optional + - ``localhost`` + * - ``--port`` + - integer + - The SQreamDB port number + - Optional + - ``5000`` + * - ``--database`` + - string + - The SQreamDB database name + - Optional + - ``master`` + * - ``--username`` + - string + - The SQreamDB username + - Mandatory + - ``sqream`` + * - ``--password`` + - string + - The SQreamDB password + - Mandatory + - ``sqream`` + * - ``--clustered`` + - option + - An option if the ``server_picker`` is running + - Optional + - ``False`` + * - ``--service`` + - string + - The SQreamDB service name + - Optional + - ``monitor`` + * - ``--loki_host`` + - string + - The Loki instance host address + - Optional + - ``localhost`` + * - ``--loki_port`` + - integer + - The Loki port number + - Optional + - ``3100`` + * - ``--log_file_path`` + - string + - The path to where log files are saved + - Optional + - NA + * - ``--metrics_json_path`` + - string + - The path to where the ``monitor_input.json`` file is stored + - Optional + - ```` + +Example +~~~~~~~ + +Execution example: + +.. code-block:: console + + ./monitor_service --username=sqream --password=sqream --host=1.2.3.4 --port=2711 --service=monitor --loki_host=1.2.3.5 --loki_port=3100 --metrics_json_path='/home/arielw/monitor_service/monitor_input.josn' + +Monitor Service Output Example +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Color + * - Information about monitor service triggering + - Blue + * - Successful insertion + - Green + * - Error + - Red + +|monitor_service_example| + +.. |monitor_service_example| image:: /_static/images/monitor_service_example.png + :align: middle + From 0b78da540301a61c3aa348e19583a72f29daeddd Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:44:49 +0300 Subject: [PATCH 1602/1892] 4.7 RN --- releases/4.7.rst | 20 ++++++++++---------- releases/index.rst | 4 +++- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index e200f22ad..342fe2344 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -4,7 +4,7 @@ Release Notes 4.7 ***************** -The 4.7 release notes were released on March XX, 2024 +The 4.7 release notes were released on September 01, 2024 .. contents:: :local: @@ -37,19 +37,11 @@ New Features and Enhancements -► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require :ref:`Health Monitoring<health_monitoring_release>`, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. - -.. note:: - The ``logFormat`` flag must be configured identically in both your ``legacy_config_file`` and your ``metadata_config_file`` - -.. _health_monitoring_release: ► :ref:`health_monitoring` -► Lift&Shift - - +► SQreamDB may now be deployed on :ref:`AWS private cloud<sqreamdb_on_aws>`. ► A ``SUPERUSER`` may now release a :ref:`specific lock<remove_lock>` or :ref:`all locks<remove_statement_locks>` blocking file cleanup and preventing operations on locked objects within the system. @@ -65,6 +57,14 @@ New Features and Enhancements ► You may now retrieve and manipulate data from different databases within a single SQreamDB cluster through the execution of a single SQL statement using the :ref:`Cross-Database<cross_database_query>` syntax. +► You may now use the new ``logFormat`` flag to configure the format of your log files. By default, logs are saved as ``CSV`` files. To configure your log files to be saved as ``JSON`` instead, use the ``logFormat`` flag in your :ref:`legacy config file<current_method_flag_types>`. If your current logs are in ``CSV`` format and you require :ref:`Health Monitoring<health_monitoring_release>`, it's advisable to configure your logs to be saved in both ``CSV`` and ``JSON`` formats as outlined above. + +.. note:: + + The ``logFormat`` flag must be configured identically in both your ``legacy_config_file`` and your ``metadata_config_file`` + +.. _health_monitoring_release: + ► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. :ref:`metadata_server_cli_reference` diff --git a/releases/index.rst b/releases/index.rst index cc74991a4..dc2d905e0 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,10 +4,12 @@ Release Notes ************* -:ref:`Version 4.7 - March XX, 2024<4.7>` +:ref:`Version 4.7 - September 01, 2024<4.7>` +* :ref:`AWS private cloud deployment<sqreamdb_on_aws>` is now available for SQreamDB on AWS Marketplace. * Execute a single SQL statement across your SQreamDB cluster using the new :ref:`Cross-Database<cross_database_query>` syntax. * Safely cast data types with the new :ref:`IsCastable<is_castable>` function. +* Automatically delete source files being copied into SQreamDB using the :ref:`copy_from` command. :ref:`Version 4.6 - August 20, 2024<4.6>` From 75a277afe1eef67adfbed4504c8bd7372a76fe49 Mon Sep 17 00:00:00 2001 From: RosinTalia <117294941+TaliaSQream@users.noreply.github.com> Date: Sun, 1 Sep 2024 17:49:40 +0300 Subject: [PATCH 1603/1892] Update 4.7.rst --- releases/4.7.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/releases/4.7.rst b/releases/4.7.rst index 342fe2344..484216acc 100644 --- a/releases/4.7.rst +++ b/releases/4.7.rst @@ -37,9 +37,7 @@ New Features and Enhancements - - -► :ref:`health_monitoring` +► Enhance observability and enable shorter investigation times with the new :ref:`health_monitoring` SQreamDB service. ► SQreamDB may now be deployed on :ref:`AWS private cloud<sqreamdb_on_aws>`. From 1328abb4d5fd798cb63008b9d2cc8817e3978166 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Sep 2024 07:44:29 +0300 Subject: [PATCH 1604/1892] Update health_monitoring.rst --- operational_guides/health_monitoring.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/health_monitoring.rst b/operational_guides/health_monitoring.rst index fca1fe10f..f4631993d 100644 --- a/operational_guides/health_monitoring.rst +++ b/operational_guides/health_monitoring.rst @@ -543,7 +543,7 @@ Execution example: .. code-block:: console - ./monitor_service --username=sqream --password=sqream --host=1.2.3.4 --port=2711 --service=monitor --loki_host=1.2.3.5 --loki_port=3100 --metrics_json_path='/home/arielw/monitor_service/monitor_input.josn' + ./monitor_service --username=sqream --password=sqream --host=1.2.3.4 --port=2711 --service=monitor --loki_host=1.2.3.5 --loki_port=3100 --metrics_json_path='/home/arielw/monitor_service/monitor_input.json' Monitor Service Output Example ------------------------------ From 8992535d2fec4477c731ff4f527f8eea9d5bebd0 Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Sep 2024 07:52:17 +0300 Subject: [PATCH 1605/1892] Update health_monitoring.rst --- operational_guides/health_monitoring.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/operational_guides/health_monitoring.rst b/operational_guides/health_monitoring.rst index f4631993d..9da16080e 100644 --- a/operational_guides/health_monitoring.rst +++ b/operational_guides/health_monitoring.rst @@ -453,12 +453,16 @@ Before running the monitor service worker, ensure the following Sqream configura :header-rows: 1 * - Flag + - Configuration File - Description * - ``"cudaMemQuota": 0`` + - :ref:`Worker configuration file<modifying_your_configuration_using_the_worker_configuration_file>` - This setting disables GPU memory usage for the monitor service. Consequently, the Worker must be a non-GPU Worker to avoid exceptions from the monitor service. * - ``"initialSubscribedServices": "monitor"`` + - :ref:`Worker configuration file<modifying_your_configuration_using_the_worker_configuration_file>` - This configuration specifies that the monitor service should run on a non-GPU Worker. To avoid mixing with GPU Worker processes, the monitor service is set to operate on a designated non-GPU Worker. By default, it runs under the service name ``monitor``, but this can be adjusted if needed. * - ``"enableNvprofMarkers" : false`` + - :ref:`Cluster and session configuration file<modifying_your_configuration_using_a_legacy_configuration_file>` - Enabling this flag while using a non-GPU Worker results in exceptions. Ensure this flag is turned off to avoid issues since there are no GPU instances involved. Execution Arguments From 520b6c2bf40ae98cd875bf654c3e257827bcbf2a Mon Sep 17 00:00:00 2001 From: TaliaSQream <117294941+TaliaSQream@users.noreply.github.com> Date: Mon, 2 Sep 2024 08:02:41 +0300 Subject: [PATCH 1606/1892] Update health_monitoring.rst --- operational_guides/health_monitoring.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/operational_guides/health_monitoring.rst b/operational_guides/health_monitoring.rst index 9da16080e..a476e934b 100644 --- a/operational_guides/health_monitoring.rst +++ b/operational_guides/health_monitoring.rst @@ -427,7 +427,9 @@ Grafana #. Change your password. -#. Go to **Data Sources** and choose **Prometheus**. +#. Go to **Data Sources** and choose **prometheus**. + +#. Go to **Data Sources** and choose **loki**. #. Set **URL** as your Prometheus server ip. From 0f55365ae0a58d2d951153f0f34d136e7e13b092 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:12:18 +0300 Subject: [PATCH 1607/1892] Concat --- reference/sql/sql_functions/index.rst | 2 + .../scalar_functions/string/concat.rst | 1 + .../string/concat_function.rst | 86 +++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 reference/sql/sql_functions/scalar_functions/string/concat_function.rst diff --git a/reference/sql/sql_functions/index.rst b/reference/sql/sql_functions/index.rst index 4f7bf1c5a..8ee1b0b8e 100644 --- a/reference/sql/sql_functions/index.rst +++ b/reference/sql/sql_functions/index.rst @@ -235,6 +235,8 @@ The following table shows the **string** functions: - Calculates the position where a string starts inside another string * - :ref:`concat` - Concatenates two strings + * - :ref:`concat_function` + - Concatenates multiple strings * - :ref:`crc64` - Calculates a CRC-64 hash of an argument * - :ref:`decode` diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index c612a9bdd..4e7fcf728 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -5,6 +5,7 @@ ************************** Concatenate two strings to create a longer string +The :ref:`concat_function` provides alternative syntax for CONCAT and requires at least two arguments. Syntax ========== diff --git a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst new file mode 100644 index 000000000..4e204b798 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst @@ -0,0 +1,86 @@ +.. _concat_function: + +************************** +CONCAT function +************************** + +Concatenates one or more strings, or concatenates one or more binary values. +The || operator provides alternative syntax for CONCAT and requires at least two arguments. + +Syntax +========== + + +.. code-block:: postgres + + CONCAT( <expr> [ , <expr> ... ] ) + + +Arguments +============ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``expr1``, ``expr2`` + - String expressions + +Returns +============ + +The data type of the returned value is TEXT, If any input value is NULL, returns NULL. + +Notes +======= + +* SQream DB removes the trailing spaces from strings by default, which may lead to unexpected results. See the examples for more information. + +Examples +=========== + + +For these examples, assume a table named ``nba``, with the following structure: + +.. code-block:: postgres + + CREATE TABLE nba + ( + Name text(40), + Team text(40), + Number tinyint, + Position text(2), + Age tinyint, + Height text(4), + Weight real, + College text(40), + Salary float + ); + + +Here's a peek at the table contents (:download:`Download nba.csv </_static/samples/nba.csv>`): + +.. csv-table:: nba.csv + :file: nba-t10.csv + :widths: auto + :header-rows: 1 + + +Concatenate two values +-------------------------------------- + +Convert values to string types before concatenation + +.. code-block:: psql + + + nba=> SELECT CONCAT(Age ,Name) FROM nba ORDER BY 1 DESC LIMIT 5; + ?column? + ---------------- + 40Tim Duncan + 40Kevin Garnett + 40Andre Miller + 39Vince Carter + 39Pablo Prigioni From eb62d5619b4e35ed17a023b0af8fe5093fbaf109 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 12 Sep 2024 15:13:41 +0300 Subject: [PATCH 1608/1892] Update version to 4.8 --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 73a1fb113..44fcb1414 100644 --- a/conf.py +++ b/conf.py @@ -32,7 +32,7 @@ # The full version, including alpha/beta/rc tags -release = '4.7' +release = '4.8' # -- General configuration --------------------------------------------------- From 75e0fc94ac48b5b4ad53add0d226619f7dec9c5e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:17:52 +0300 Subject: [PATCH 1609/1892] Update concat_function.rst --- .../sql_functions/scalar_functions/string/concat_function.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst index 4e204b798..d314c6d41 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst @@ -5,7 +5,7 @@ CONCAT function ************************** Concatenates one or more strings, or concatenates one or more binary values. -The || operator provides alternative syntax for CONCAT and requires at least two arguments. +The :ref:`concat` operator provides alternative syntax for CONCAT and requires at least two arguments. Syntax ========== From 26c11c66f6be742f8dc65fe61a45b0cb938591c8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 12 Sep 2024 17:22:32 +0300 Subject: [PATCH 1610/1892] Update concat_function.rst --- .../sql_functions/scalar_functions/string/concat_function.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst index d314c6d41..e08507161 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst @@ -5,7 +5,6 @@ CONCAT function ************************** Concatenates one or more strings, or concatenates one or more binary values. -The :ref:`concat` operator provides alternative syntax for CONCAT and requires at least two arguments. Syntax ========== @@ -36,6 +35,7 @@ The data type of the returned value is TEXT, If any input value is NULL, returns Notes ======= +* The :ref:`concat` operator provides alternative syntax for CONCAT and requires at least two arguments. * SQream DB removes the trailing spaces from strings by default, which may lead to unexpected results. See the examples for more information. Examples From e9acb3f903e92b731e55728c547c9b8b00ac4aab Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 15 Sep 2024 08:34:05 +0300 Subject: [PATCH 1611/1892] Create pivot_unpivot.rst --- reference/sql/sql_syntax/pivot_unpivot.rst | 116 +++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 reference/sql/sql_syntax/pivot_unpivot.rst diff --git a/reference/sql/sql_syntax/pivot_unpivot.rst b/reference/sql/sql_syntax/pivot_unpivot.rst new file mode 100644 index 000000000..619d491ba --- /dev/null +++ b/reference/sql/sql_syntax/pivot_unpivot.rst @@ -0,0 +1,116 @@ +:orphan: + +.. _pivot_unpivot: + +******************** +PIVOT & UNPIVOT +******************** + +PIVOT allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. +UNPIVOT does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. + + +Syntax +======== + +.. code-block:: postgres + + SELECT <selected_columns> + + FROM <from_clause> + [ + PIVOT + (<pivot_expression> + FOR <column_name> + IN ([<expression1> AS] <name1>, [<expression2> AS] <name2>, ... , [<expressionN> AS] <nameN>) + ) + [AS <pivoted_result_name>] + ] + [ + UNPIVOT + (<unpivot_expression> + FOR <column_name> + IN ([<name1> AS] expression1, [<name2> AS] expression2, ... , [<nameN> AS] <expressionN>) + ) + [AS <unpivoted_result_name>] + ] + + <rest of the query ...> + + pivot_expression := <aggregation function> ( <column being aggregated> ) + + unpivot_expression := <new output column created for values in result of the source query> + + +Limitations +================= +Gil - here we should list the maximum allowed number of column for PIVOT - 5K? Anything else? All data types supported? Numeric? Array? + + + +Examples +========== + + +.. code-block:: postgres + + CREATE OR REPLACE TABLE Sales ( + ProductID int, + ProductName varchar(50), + SalesDate date, + Revenue decimal(10, 2) + ); + + INSERT INTO Sales (ProductID, ProductName, SalesDate, Revenue) VALUES + (1, 'Product A', '2024-01-01', 100.00), + (2, 'Product B', '2024-01-01', 150.00), + (3, 'Product C', '2024-01-01', 200.00), + (1, 'Product A', '2024-01-02', 120.00), + (2, 'Product B', '2024-01-02', 180.00); + + SELECT * FROM ( + SELECT ProductName, SalesDate, Revenue + FROM Sales + ) AS SourceTable + PIVOT ( + SUM(Revenue) + FOR SalesDate IN ("2024-01-01", "2024-01-02") + ) AS PivotTable; + + Product A ,100.00,120.00 + Product B ,150.00,180.00 + Product C ,200.00,\N + 3 rows + + CREATE OR REPLACE TABLE Sales ( + ProductID int, + ProductName varchar(50), + JanuaryRevenue decimal(10, 2), + FebruaryRevenue decimal(10, 2), + MarchRevenue decimal(10, 2) + ); + + INSERT INTO Sales (ProductID, ProductName, JanuaryRevenue, FebruaryRevenue, MarchRevenue) VALUES + (1, 'Product A', 100.00, 120.00, 150.00), + (2, 'Product B', 150.00, 180.00, 200.00), + (3, 'Product C', 200.00, 220.00, 250.00); + + SELECT ProductID, ProductName, Month, Revenue + FROM ( + SELECT ProductID, ProductName, JanuaryRevenue, FebruaryRevenue, MarchRevenue + FROM Sales + ) AS SourceTable + UNPIVOT ( + Revenue FOR Month IN (JanuaryRevenue, FebruaryRevenue, MarchRevenue) + ) AS UnpivotTable; + + 1,Product A ,JanuaryRevenue,100.00 + 2,Product B ,JanuaryRevenue,150.00 + 3,Product C ,JanuaryRevenue,200.00 + 1,Product A ,FebruaryRevenue,120.00 + 2,Product B ,FebruaryRevenue,180.00 + 3,Product C ,FebruaryRevenue,220.00 + 1,Product A ,MarchRevenue,150.00 + 2,Product B ,MarchRevenue,200.00 + 3,Product C ,MarchRevenue,250.00 + 9 rows From d6de970d4d7193fc8476e870b45f11044d87c51a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 17 Sep 2024 12:52:54 +0300 Subject: [PATCH 1612/1892] Pivot updates --- reference/sql/sql_syntax/index.rst | 4 +++ reference/sql/sql_syntax/pivot_unpivot.rst | 37 ++++++++++++++++++---- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 1f706db1b..40678b5e7 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -32,6 +32,9 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Null handling involves managing and evaluating the presence of null values, representing unknown or undefined data, to avoid unexpected results in queries and expressions. * - :ref:`sqream_scripting` - Metalanguage scripting enhances your interaction with SQL by providing conventions which allow dynamic generation, management, and automation of SQL code. + * - :ref:`pivot_unpivot` + - convert row-level data into columnar representation. + .. toctree:: @@ -51,6 +54,7 @@ SQreamDB supports SQL from the ANSI 92 syntax. subqueries null_handling sqream_scripting + pivot_unpivot diff --git a/reference/sql/sql_syntax/pivot_unpivot.rst b/reference/sql/sql_syntax/pivot_unpivot.rst index 619d491ba..25fc1a3bc 100644 --- a/reference/sql/sql_syntax/pivot_unpivot.rst +++ b/reference/sql/sql_syntax/pivot_unpivot.rst @@ -6,8 +6,8 @@ PIVOT & UNPIVOT ******************** -PIVOT allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. -UNPIVOT does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. +``PIVOT`` allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. +``UNPIVOT`` does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. Syntax @@ -44,13 +44,13 @@ Syntax Limitations ================= -Gil - here we should list the maximum allowed number of column for PIVOT - 5K? Anything else? All data types supported? Numeric? Array? +The number of resulting columns for ``PIVOT`` and the number of input columns for ``UNPIVOT`` is limited to 10,000. -Examples -========== - +PIVOT Example +================= +Create a sales table .. code-block:: postgres @@ -60,6 +60,10 @@ Examples SalesDate date, Revenue decimal(10, 2) ); + +Populate data + +.. code-block:: postgres INSERT INTO Sales (ProductID, ProductName, SalesDate, Revenue) VALUES (1, 'Product A', '2024-01-01', 100.00), @@ -67,6 +71,13 @@ Examples (3, 'Product C', '2024-01-01', 200.00), (1, 'Product A', '2024-01-02', 120.00), (2, 'Product B', '2024-01-02', 180.00); + + +Pivots the SalesDate column, creating new columns for each specified date. +The ``SUM(Revenue)`` aggregates the Revenue for each product and date combination. +The ``PIVOT`` operation creates a new table with ProductName as the first column and additional columns for each specified SalesDate. The values in these columns are the summed Revenue for each product on that date. + +.. code-block:: postgres SELECT * FROM ( SELECT ProductName, SalesDate, Revenue @@ -81,6 +92,12 @@ Examples Product B ,150.00,180.00 Product C ,200.00,\N 3 rows + +UNPIVOT Example +================= +Create a sales table + +.. code-block:: postgres CREATE OR REPLACE TABLE Sales ( ProductID int, @@ -89,12 +106,20 @@ Examples FebruaryRevenue decimal(10, 2), MarchRevenue decimal(10, 2) ); + +Populate data + +.. code-block:: postgres INSERT INTO Sales (ProductID, ProductName, JanuaryRevenue, FebruaryRevenue, MarchRevenue) VALUES (1, 'Product A', 100.00, 120.00, 150.00), (2, 'Product B', 150.00, 180.00, 200.00), (3, 'Product C', 200.00, 220.00, 250.00); +Unpivots the JanuaryRevenue, FebruaryRevenue, and MarchRevenue columns, creating a new column Month and a column Revenue to store the corresponding values. The ``UNPIVOT`` operation creates a new table with ProductID, ProductName, Month, and Revenue columns, effectively transforming the column-based data into a row-based format. + +.. code-block:: postgres + SELECT ProductID, ProductName, Month, Revenue FROM ( SELECT ProductID, ProductName, JanuaryRevenue, FebruaryRevenue, MarchRevenue From 54b836eb2dc3a4e16afda7e3f03e1dc53cdee8f9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 17 Sep 2024 13:01:15 +0300 Subject: [PATCH 1613/1892] Update index.rst --- reference/sql/sql_syntax/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/index.rst b/reference/sql/sql_syntax/index.rst index 40678b5e7..498fec6c3 100644 --- a/reference/sql/sql_syntax/index.rst +++ b/reference/sql/sql_syntax/index.rst @@ -32,7 +32,7 @@ SQreamDB supports SQL from the ANSI 92 syntax. - Null handling involves managing and evaluating the presence of null values, representing unknown or undefined data, to avoid unexpected results in queries and expressions. * - :ref:`sqream_scripting` - Metalanguage scripting enhances your interaction with SQL by providing conventions which allow dynamic generation, management, and automation of SQL code. - * - :ref:`pivot_unpivot` + * - :ref:`pivot_unpivot` - convert row-level data into columnar representation. From b394ee963769279540eef81918836bd28c6891b2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:54:01 +0300 Subject: [PATCH 1614/1892] Remove SQLoader as a process --- data_ingestion/ingesting_from_databases.rst | 674 -------------------- data_ingestion/sqloader.rst | 3 +- index.rst | 2 +- 3 files changed, 2 insertions(+), 677 deletions(-) delete mode 100644 data_ingestion/ingesting_from_databases.rst diff --git a/data_ingestion/ingesting_from_databases.rst b/data_ingestion/ingesting_from_databases.rst deleted file mode 100644 index e631eac41..000000000 --- a/data_ingestion/ingesting_from_databases.rst +++ /dev/null @@ -1,674 +0,0 @@ -.. _ingesting_from_databases: - -********************* -SQLoader As a Process -********************* - -The **SQLoader** is a CLI program that enables you to load data into SQreamDB from other DBMS and DBaaS. - -**SQLoader** supports Oracle, Postgresql, Teradata, Microsoft SQL Server, and SAP HANA. - -.. contents:: - :local: - :depth: 1 - -Before You Begin -================ - -It is essential that you have the following: - -* Java 17 -* SQLoader configuration files -* SQLoader.jar file - -Minimum Hardware Requirements ------------------------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Component - - Type - * - CPU cores - - 16 - * - RAM - - 32GB - -.. _sqloader_thread_sizing_guidelines: - -Sizing Guidelines ------------------ - -The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader instance runs on a single table, meaning concurrent imports of multiple tables require multiple instances. Additionally, when dealing with partitioned tables, each partition consumes a thread, so users should consider the table's partition count when managing thread allocation for efficient performance. - ---------------------------------- - -Installation and Connection -=========================== - -Getting the SQLoader Configuration and JAR Files ------------------------------------------------- - -1. Download the ``.tar`` file using the following command: - - .. code-block:: console - - curl -O https://sq-ftp-public.s3.amazonaws.com/sqloader-v7.13.tar - -2. Extract the ``.tar`` file using the following command: - - .. code-block:: console - - tar -xf sqloader-7.13.tar.gz - - A folder named ``sqloader`` with the following files is created: - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - File - - Description - * - ``sqream-mapping.json`` - - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion - * - ``sqload-jdbc.properties`` - - Used for defining a connection string and may also be used to reconfigure data loading - * - ``reserved_words.txt`` - - A list of reserved words which cannot be used as table and/or column names. - * - ``sqloader.jar`` - - The SQLoader package file - -Establishing a Connection -------------------------- - -The ``sqload-jdbc.properties`` file contains a connection string that must be configured to enable data loading into SQreamDB. - -1. Open the ``sqload-jdbc.properties`` file. -2. Configure connection parameters for: - - a. Either Postgresql, Oracle, Teradata, Microsoft SQL Server, SAP HANA or SQreamDB connection strings - b. Optionally, Oracle or SQreamDB catalogs (recommended) - -.. list-table:: Connection String Parameters - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``HostIp:port`` - - The host and IP address number - * - ``database_name`` - - The name of the database from which data is loaded - * - ``user`` - - Username of a role to use for connection - * - ``password`` - - Specifies the password of the selected role - * - ``ssl`` - - Specifies SSL for this connection - -.. literalinclude:: connection_string.ini - :language: ini - :caption: Properties File Sample - :linenos: - -Starting SQLoader ------------------ - -To start SQLoader, run the ``sqloader.jar`` file: - -.. code-block:: console - - java -jar sqloader.jar - ---------------------------------- - -Loading Data into SQreamDB -========================== - -To load data into SQreamDB using SQLoader, you must specify a source table name at minimum. Executing the command below will generate a SQreamDB table using the specified source table's DDL and load all its data: - -.. code-block:: console - - java -jar sqloader.jar -table <source_table_name> - -.. contents:: - :local: - :depth: 1 - -Customizing Data Load ---------------------- - -While specifying a source table name is mandatory for data loading, you have the option to customize the loading process by utilizing *optional* parameters. These parameters can be configured either within a CLI command or by adjusting settings in the properties file. - -Please note that any customization done through the CLI will override configurations made using the properties file. - -.. list-table:: SQLoader CLI Parameters - :widths: auto - :header-rows: 1 - - * - CLI Parameter - - State - - Default - - Type - - Description - * - ``-batchsize`` - - Optional - - ``10.000`` - - - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes - * - ``-casesensative`` - - Optional - - ``false`` - - - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB - * - ``-check_cdc_chain`` - - Optional - - ``false`` - - - - Check CDC chain between tracking table and source table - * - ``-chunkSize`` - - Optional - - ``0`` - - - - The number of records read at once from the source database - * - ``-columnlist`` - - Optional - - *None* - - ``.txt`` - - The name of the file that contains all column names. Columns must be separated using ``\n`` - * - ``-columns`` - - Optional - - All columns - - - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true - * - ``-config`` - - Optional - - ``/home/username/downloads/config/sqload-jdbc.properties`` - - - - Defines the path to the configuration file you wish to use. This parameter may be defined using only the CLI - * - ``-config_dir`` - - Optional - - ``/home/username/downloads/config`` - - - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error - * - ``-count`` - - Optional - - ``true`` - - - - Defines whether or not table rows will be counted before being loaded into SQreamDB - * - ``-delete`` - - Optional - - ``true`` - - - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows - * - ``-drop`` - - Optional - - ``true`` - - - - - Assuming we're loading into table ``x``: - - * ``true`` essentially allows for the replacement of the existing table with the newly loaded data by triggering the following actions: - - * Creating or replacing a temporary table named ``x_temp`` - * The data you intend to load is inserted into the ``x_temp`` table - * If a table named ``x`` already exists, it will be renamed to ``x_old``. (If ``x`` exists as a view, the view will be dropped) - * The ``x_temp`` table, which now contains your loaded data, is renamed to ``x`` - * Any previously existing table named ``x_old`` is dropped from the database - - * ``false`` (requires using ``- target``) essentially allows for appending data to an existing table without performing any deletion or replacement operations by triggering the following actions: - - * SQLoader first checks if the target table exists and raises an exception if it does not - * If ``truncate`` is set to false, SQLoader appends more data to the existing table without using any staging tables - * If ``truncate`` is set to true, a temporary table, ``x_temp``, is created based on the existing table, but no data is initially loaded. If ``x_temp`` exists, an error is raised since ``CREATE OR REPLACE`` is not used - * Data is loaded into the temporary table - * Target table is renamed to ``x_old`` - * The temporary table ``x_temp`` is renamed to the target table name ``x`` - * ``x_old`` is dropped - * - ``-fetchsize`` - - Optional - - ``100000`` - - - - The number of records to be read at once from source database - * - ``-filter`` - - Optional - - ``1=1`` - - - - Defines whether or not only records with SQL conditions are loaded - * - ``-h, --help`` - - Optional - - *No input* - - - - Displays the help menu and exits - * - ``-limit`` - - Optional - - ``0`` (no limit) - - - - Limits the number of rows to be loaded - * - ``-load_dttm`` - - Optional - - ``true`` - - - - Add an additional ``load_dttm`` column that defines the time and date of loading - * - ``-lock_check`` - - Optional - - ``true`` - - - - Defines whether or not SQLoader will check source table is locked before the loading starts - * - ``-lock_table`` - - Optional - - ``true`` - - - - Defines whether or not SQLoader will lock target table before the loading starts - * - ``-log_dir`` - - Optional - - ``logs`` - - - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file - * - ``-partition`` - - Optional - - *None* - - Partition identifier ``string`` - - Specifies the number of table partitions. If configured, ``-partition`` ensures that data is loaded according to the specified partition. You may configure the ``-thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions - * - ``-rowid`` - - Optional - - ``false`` - - - - Defines whether or not SQLoader will get row IDs from Oracle tables - * - ``-source_db`` - - Optional - - ``ORCL`` - - - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables - * - ``-split`` - - Optional - - *None* - - Column name ``string`` - - Column name for split (required for multi-thread loads) - * - ``-table`` - - Mandatory - - *None* - - Table name ``string`` - - Source table name to load data from - * - ``-target`` - - Optional - - Target table name - - Table name ``string`` - - Target table name to load data into - * - ``-thread`` - - Optional - - ``1`` - - - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``-thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guidelines>` - * - ``-truncate`` - - Optional - - ``false`` - - - - Truncate target table before loading - * - ``-type`` - - Optional - - ``full`` - - - - Defines a loading type that affects the table that is created in SQreamDB. Options are: - - * ``full``: The entire data of the source table is loaded into SQreamDB - - * ``cdc`` (Change Data Capture): Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata - - * ``inc``: Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata - Please note that ``cdc``, and ``inc`` are supported only for Oracle - - * - ``-use_dbms_lob`` - - Optional - - ``true`` - - - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types - * - ``-use_partitions`` - - Optional - - ``true`` - - - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements - -Data Types and Mapping ----------------------- - -SQLoader automatically assigns data types during the data loading process. Nevertheless, you retain the choice to manually specify the preferred data type you want to map to during the loading operation. - -.. contents:: - :local: - :depth: 1 - -Automatic Mapping -^^^^^^^^^^^^^^^^^ - -Oracle -"""""" - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Oracle Type - - SQreamDB Type - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - - ``BIGINT`` - * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - - ``TEXT`` - * - ``DATE``, ``DATETIME`` - - ``DATETIME`` - * - ``TIMESTAMP`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOLEAN`` - - ``BOOL`` - * - ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``CLOB`` - - ``TEXT`` - * - ``BLOB`` - - ``TEXT`` - * - ``RAW`` - - ``TEXT`` - - - -Postgresql -"""""""""" - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Postgresql Type - - SQreamDB Type - * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - - ``TEXT`` - * - ``TEXT`` - - ``TEXT`` - * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT``, ``BOOL`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL``, ``FLOAT4`` - - ``REAL`` - -Teradata -"""""""" - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Teradata Type - - SQreamDB Type - * - ``F`` - - ``DOUBLE`` - * - ``N``, ``D`` - - ``NUMERIC`` - * - ``CO`` - - ``TEXT`` - * - ``BO`` - - ``TEXT`` - * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - - ``TEXT`` - * - ``I``, ``I4``, ``I(4)`` - - ``INT`` - * - ``I2``, ``I(2)`` - - ``SMALLINT`` - * - ``I1``, ``I(1)`` - - ``TINYINT`` - * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - - ``BIGINT`` - * - ``TS``, ``DATETIME`` - - ``DATETIME`` - * - ``DA`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``REAL``, ``DOUBLE`` - - ``DOUBLE`` - -Microsoft SQL Server -"""""""""""""""""""" - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Microsoft SQL Server Type - - SQreamDB Type - * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - - ``TEXT`` - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL`` - - ``REAL`` - * - ``VARBINARY`` - - ``TEXT`` - -SAP HANA -"""""""" - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - SAP HANA Type - - SQreamDB Type - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - - ``BIGINT`` - * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - - ``TEXT`` - * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOLEAN`` - - ``TEXT`` - * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - - ``NUMERIC`` - * - ``DOUBLE``, ``REAL`` - - ``FLOAT`` - * - ``TEXT`` - - ``TEXT`` - * - ``BIGINT`` - - ``BIGINT`` - * - ``INT`` - - ``INT`` - * - ``SMALLINT`` - - ``SMALLINT`` - * - ``TINYINT`` - - ``TINYINT`` - * - ``DATETIME`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOL`` - - ``BOOL`` - * - ``NUMERIC`` - - ``NUMERIC`` - * - ``DOUBLE`` - - ``DOUBLE`` - * - ``FLOAT`` - - ``FLOAT`` - * - ``REAL`` - - ``REAL`` - -Manual Mapping -^^^^^^^^^^^^^^ - -You have the possibility to adjust the SQLoader mapping process according to your specific needs using the ``names`` Method. - -To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. - -In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. - -.. code-block:: json - - { - "oracle": [ - { - "names": ["column1", "column2", "column3"], - "sqream": "bigint", - "java": "int", - "length": false - }, - { - "type": ["bigint","int","smallint","integer"], - "sqream": "bigint", - "java": "int", - "length": false - } - } - ---------------------------------- - -Creating Summary Tables -======================= - -Summary tables are pre-aggregated tables that store summarized or aggregated data, which can help improve query performance and reduce the need for complex calculations during runtime. - -Summary tables are part of the schema within the database catalog. - -Examples --------- - -The following examples use Oracle syntax. - -A Summary Table -^^^^^^^^^^^^^^^ - -.. code-block:: sql - - - CREATE TABLE public.SQLOAD_SUMMARY ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - UPDATED_DTTM_FROM DATE VISIBLE, - UPDATED_DTTM_TO DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE, - LAST_VAL_TS DATE VISIBLE, - START_TIME TIMESTAMP(6) VISIBLE, - FINISH_TIME TIMESTAMP(6) VISIBLE, - ELAPSED_SEC NUMBER VISIBLE, - ROW_COUNT NUMBER VISIBLE, - SQL_FILTER TEXT(200 BYTE) VISIBLE, - PARTITION TEXT(200 BYTE) VISIBLE, - STMT_TYPE TEXT(200 BYTE) VISIBLE, - STATUS TEXT(200 BYTE) VISIBLE, - LOG_FILE TEXT(200 BYTE) VISIBLE, - DB_URL TEXT(200 BYTE) VISIBLE, - PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, - THREAD_COUNT NUMBER VISIBLE DEFAULT 1, - ELAPSED_MS NUMBER VISIBLE DEFAULT 0, - STATUS_CODE NUMBER VISIBLE DEFAULT 0, - ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, - TARGET_DB_URL VARCHAR2(200) DEFAULT NULL, - SQLOADER_VERSION VARCHAR2(20) DEFAULT NULL, - HOST VARCHAR2(200) DEFAULT NULL - ); - - -Change Data Capture Summary Tables ----------------------------------- - -Change Data Capture (CDC) tables are supported only for Oracle. - -.. code-block:: sql - - CREATE TABLE public.CDC_TABLES ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, - INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, - INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_INTERVAL NUMBER(22,0) VISIBLE, - IS_ACTIVE NUMBER VISIBLE DEFAULT 0, - STATUS_LOAD NUMBER VISIBLE DEFAULT 0, - INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 - ); - - CREATE TABLE public.CDC_TRACKING ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LAST_UPDATED_DTTM DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - LAST_VAL_DT DATE VISIBLE - ); - - CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, - COLUMN_NAME TEXT(200 BYTE) VISIBLE, - IS_NULLABLE NUMBER VISIBLE DEFAULT 0 - ); - -------------------------------------------------------- - -CLI Examples -============ - -Loading data into a CDC table using the ``type`` and ``limit`` parameters: - -.. code-block:: console - - java -jar sqloader.jar -table <source_table_name> -type cdc -limit 100 - -Loading data into a table using your own configuration file (this will override the default configuration file): - -.. code-block:: console - - java -jar sqloader.jar -config path/to/your/config/file - -Loading data into a table using a custom configuration file: - -.. code-block:: console - - java -jar -config MyConfigFile.properties -table <source_table_name> -type cdc -target <target_table_name> -drop true -lock_check false - -Loading data into a table using a the ``filter`` parameter: - -.. code-block:: console - - java -jar sqloader.jar -table <source_table_name> -filter column_name>50 - - - diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 3c16ff6d3..d942d672e 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -4,7 +4,7 @@ SQLoader ******** -SQLoader enables you to load data into SQreamDB from other DBMS and DBaaS. You may use it as a :ref:`process<ingesting_from_databases>` or as a :ref:`service<sqloader_as_a_service>`. +SQLoader enables you to load data into SQreamDB from other DBMS and DBaaS. For loading data from Oracle, check out this :ref:`preparing_oracle_for_data_migration` @@ -14,5 +14,4 @@ For loading data from Oracle, check out this :ref:`preparing_oracle_for_data_mig :hidden: sqloader_as_a_service - ingesting_from_databases preparing_oracle_for_data_migration \ No newline at end of file diff --git a/index.rst b/index.rst index bc01767ec..858a96f98 100644 --- a/index.rst +++ b/index.rst @@ -33,7 +33,7 @@ SQreamDB is a columnar analytic SQL database management system. SQreamDB support +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`parquet` | :ref:`orc` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`json` | :ref:`ingesting_from_databases` | | +| :ref:`json` | :ref:`sqloader_as_a_service` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | **Connecting to SQreamDB** | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ From 8b99e9c83f90206484d0302bc741eaad0ab73c34 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:06:10 +0300 Subject: [PATCH 1615/1892] Update index.rst --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 858a96f98..67976dc04 100644 --- a/index.rst +++ b/index.rst @@ -33,7 +33,7 @@ SQreamDB is a columnar analytic SQL database management system. SQreamDB support +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`parquet` | :ref:`orc` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`json` | :ref:`sqloader_as_a_service` | | +| :ref:`json` | :ref:`sqloader_as_a_service` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | **Connecting to SQreamDB** | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ From 4fea4e055e222f607413596a4a4403d16bbc32ee Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:18:22 +0300 Subject: [PATCH 1616/1892] Update index.rst --- index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.rst b/index.rst index 67976dc04..7d41b4984 100644 --- a/index.rst +++ b/index.rst @@ -33,7 +33,7 @@ SQreamDB is a columnar analytic SQL database management system. SQreamDB support +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`parquet` | :ref:`orc` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -| :ref:`json` | :ref:`sqloader_as_a_service` | | +| :ref:`json` | :ref:`sqloader_as_a_service` | | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | **Connecting to SQreamDB** | +--------------------------+----------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ From 5a3875ff499dc5d5995afe6d9070cd92a65adebc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Sep 2024 16:36:10 +0300 Subject: [PATCH 1617/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index d942d672e..2c778fca2 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -4,7 +4,7 @@ SQLoader ******** -SQLoader enables you to load data into SQreamDB from other DBMS and DBaaS. +:ref:`sqloader_as_a_service` enables you to load data into SQreamDB from other DBMS and DBaaS. For loading data from Oracle, check out this :ref:`preparing_oracle_for_data_migration` From f7528a7f19ff75fbbf79fb6776dd13c5e41b07e8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:13:03 +0300 Subject: [PATCH 1618/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 3a1832c59..c80b1cab6 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -175,7 +175,9 @@ You can download the :download:`JDBC Application Sample File <sample.java>` belo Prepared Statements ==================== -Prepared statements, also known as parameterized queries, are a feature of JDBC that enable the use of parameters to optimize query execution, enhance security, and enable query template reuse with different parameter values in Java applications. +Prepared statements, also known as parameterized queries, שre a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +In SQream, we use ? as a placeholder for the relevant value in parameterized queries. +Prepared statements ``INSERT``, ``SELECT``, ``UPDATE`` and ``DELETE`` Prepared Statement Sample --------------------------- @@ -188,3 +190,8 @@ You may download the :download:`Prepared statement <samplepreparedstatement.java :language: java :caption: Prepared Statement Sample :linenos: + +Prepared Statement Limitations +--------------------------- +* Prepared Statement do not support the use of :ref:`_keywords_and_identifiers` and input parameters +* ``SELECT`` statements require preparation on each execution (see above exmaple) \ No newline at end of file From 13a57649edc2b8dd2a866b1af671823fa75e1dcc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:43:11 +0300 Subject: [PATCH 1619/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index c80b1cab6..5b2354225 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -175,8 +175,8 @@ You can download the :download:`JDBC Application Sample File <sample.java>` belo Prepared Statements ==================== -Prepared statements, also known as parameterized queries, שre a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. -In SQream, we use ? as a placeholder for the relevant value in parameterized queries. +Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +In SQream, we use ``?`` as a placeholder for the relevant value in parameterized queries. Prepared statements ``INSERT``, ``SELECT``, ``UPDATE`` and ``DELETE`` Prepared Statement Sample @@ -193,5 +193,5 @@ You may download the :download:`Prepared statement <samplepreparedstatement.java Prepared Statement Limitations --------------------------- -* Prepared Statement do not support the use of :ref:`_keywords_and_identifiers` and input parameters -* ``SELECT`` statements require preparation on each execution (see above exmaple) \ No newline at end of file +* Prepared Statement do not support the use of :ref:`keywords_and_identifiers` as input parameters +* ``SELECT``, ``UPDATE`` and ``DELETE`` statements require the use of ``add_batch`` prior to each execution. \ No newline at end of file From ab86249921d49bd9ca0a65eacdb1f4f1f13372ca Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:55:42 +0300 Subject: [PATCH 1620/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 591ae8544..949fab95c 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -466,4 +466,16 @@ This section shows how to use the ORM to create and populate tables from Python .. code-block:: python result = session.execute(ins) + +Prepared Statements +==================== + +Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +In SQream, we use ``?`` as a placeholder for the relevant value in parameterized queries. +Prepared statements ``INSERT``, ``SELECT``, ``UPDATE`` and ``DELETE`` + +Prepared Statement Limitations +--------------------------- +* Prepared Statement do not support the use of :ref:`keywords_and_identifiers` as input parameters. + From fb2def6d4266e3b3b6fef771f199d1e09032a9bb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 10:56:10 +0300 Subject: [PATCH 1621/1892] Update index.rst --- connecting_to_sqream/client_drivers/jdbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index 5b2354225..ccc821476 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -193,5 +193,5 @@ You may download the :download:`Prepared statement <samplepreparedstatement.java Prepared Statement Limitations --------------------------- -* Prepared Statement do not support the use of :ref:`keywords_and_identifiers` as input parameters +* Prepared Statement do not support the use of :ref:`keywords_and_identifiers` as input parameters. * ``SELECT``, ``UPDATE`` and ``DELETE`` statements require the use of ``add_batch`` prior to each execution. \ No newline at end of file From c7a080ac936e5d0dd93de83b75ecf611e4076a84 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:55:13 +0300 Subject: [PATCH 1622/1892] Update window_functions.rst --- reference/sql/sql_syntax/window_functions.rst | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/reference/sql/sql_syntax/window_functions.rst b/reference/sql/sql_syntax/window_functions.rst index 6b428d98f..e2f66e829 100644 --- a/reference/sql/sql_syntax/window_functions.rst +++ b/reference/sql/sql_syntax/window_functions.rst @@ -330,3 +330,35 @@ This example calculates the salary between two players, starting from the highes Dwyane Wade | 20000000 | 19689000 | 311000 Brook Lopez | 19689000 | 19689000 | 0 DeAndre Jordan | 19689000 | 19689000 | 0 + +Window funtion alias +======================= + + +The window funtion alias allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. + +.. code-block:: psql + + t=> SELECT SUM("Salary") OVER w + WINDOW w AS + FROM nba + (PARTITION BY "Team" ORDER BY "Age"); + sum + --------- + 1763400 + 5540289 + 5540289 + 5540289 + 5540289 + 7540289 + 18873622 + 18873622 + 30873622 + 60301531 + 60301531 + 60301531 + 64301531 + 72902950 + 72902950 + [...] + \ No newline at end of file From e74fa556d6d76c08dee06edbea51e31755b4a09a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 13:02:42 +0300 Subject: [PATCH 1623/1892] Update 4.8.rst --- releases/4.8.rst | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index b1fbc306e..7fe458c11 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -4,7 +4,7 @@ Release Notes 4.8 ***************** -The 4.8 release notes were released on March XX, 2024 +The 4.8 release notes were released on October 1st, 2024 .. contents:: :local: @@ -90,22 +90,7 @@ Version 4.8 resolved Issues +==============+=====================================================================================================================+ | SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16038 | Fixed ``CREATE TABLE.. LIKE`` permission heritage issue | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16937 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17149 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17270 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17457 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17502 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17520 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17944 | | -+--------------+---------------------------------------------------------------------------------------------------------------------+ + Deprecations @@ -148,12 +133,6 @@ Upgrading to Version 4.8 ./upgrade_storage <levelDB path> -7. Version 4.4 introduces a service permission feature that enables superusers to grant and revoke role access to services. However, when upgrading from version 4.2 or earlier to version 4.4 or later, this feature initializes access to services, causing existing roles to lose their access to services. - -There are two methods of granting back access to services: - - * Grant access to all services for all roles using the :ref:`grant_usage_on_service_to_all_roles` utility function - * Selectively grant or revoke access to services by following the :ref:`access permission guide<access_control_permissions>` .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. From ab1c6845cd7f060f1245d975120a45962a0e1353 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:10:37 +0300 Subject: [PATCH 1624/1892] Update 4.8.rst --- releases/4.8.rst | 37 ++----------------------------------- 1 file changed, 2 insertions(+), 35 deletions(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index 7fe458c11..ab7a6470e 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -37,43 +37,10 @@ New Features and Enhancements -► ALL log files should reside under the same folder +► Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and JDBC client drivers. -► You now have the option to choose the location for your ``metadata_server``, ``server_picker``, and Worker log files. In previous SQreamDB versions, the location of your log files was predetermined and hard-coded. -:ref:`metadata_server_cli_reference` - -* Using the ``metadata_server_config.json`` file: - - .. code-block:: json - - { - "logPath": "<home/logs/my_logs>" - } - -* Using the CLI: - - .. code-block:: console - - ./metadata_server --log_path=<home/logs/my_logs> - -:ref:`server_picker_cli_reference` - - Using the CLI: - - .. code-block:: console - - ./server_picker --log_path=<home/logs/my_logs> - -:ref:`Worker<current_method_modification_methods>` - - Using the ``sqream_config_legacy.json``: - - .. code-block:: json - - { - "DefaultPathToLogs": "<home/logs/my_logs>" - } From a5b696abebb95f02ad38bbe17bacec819097c9b3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:21:18 +0300 Subject: [PATCH 1625/1892] 4.8 RN --- releases/4.0_index.rst | 3 ++- releases/4.8.rst | 2 +- releases/index.rst | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 2f4213ce0..aeb64b861 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -19,4 +19,5 @@ 4.4 4.5 4.6 - 4.7 \ No newline at end of file + 4.7 + 4.8 \ No newline at end of file diff --git a/releases/4.8.rst b/releases/4.8.rst index ab7a6470e..9f46e6881 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -38,7 +38,7 @@ New Features and Enhancements ► Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. -These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and JDBC client drivers. +These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. diff --git a/releases/index.rst b/releases/index.rst index dc2d905e0..b15eec70f 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,8 @@ Release Notes ************* +:ref:`Version 4.8 - October 01, 2024<4.8>` + :ref:`Version 4.7 - September 01, 2024<4.7>` * :ref:`AWS private cloud deployment<sqreamdb_on_aws>` is now available for SQreamDB on AWS Marketplace. From eedce8d90ea1c9e5cd5145d31897fd1a74369c4a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:27:24 +0300 Subject: [PATCH 1626/1892] RN index --- releases/4.0_index.rst | 7 ++----- releases/index.rst | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index aeb64b861..c43e090a0 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -1,7 +1,7 @@ -.. _4.0_index: +.. _4.x_index: ***************** -4.0 Release Notes +4.x Release Notes ***************** .. contents:: @@ -12,9 +12,6 @@ :maxdepth: 1 :glob: - 4.0 - 4.1 - 4.2 4.3 4.4 4.5 diff --git a/releases/index.rst b/releases/index.rst index b15eec70f..a1bc96913 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -64,7 +64,7 @@ Release Notes :glob: :hidden: - 4.0_index + 4.x_index 2022.1_index From 353fc2c2f91bb51498a129532fe4a473612146e5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:35:56 +0300 Subject: [PATCH 1627/1892] Update index.rst --- releases/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/index.rst b/releases/index.rst index a1bc96913..b15eec70f 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -64,7 +64,7 @@ Release Notes :glob: :hidden: - 4.x_index + 4.0_index 2022.1_index From 29db4c626405e70c0061a6d8c6c9abc23dd590cc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 14:54:38 +0300 Subject: [PATCH 1628/1892] Update 4.8.rst --- releases/4.8.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index 9f46e6881..3785cce9c 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -40,8 +40,11 @@ New Features and Enhancements ► Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. +► `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. +► `Window funtion alias <../reference/sql/sql_syntax/window_functions.html#window-funtion-alias>`_ allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. +► `CONCAT <../reference/sql/sql_functions/scalar_functions/string/concat_function.html#concat-function>`_ function concatenates one or more strings, or concatenates one or more binary values. Known Issues @@ -55,7 +58,9 @@ Version 4.8 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-15691 | Fixed ``TEXT`` casting into ``DOUBLE`` and ``NUMERIC`` issue when using scientific notation | +| SQ-12365 | SQream CLI - Comment is not ignored as expected | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17520 | SQLoader - DELETE issue following CDC process | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 563b798f3e3adcfe3f17ad39c69ae248e75bf82b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:26:18 +0300 Subject: [PATCH 1629/1892] Update index.rst --- releases/index.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/releases/index.rst b/releases/index.rst index b15eec70f..68e8438c4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -6,6 +6,12 @@ Release Notes :ref:`Version 4.8 - October 01, 2024<4.8>` +* Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. +* `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. +* `Window funtion alias <../reference/sql/sql_syntax/window_functions.html#window-funtion-alias>`_ allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. +* `CONCAT <../reference/sql/sql_functions/scalar_functions/string/concat_function.html#concat-function>`_ function concatenates one or more strings, or concatenates one or more binary values. + :ref:`Version 4.7 - September 01, 2024<4.7>` * :ref:`AWS private cloud deployment<sqreamdb_on_aws>` is now available for SQreamDB on AWS Marketplace. From d2c4abbb6d68cdfd0b9919c2495581238e82ec2d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 30 Sep 2024 15:36:44 +0300 Subject: [PATCH 1630/1892] Update index.rst --- releases/index.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 68e8438c4..ada62e491 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -6,9 +6,8 @@ Release Notes :ref:`Version 4.8 - October 01, 2024<4.8>` -* Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. -These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. -* `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. +* Prepared statements are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. +* `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ and `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_. * `Window funtion alias <../reference/sql/sql_syntax/window_functions.html#window-funtion-alias>`_ allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. * `CONCAT <../reference/sql/sql_functions/scalar_functions/string/concat_function.html#concat-function>`_ function concatenates one or more strings, or concatenates one or more binary values. From 5be2b4ad74ed9652712195023c02f481198bbe1d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:37:39 +0300 Subject: [PATCH 1631/1892] Update 4.8.rst --- releases/4.8.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index 3785cce9c..d7ba9f1b9 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -22,14 +22,14 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.3.1 | +| Driver compatibility | * JDBC 5.4.0 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | -| | * Pysqream 5.1.0 (compatible with v4.5.13 or later) | +| | * Pysqream 5.3.0 | +| | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | -| | * SQLoader As A Service 8.1 (compatible with v4.6.1 or later) | -| | * SQLoader As A Process 7.13 (compatible with v4.5.13 or later) | +| | * SQLoader As A Service 8.2 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From ac99fa5dafa61013c0f229c63ab8178354a22734 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 6 Oct 2024 12:13:10 +0300 Subject: [PATCH 1632/1892] Update 4.8 --- releases/4.8.rst | 2 +- releases/index.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index d7ba9f1b9..be1eaf5a9 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -4,7 +4,7 @@ Release Notes 4.8 ***************** -The 4.8 release notes were released on October 1st, 2024 +The 4.8 release notes were released on October 6th, 2024 .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index ada62e491..357d0cda2 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.8 - October 01, 2024<4.8>` +:ref:`Version 4.8 - October 06, 2024<4.8>` * Prepared statements are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. * `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ and `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_. From 1ee099fa1fa4e1b79afe9b74bd2a67fd791ad5a7 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 6 Oct 2024 13:17:37 +0300 Subject: [PATCH 1633/1892] Update pivot_unpivot.rst --- reference/sql/sql_syntax/pivot_unpivot.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_syntax/pivot_unpivot.rst b/reference/sql/sql_syntax/pivot_unpivot.rst index 25fc1a3bc..678e8017b 100644 --- a/reference/sql/sql_syntax/pivot_unpivot.rst +++ b/reference/sql/sql_syntax/pivot_unpivot.rst @@ -44,7 +44,7 @@ Syntax Limitations ================= -The number of resulting columns for ``PIVOT`` and the number of input columns for ``UNPIVOT`` is limited to 10,000. +The number of resulting columns for ``PIVOT`` and the number of input columns for ``UNPIVOT`` is limited to 8,000. From 36287751e2a72758c8f269a52636d01edace4361 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 8 Oct 2024 10:55:15 +0300 Subject: [PATCH 1634/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 44fcb1414..44069a834 100644 --- a/conf.py +++ b/conf.py @@ -32,7 +32,7 @@ # The full version, including alpha/beta/rc tags -release = '4.8' +release = '4.9' # -- General configuration --------------------------------------------------- From b95d2d6658dcc170332b87376666c6ca6ff01136 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:39:44 +0300 Subject: [PATCH 1635/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index a9a74fe4d..7a242a775 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -29,7 +29,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.3.1 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.3.1.jar>`_ + - `sqream-jdbc 5.4.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.4.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From 572d5608af7b32c74d786aa43dcbdffbeb8540d5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 10 Oct 2024 10:11:02 +0300 Subject: [PATCH 1636/1892] up --- connecting_to_sqream/client_drivers/index.rst | 2 +- reference/sql/sql_syntax/pivot_unpivot.rst | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 7a242a775..b752a4dd9 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -49,7 +49,7 @@ Client Driver Downloads - - All * - **Python** - - `pysqream v5.2.0 <https://github.com/SQream/pysqream/releases>`_ + - `pysqream v5.3.0 <https://github.com/SQream/pysqream/releases>`_ - :ref:`pysqream` - Recommended installation via ``pip`` - All diff --git a/reference/sql/sql_syntax/pivot_unpivot.rst b/reference/sql/sql_syntax/pivot_unpivot.rst index 678e8017b..a3949c0ec 100644 --- a/reference/sql/sql_syntax/pivot_unpivot.rst +++ b/reference/sql/sql_syntax/pivot_unpivot.rst @@ -44,7 +44,8 @@ Syntax Limitations ================= -The number of resulting columns for ``PIVOT`` and the number of input columns for ``UNPIVOT`` is limited to 8,000. +* The number of resulting columns for ``PIVOT`` is limited to 8,000. +* The number of resulting columns for ``UNPIVOT`` is limited to 2,000. From d56ed3e08b438294e58fb18364e307ebbcdf524b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 14 Oct 2024 14:54:32 +0300 Subject: [PATCH 1637/1892] Update 4.8.rst --- releases/4.8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.8.rst b/releases/4.8.rst index be1eaf5a9..c5fd6af43 100644 --- a/releases/4.8.rst +++ b/releases/4.8.rst @@ -18,7 +18,7 @@ Compatibility Matrix +=========================+========================================================================+ | Supported OS | RHEL 8.x | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version 11.x | +| supported Nvidia driver | CUDA version 12.x | +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ From 80d0a975e0e6f497b3a2a631888a50809bc182a2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:08:33 +0300 Subject: [PATCH 1638/1892] encryption --- feature_guides/data_encryption.rst | 16 +++++++++++ feature_guides/data_encryption_methods.rst | 17 +++++++++++ feature_guides/data_encryption_overview.rst | 28 ++++++++++++++++++ feature_guides/data_encryption_syntax.rst | 32 +++++++++++++++++++++ feature_guides/data_encryption_types.rst | 14 +++++++++ 5 files changed, 107 insertions(+) create mode 100644 feature_guides/data_encryption.rst create mode 100644 feature_guides/data_encryption_methods.rst create mode 100644 feature_guides/data_encryption_overview.rst create mode 100644 feature_guides/data_encryption_syntax.rst create mode 100644 feature_guides/data_encryption_types.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst new file mode 100644 index 000000000..c38d126fc --- /dev/null +++ b/feature_guides/data_encryption.rst @@ -0,0 +1,16 @@ +.. _data_encryption: + +*********************** +Data Encryption +*********************** +The **Data Encryption** page describes the following: + + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + data_encryption_overview + data_encryption_methods + data_encryption_types + data_encryption_syntax \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst new file mode 100644 index 000000000..250ca06de --- /dev/null +++ b/feature_guides/data_encryption_methods.rst @@ -0,0 +1,17 @@ +.. _data_encryption_methods: + +*********************** +Encryption Methods +*********************** +Data exists in one of following states and determines the encryption method: + + +Encrypting Data in Transit +---------------- +**Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. + +For more information, see `Use TLS/SSL When Possible <../operational_guides/security.html#use-tls-ssl-when-possible>`_. + +Encrypting Data at Rest +---------------- +**Data at rest** refers to data stored on your hard drive or on the cloud. Because this data can be potentially intercepted **physically**, it requires a form of encryption that protects your data wherever you store it. SQream facilitates encryption by letting you encrypt any column. \ No newline at end of file diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst new file mode 100644 index 000000000..ca953ce2a --- /dev/null +++ b/feature_guides/data_encryption_overview.rst @@ -0,0 +1,28 @@ +.. _data_encryption_overview: + +*********************** +Overview +*********************** +**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. + +Encryption can be used for the following: + +* Creating tables with up to three encrypted columns. + + :: + +* Joining encrypted columns with other tables. + + :: + +* Selecting data from an encrypted column. + +.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. + +For more information on the encryption syntax, see :ref:`data_encryption_syntax`. + +For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst new file mode 100644 index 000000000..56934378e --- /dev/null +++ b/feature_guides/data_encryption_syntax.rst @@ -0,0 +1,32 @@ +.. _data_encryption_syntax: + +*********************** +Syntax +*********************** +The following is the syntax for encrypting a new table: + +.. code-block:: console + + CREATE TABLE <table name> ( + <column_name> NOT NULL ENCRYPT, + <column_name> <type_name> ENCRYPT, + <column_name> <type_name>, + <column_name> <type_name> ENCRYPT); + +The following is an example of encrypting a new table: + +.. code-block:: console + + CREATE TABLE client_name ( + id BIGINT NOT NULL ENCRYPT, + first_name TEXT ENCRYPT, + last_name TEXT, + salary INT ENCRYPT); + +.. note:: Because encryption is not associated with any role, users with **Read** or **Insert** permissions can read tables containing encrypted data. + +You cannot encrypt more than three columns. Attempting to encrypt more than three columns displays the following error message: + +.. code-block:: console + + Error preparing statement: Cannot create a table with more than three encrypted columns. diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst new file mode 100644 index 000000000..ad6d96dc3 --- /dev/null +++ b/feature_guides/data_encryption_types.rst @@ -0,0 +1,14 @@ +.. _data_encryption_types: + +*********************** +Data Types +*********************** +Typically speaking, sensitive pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +SQream's data encryption feature supports encrypting column-based data belonging to the following data types: + +* INT +* BIGINT +* TEXT + +For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file From e58cf75500ae8fb02f8d7250baaebc3261a06d25 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 10:45:42 +0300 Subject: [PATCH 1639/1892] encryption2 --- feature_guides/data_encryption_overview.rst | 14 ++------------ feature_guides/data_encryption_syntax.rst | 13 +++++++------ feature_guides/index.rst | 1 + 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst index ca953ce2a..3df4820a9 100644 --- a/feature_guides/data_encryption_overview.rst +++ b/feature_guides/data_encryption_overview.rst @@ -9,19 +9,9 @@ Users encrypt their data on a column basis by specifying ``column_name`` in the The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. -Encryption can be used for the following: +SQream enables customers to implement a-Symmetric Encryption solution using Secret Keys that they provide and manage themselves. +The chosen encryption algorithm is AES-256, known for its strength and security. It is crucial to ensure that the Secret Key length is precisely 256 bits or 32 bytes. -* Creating tables with up to three encrypted columns. - - :: - -* Joining encrypted columns with other tables. - - :: - -* Selecting data from an encrypted column. - -.. warning:: The ``SELECT`` statement decrypts information by default. When executing ``CREATE TABLE AS SELECT``, encrypted information will appear as clear text in the newly created table. For more information on the encryption syntax, see :ref:`data_encryption_syntax`. diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 56934378e..d862a6423 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -5,7 +5,7 @@ Syntax *********************** The following is the syntax for encrypting a new table: -.. code-block:: console +.. code-block:: psql CREATE TABLE <table name> ( <column_name> NOT NULL ENCRYPT, @@ -15,7 +15,7 @@ The following is the syntax for encrypting a new table: The following is an example of encrypting a new table: -.. code-block:: console +.. code-block:: psql CREATE TABLE client_name ( id BIGINT NOT NULL ENCRYPT, @@ -23,10 +23,11 @@ The following is an example of encrypting a new table: last_name TEXT, salary INT ENCRYPT); -.. note:: Because encryption is not associated with any role, users with **Read** or **Insert** permissions can read tables containing encrypted data. +.. note:: xxxxxxxxxxxx. -You cannot encrypt more than three columns. Attempting to encrypt more than three columns displays the following error message: -.. code-block:: console - Error preparing statement: Cannot create a table with more than three encrypted columns. +*********************** +Permissions +*********************** +Because the Data Encryption feature does not require a role, users with **Read** and **Insert** permissions can read tables containing encrypted data. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 672d7d423..9d29ab3f1 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -15,3 +15,4 @@ The **Feature Guides** section describes background processes that SQreamDB uses python_functions workload_manager concurrency_and_locks + data_encryption From be65b090081f7b75fbda5c0d09981ebf0af76fb9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:06:20 +0300 Subject: [PATCH 1640/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 89 +++++++++++++++++++++-- 1 file changed, 83 insertions(+), 6 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index d862a6423..16afceaa2 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -8,10 +8,17 @@ The following is the syntax for encrypting a new table: .. code-block:: psql CREATE TABLE <table name> ( - <column_name> NOT NULL ENCRYPT, - <column_name> <type_name> ENCRYPT, - <column_name> <type_name>, - <column_name> <type_name> ENCRYPT); + <column_name> <data_type> ENCRYPT, + <column_name> <data_type> NULL ENCRYPT, + <column_name> <data_type> NOT NULL ENCRYPT + ); + +The following is the syntax for adding an encrypted column to an existing table: + +.. code-block:: psql + + ALTER TABLE client_name + ADD COLUMN rank TEXT ENCRYPT; The following is an example of encrypting a new table: @@ -22,8 +29,78 @@ The following is an example of encrypting a new table: first_name TEXT ENCRYPT, last_name TEXT, salary INT ENCRYPT); - -.. note:: xxxxxxxxxxxx. + + +Encryption / Decryption methods: + +.. code-block:: psql + +ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + +.. code-block:: psql + +DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + +The following is an example of inserting encrypt player salary (``INT`` data type) + +.. code-block:: psql + +INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) +VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); + +Similar example using ``COPY FROM'' + +.. code-block:: psql + +COPY NBA +( +player_name, team_name, jersey_number, position, age, height, weight, college, +ENCRYPT (salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') +) +FROM WRAPPER csv_fdw +OPTIONS +(location = '/tmp/source_file.csv', quote='@'); + +Example of querying the encrypted data: + +.. code-block:: psql + +SELECT player_name, salary FROM NBA +WHERE player_name ='Jayson Christopher Tatum'; + +player_name |salary | +------------------------+----------+ +Jayson Christopher Tatum|-561885196| + +Example of querying the encrypted data using ``WHERE`` clause on an encrypted column: + +.. code-block:: psql + +SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') +FROM NBA +WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; + +Example of ``COPY TO`` using ``DECRYPT``: + +.. code-block:: psql + +COPY + (SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + FROM NBA + WHERE player_name ='Jayson Christopher Tatum') +TO WRAPPER parquet_fdw +OPTIONS (LOCATION = '/tmp/file.parquet'); + + +*********************** +Limitations +*********************** +* The following functionality is not supported by the encryption feature: ``Catalog queries``, ``Utility commands``, ``Foreign Tables``, ``Create AS SELECT``. +* A single encryption key must be used per column - using a different key would result in an error. +* Compression of encrypted columns is limited to the following types: ``Flat``, ``LZ4``, ``PD4``, ``DICT``, ``RLE``. +* It is crucial to use a single encryption key per column to avoid potential data corruption. Responsibility for providing and managing the encryption key lies with the customer, as the key is utilized with the DECRYPT function. +* This feature is not backward compatible with previous versions of SQreamDB. +* The encryption feature affect performance and compression. From d4d63436042f42388b698b6ede5265d7f98ac848 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:16:16 +0300 Subject: [PATCH 1641/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 16afceaa2..40f9b23a4 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -31,16 +31,19 @@ The following is an example of encrypting a new table: salary INT ENCRYPT); -Encryption / Decryption methods: +Encryption methods syntax: .. code-block:: psql - ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + +Decryption method syntax: + .. code-block:: psql DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + The following is an example of inserting encrypt player salary (``INT`` data type) .. code-block:: psql From 67e22703a316a3c9968c6ef39aa3a291543da1ee Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:25:05 +0300 Subject: [PATCH 1642/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 40f9b23a4..040d01bf1 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -33,13 +33,13 @@ The following is an example of encrypting a new table: Encryption methods syntax: -.. code-block:: psql +.. code-block:: bash ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) Decryption method syntax: -.. code-block:: psql +.. code-block:: bash DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) From 1055c34151a3cd5d95340103e4f64269157540b6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:34:15 +0300 Subject: [PATCH 1643/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 40 +++++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 040d01bf1..c92761c9d 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -3,7 +3,7 @@ *********************** Syntax *********************** -The following is the syntax for encrypting a new table: +The following is the syntax for encrypting a new table .. code-block:: psql @@ -13,36 +13,40 @@ The following is the syntax for encrypting a new table: <column_name> <data_type> NOT NULL ENCRYPT ); -The following is the syntax for adding an encrypted column to an existing table: +The following is the syntax for adding an encrypted column to an existing table .. code-block:: psql ALTER TABLE client_name ADD COLUMN rank TEXT ENCRYPT; -The following is an example of encrypting a new table: - -.. code-block:: psql - - CREATE TABLE client_name ( - id BIGINT NOT NULL ENCRYPT, - first_name TEXT ENCRYPT, - last_name TEXT, - salary INT ENCRYPT); - -Encryption methods syntax: +Encryption methods syntax + +.. code-block:: console -.. code-block:: bash ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) Decryption method syntax: -.. code-block:: bash +.. code-block:: console DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) +*********************** +Examples +*********************** + +The following is an example of encrypting a new table + +.. code-block:: psql + + CREATE TABLE client_name ( + id BIGINT NOT NULL ENCRYPT, + first_name TEXT ENCRYPT, + last_name TEXT, + salary INT ENCRYPT); The following is an example of inserting encrypt player salary (``INT`` data type) @@ -64,7 +68,7 @@ FROM WRAPPER csv_fdw OPTIONS (location = '/tmp/source_file.csv', quote='@'); -Example of querying the encrypted data: +Example of querying the encrypted data .. code-block:: psql @@ -75,7 +79,7 @@ player_name |salary | ------------------------+----------+ Jayson Christopher Tatum|-561885196| -Example of querying the encrypted data using ``WHERE`` clause on an encrypted column: +Example of querying the encrypted data using ``WHERE`` clause on an encrypted column .. code-block:: psql @@ -83,7 +87,7 @@ SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366a FROM NBA WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; -Example of ``COPY TO`` using ``DECRYPT``: +Example of ``COPY TO`` using ``DECRYPT`` .. code-block:: psql From 976b57e578cac8f643259a7d18c2b909ec5830c3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:41:28 +0300 Subject: [PATCH 1644/1892] encryption 3 --- feature_guides/data_encryption_syntax.rst | 8 ++++---- feature_guides/data_encryption_types.rst | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index c92761c9d..52ad50db9 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -23,16 +23,16 @@ The following is the syntax for adding an encrypted column to an existing table Encryption methods syntax -.. code-block:: console +.. code-block:: psql -ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) Decryption method syntax: -.. code-block:: console +.. code-block:: psql -DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) *********************** Examples diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst index ad6d96dc3..a42d22da9 100644 --- a/feature_guides/data_encryption_types.rst +++ b/feature_guides/data_encryption_types.rst @@ -7,8 +7,8 @@ Typically speaking, sensitive pertains to **PII (Personally Identifiable Informa SQream's data encryption feature supports encrypting column-based data belonging to the following data types: -* INT -* BIGINT -* TEXT +* ``INT`` +* ``BIGINT`` +* ``TEXT`` For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file From d3edb26f6d6f10281a9e6e6d515919121ba9d8d0 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:47:49 +0300 Subject: [PATCH 1645/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 67 +++++++++++------------ 1 file changed, 33 insertions(+), 34 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 52ad50db9..224103d14 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -3,7 +3,7 @@ *********************** Syntax *********************** -The following is the syntax for encrypting a new table +Encrypting columns in a new table .. code-block:: psql @@ -13,22 +13,21 @@ The following is the syntax for encrypting a new table <column_name> <data_type> NOT NULL ENCRYPT ); -The following is the syntax for adding an encrypted column to an existing table +Adding an encrypted column to an existing table .. code-block:: psql - ALTER TABLE client_name - ADD COLUMN rank TEXT ENCRYPT; + ALTER TABLE <table_name> ADD COLUMN <column_name> <data_type> ENCRYPT; -Encryption methods syntax +Encryption methods .. code-block:: psql ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) -Decryption method syntax: +Decryption method .. code-block:: psql @@ -38,7 +37,7 @@ Decryption method syntax: Examples *********************** -The following is an example of encrypting a new table +Encrypting a new table .. code-block:: psql @@ -48,55 +47,55 @@ The following is an example of encrypting a new table last_name TEXT, salary INT ENCRYPT); -The following is an example of inserting encrypt player salary (``INT`` data type) +Inserting encrypt player salary (``INT`` data type) .. code-block:: psql -INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) -VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); + INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) + VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); Similar example using ``COPY FROM'' .. code-block:: psql -COPY NBA -( -player_name, team_name, jersey_number, position, age, height, weight, college, -ENCRYPT (salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') -) -FROM WRAPPER csv_fdw -OPTIONS -(location = '/tmp/source_file.csv', quote='@'); + COPY NBA + ( + player_name, team_name, jersey_number, position, age, height, weight, college, + ENCRYPT (salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + ) + FROM WRAPPER csv_fdw + OPTIONS + (location = '/tmp/source_file.csv', quote='@'); -Example of querying the encrypted data +Query the encrypted data .. code-block:: psql -SELECT player_name, salary FROM NBA -WHERE player_name ='Jayson Christopher Tatum'; + SELECT player_name, salary FROM NBA + WHERE player_name ='Jayson Christopher Tatum'; -player_name |salary | -------------------------+----------+ -Jayson Christopher Tatum|-561885196| + player_name |salary | + ------------------------+----------+ + Jayson Christopher Tatum|-561885196| -Example of querying the encrypted data using ``WHERE`` clause on an encrypted column +Query the encrypted data using ``WHERE`` clause on an encrypted column .. code-block:: psql -SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') -FROM NBA -WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; + SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + FROM NBA + WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; Example of ``COPY TO`` using ``DECRYPT`` .. code-block:: psql -COPY - (SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') - FROM NBA - WHERE player_name ='Jayson Christopher Tatum') -TO WRAPPER parquet_fdw -OPTIONS (LOCATION = '/tmp/file.parquet'); + COPY + (SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + FROM NBA + WHERE player_name ='Jayson Christopher Tatum') + TO WRAPPER parquet_fdw + OPTIONS (LOCATION = '/tmp/file.parquet'); *********************** From 11288cc472e596404183210a35abe12778f2700e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 11:53:48 +0300 Subject: [PATCH 1646/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 224103d14..d4587f781 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -104,7 +104,6 @@ Limitations * The following functionality is not supported by the encryption feature: ``Catalog queries``, ``Utility commands``, ``Foreign Tables``, ``Create AS SELECT``. * A single encryption key must be used per column - using a different key would result in an error. * Compression of encrypted columns is limited to the following types: ``Flat``, ``LZ4``, ``PD4``, ``DICT``, ``RLE``. -* It is crucial to use a single encryption key per column to avoid potential data corruption. Responsibility for providing and managing the encryption key lies with the customer, as the key is utilized with the DECRYPT function. * This feature is not backward compatible with previous versions of SQreamDB. * The encryption feature affect performance and compression. From 0d102ff5bc7bd0b0a9cebd5a45e6a3e5c4b21f4f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:01:56 +0300 Subject: [PATCH 1647/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index d4587f781..10543c3a0 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -112,4 +112,4 @@ Limitations *********************** Permissions *********************** -Because the Data Encryption feature does not require a role, users with **Read** and **Insert** permissions can read tables containing encrypted data. \ No newline at end of file +The Data Encryption feature does not require a specific permission, users with **Read** or **Insert** may utilize encryption. \ No newline at end of file From 74fb418dc85fc9f1f063bb434ea270600f4fbe83 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:06:18 +0300 Subject: [PATCH 1648/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index 10543c3a0..a371e1a83 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -112,4 +112,4 @@ Limitations *********************** Permissions *********************** -The Data Encryption feature does not require a specific permission, users with **Read** or **Insert** may utilize encryption. \ No newline at end of file +The Data Encryption feature does not require a specific permission, users with relevant **TABLE** and **COLUMN** `permissions <../operational_guides/access_control_permissions.html#permissions>`_ may utilize it. \ No newline at end of file From f2c94111021b5083a62e08950d91fd6fe66b9876 Mon Sep 17 00:00:00 2001 From: LiavSanker <liavs@sqreamtech.com> Date: Mon, 4 Nov 2024 16:16:12 +0200 Subject: [PATCH 1649/1892] 4.9 RN --- releases/4.0_index.rst | 3 +- releases/4.9.rst | 111 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 releases/4.9.rst diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index c43e090a0..d50c44088 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -17,4 +17,5 @@ 4.5 4.6 4.7 - 4.8 \ No newline at end of file + 4.8 + 4.9 \ No newline at end of file diff --git a/releases/4.9.rst b/releases/4.9.rst new file mode 100644 index 000000000..c5d220d55 --- /dev/null +++ b/releases/4.9.rst @@ -0,0 +1,111 @@ +.. _4.9: + +***************** +Release Notes 4.9 +***************** + +The 4.9 release notes were released on October 28th, 2024 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | RHEL 8.x | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 12.x | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 51 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.4.0 | +| | * ODBC 4.4.4 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | +| | * Pysqream 5.3.0 | +| | * SQLAlchemy 1.4 | +| | * Spark 5.0.0 | +| | * SQLoader As A Service 8.2 | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- + + + +► Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. +These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. + +► `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. + +► `Window funtion alias <../reference/sql/sql_syntax/window_functions.html#window-funtion-alias>`_ allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. + +► `CONCAT <../reference/sql/sql_functions/scalar_functions/string/concat_function.html#concat-function>`_ function concatenates one or more strings, or concatenates one or more binary values. + + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.9 resolved Issues +--------------------------- + ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-12365 | SQream CLI - Comment is not ignored as expected | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17520 | SQLoader - DELETE issue following CDC process | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + + +Deprecations +------------------- + +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +* REHL 8.x is now officially supported. + +Upgrading to Version 4.9 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 43b52c13ca544dd79abfa819d19347e3a701dfda Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:32:36 +0200 Subject: [PATCH 1650/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index b752a4dd9..9efae4276 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -29,7 +29,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.4.0 <https://sq-ftp-public.s3.amazonaws.com/sqream-jdbc-5.4.0.jar>`_ + - `sqream-jdbc 5.4.1 <`_https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-driver_sqream-jdbc-5.4.1.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From 450af5345737237a755522ca3881df45d8f08419 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 12 Nov 2024 16:45:55 +0200 Subject: [PATCH 1651/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 9efae4276..c647ea69e 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -29,7 +29,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.4.1 <`_https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-driver_sqream-jdbc-5.4.1.jar>`_ + - `sqream-jdbc 5.4.1 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-driver_sqream-jdbc-5.4.1.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From ff562fdb09187393868b69c562d4fe1c3c340a56 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:02:31 +0200 Subject: [PATCH 1652/1892] Update index.rst --- .../client_drivers/python/index.rst | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 949fab95c..d25709768 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -478,4 +478,83 @@ Prepared Statement Limitations --------------------------- * Prepared Statement do not support the use of :ref:`keywords_and_identifiers` as input parameters. +Prepared Statements code example +-------------------------------- + +.. code-block:: python + + import pysqream + from datetime import date, datetime + from time import time + + # SQreamDB Connection Setting + con = pysqream.connect(host='112.217.87.18', port=3108, database='master' + , username='sqream', password='sqream' + , clustered=True) + cur = con.cursor() + + # CREATE + create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text(12), ss text, dt date, dtt datetime)' + cur.execute(create) + + # DATA + data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "HENRY" , "TEST", date(2024, 11, 11), datetime(2024, 11, 11, 11, 11, 11, 11)) + row_count = 10**2 + + # Insert + insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)' + start = time() + + # Prepared Statement + cur.executemany(insert, [data] * row_count) + print (f"Total insert time for {row_count} rows: {time() - start} seconds") + + + # Results(Table Count) + cur = con.cursor() + cur.execute('select count(*) from perf') + result = cur.fetchall() # `fetchall` collects the entire data set + print (f"Count of inserted rows: {result[0][0]}") + + + # SELECT + query = "SELECT * FROM perf WHERE s = ?" + params = [("HENRY",)] + + # Prepared Statement + cur.execute(query,params) + + + # Result + rows = cur.fetchall() + print(rows) + + for row in rows: + print(row) + + # Conn Close + + + # DELETE + query = "DELETE FROM perf WHERE s = ?" + params = [("HENRY",)] + + # Prepared Statement + cur.execute(query,params) + + print("Delete completed.") + + # UPDATE + query = "UPDATE perf SET s = '?' WHERE s = '?'" + params = [("HENRY", "HENRY_TEST")] + + # Prepared Statement + cur.execute(query,params) + + print("Update completed.") + + # Conn Close + cur.close() + con.close() + From 641cab0372c50de519f187f708b8613b45e72d7a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:09:37 +0200 Subject: [PATCH 1653/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index d25709768..0f345dbcb 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -488,8 +488,8 @@ Prepared Statements code example from time import time # SQreamDB Connection Setting - con = pysqream.connect(host='112.217.87.18', port=3108, database='master' - , username='sqream', password='sqream' + con = pysqream.connect(host='<your-host-ip>', port=3108, database='master' + , username='<SQDB role name>', password='<SQDB role password>' , clustered=True) cur = con.cursor() @@ -498,7 +498,7 @@ Prepared Statements code example cur.execute(create) # DATA - data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "HENRY" , "TEST", date(2024, 11, 11), datetime(2024, 11, 11, 11, 11, 11, 11)) + data = (False, 2, 12, 145, 84124234, 3.141, -4.3, "STRING1" , "STRING2", date(2024, 11, 11), datetime(2024, 11, 11, 11, 11, 11, 11)) row_count = 10**2 # Insert @@ -519,7 +519,7 @@ Prepared Statements code example # SELECT query = "SELECT * FROM perf WHERE s = ?" - params = [("HENRY",)] + params = [("STRING1",)] # Prepared Statement cur.execute(query,params) @@ -537,7 +537,7 @@ Prepared Statements code example # DELETE query = "DELETE FROM perf WHERE s = ?" - params = [("HENRY",)] + params = [("STRING1",)] # Prepared Statement cur.execute(query,params) @@ -546,7 +546,7 @@ Prepared Statements code example # UPDATE query = "UPDATE perf SET s = '?' WHERE s = '?'" - params = [("HENRY", "HENRY_TEST")] + params = [("STRING1", "HENRY_TEST")] # Prepared Statement cur.execute(query,params) From 887dde15dbaef8fea23013426fe851edfee70e9d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 14 Nov 2024 09:15:50 +0200 Subject: [PATCH 1654/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index 0f345dbcb..e621eb1fe 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -546,7 +546,7 @@ Prepared Statements code example # UPDATE query = "UPDATE perf SET s = '?' WHERE s = '?'" - params = [("STRING1", "HENRY_TEST")] + params = [("STRING3", "STRING2")] # Prepared Statement cur.execute(query,params) From 82f6dc11d43a22aa000ecdb942eb7ea60ac22f6c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:00:33 +0200 Subject: [PATCH 1655/1892] Update index.rst --- .../client_drivers/python/index.rst | 31 +++++++++---------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index e621eb1fe..cb2524749 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -489,9 +489,9 @@ Prepared Statements code example # SQreamDB Connection Setting con = pysqream.connect(host='<your-host-ip>', port=3108, database='master' - , username='<SQDB role name>', password='<SQDB role password>' - , clustered=True) - cur = con.cursor() + , username='<SQDB role name>', password='<SQDB role password>' + , clustered=True) + cur = con.cursor() # CREATE create = 'create or replace table perf (b bool, t tinyint, sm smallint, i int, bi bigint, f real, d double, s text(12), ss text, dt date, dtt datetime)' @@ -505,7 +505,7 @@ Prepared Statements code example insert = 'insert into perf values (?,?,?,?,?,?,?,?,?,?,?)' start = time() - # Prepared Statement + # Prepared Statement cur.executemany(insert, [data] * row_count) print (f"Total insert time for {row_count} rows: {time() - start} seconds") @@ -521,7 +521,7 @@ Prepared Statements code example query = "SELECT * FROM perf WHERE s = ?" params = [("STRING1",)] - # Prepared Statement + # Prepared Statement cur.execute(query,params) @@ -530,28 +530,27 @@ Prepared Statements code example print(rows) for row in rows: - print(row) - - # Conn Close + print(row) - # DELETE - query = "DELETE FROM perf WHERE s = ?" - params = [("STRING1",)] + # UPDATE + query = "UPDATE perf SET s = '?' WHERE s = '?'" + params = [("STRING3", "STRING2")] # Prepared Statement cur.execute(query,params) - print("Delete completed.") + print("Update completed.") - # UPDATE - query = "UPDATE perf SET s = '?' WHERE s = '?'" - params = [("STRING3", "STRING2")] + + # DELETE + query = "DELETE FROM perf WHERE s = ?" + params = [("STRING1",)] # Prepared Statement cur.execute(query,params) - print("Update completed.") + print("Delete completed.") # Conn Close cur.close() From d50f5ae75025ea5aad4a5876f7329d9768496fce Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:29:06 +0200 Subject: [PATCH 1656/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index dfe8c597c..47ef58f95 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -15,6 +15,7 @@ The **SQLoader** is a Java service that enables you to ingest data into SQreamDB * SAP HANA * Sybase * Teradata +* SQreamDB 4.5.15 or later (Full Load only) .. contents:: :local: From 4083c36a8fbfe97ded2fd09a1403cdbb80dfd32a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:05:20 +0200 Subject: [PATCH 1657/1892] Update 4.9.rst --- releases/4.9.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index c5d220d55..f2cb24e47 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -4,7 +4,7 @@ Release Notes 4.9 ***************** -The 4.9 release notes were released on October 28th, 2024 +The 4.9 release notes were released on Novemebr 28th, 2024 .. contents:: :local: @@ -37,14 +37,7 @@ New Features and Enhancements -► Prepared statements, also known as parameterized queries, are a safer and more efficient way to execute SQL statements. They prevent SQL injection attacks by separating SQL code from data, and they can improve performance by reusing prepared statements. -These are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. - -► `PIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ allows to convert row-level data into columnar representation. This technique is particularly useful when you need to summarize and visualize data. `UNPIVOT <../reference/sql/sql_syntax/pivot_unpivot.html#syntax>`_ does the opposite by transforming columnar data into rows. This operation is invaluable for scenarios where you wish to explore data in a more granular manner. - -► `Window funtion alias <../reference/sql/sql_syntax/window_functions.html#window-funtion-alias>`_ allows to specify a parameter within the window function definition. This eliminates the need to repeatedly input the same SQL code in queries that use multiple window functions with identical definitions. - -► `CONCAT <../reference/sql/sql_functions/scalar_functions/string/concat_function.html#concat-function>`_ function concatenates one or more strings, or concatenates one or more binary values. +► Native `Data Encryption <../feature_guides/data_encryption.html>`_ is now supported using SQL syntax. Known Issues @@ -58,10 +51,17 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-12365 | SQream CLI - Comment is not ignored as expected | +| SQ-19055 | Illegal memory access was encountered error | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19053 | Workers connectivity issues | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17520 | SQLoader - DELETE issue following CDC process | +| SQ-19051 | Metadata issues causes some data portions to becamoe inaccessible | +--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18745 | Cannot grant select to a role on a table | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16877 | Query run time is longer than expected | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + @@ -70,7 +70,7 @@ Deprecations ► **Haskell CLI** -Starting October 2024, support for the Haskell CLI will be discontinued, and it will be replaced by a JAVA CLI that is compatible with both SQreamDB and BLUE. +Starting October 2024, support for the Haskell CLI is discontinued, and it will be replaced by a JAVA CLI that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. ► **CentOS Linux 7.x** From 93bfb1dfc9f951c8b11cb948e856484e8866aff2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:12:09 +0200 Subject: [PATCH 1658/1892] 4.9 RN --- releases/4.9.rst | 4 ++-- releases/index.rst | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index f2cb24e47..4ccbdb289 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -22,7 +22,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 51 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.4.0 | +| Driver compatibility | * JDBC 5.4.1 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | @@ -51,7 +51,7 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-19055 | Illegal memory access was encountered error | +| SQ-19055 | Illegal memory access was encountered error | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19053 | Workers connectivity issues | +--------------+---------------------------------------------------------------------------------------------------------------------+ diff --git a/releases/index.rst b/releases/index.rst index 357d0cda2..baae823ff 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,11 @@ Release Notes ************* +:ref:`Version 4.9 - November 28, 2024<4.9>` + +* Native `Data Encryption <../feature_guides/data_encryption.html>`_ is now supported using SQL syntax. + + :ref:`Version 4.8 - October 06, 2024<4.8>` * Prepared statements are now supported by our `Python <../connecting_to_sqream/client_drivers/python/index.html#prepared-statements>`_ and `JDBC <../connecting_to_sqream/client_drivers/jdbc/index.html#prepared-statements>`_ client drivers. From 4a7d521feecbcaaf72e80488ef844f0a5c3a5ae9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 18 Nov 2024 15:16:43 +0200 Subject: [PATCH 1659/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 4ccbdb289..1558099bf 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -51,7 +51,7 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-19055 | Illegal memory access was encountered error | +| SQ-19055 | Illegal memory access was encountered error | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19053 | Workers connectivity issues | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 4663691c1b74675b91030d0e590dc2c68dc1dd28 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 25 Nov 2024 08:46:50 +0200 Subject: [PATCH 1660/1892] Update 4.9.rst --- releases/4.9.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 1558099bf..4e9d56ff4 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -59,8 +59,7 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18745 | Cannot grant select to a role on a table | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16877 | Query run time is longer than expected | -+--------------+---------------------------------------------------------------------------------------------------------------------+ + @@ -70,7 +69,7 @@ Deprecations ► **Haskell CLI** -Starting October 2024, support for the Haskell CLI is discontinued, and it will be replaced by a JAVA CLI that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. +Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. ► **CentOS Linux 7.x** From ffe4f42d252a38738b8e9e75f54c6e26ab16ddc8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 25 Nov 2024 09:10:01 +0200 Subject: [PATCH 1661/1892] Update 4.9.rst --- releases/4.9.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 4e9d56ff4..665f9d193 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -59,9 +59,8 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18745 | Cannot grant select to a role on a table | +--------------+---------------------------------------------------------------------------------------------------------------------+ - - - +| SQ-16877 | Query run time is longer than expected | ++--------------+---------------------------------------------------------------------------------------------------------------------+ Deprecations From c195de4fe32ec88e219b56297d70abc78d3e54ba Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:13:03 +0200 Subject: [PATCH 1662/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index a371e1a83..ff1628891 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -54,7 +54,7 @@ Inserting encrypt player salary (``INT`` data type) INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); -Similar example using ``COPY FROM'' +Similar example using ``COPY FROM`` .. code-block:: psql @@ -71,12 +71,12 @@ Query the encrypted data .. code-block:: psql - SELECT player_name, salary FROM NBA + SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') FROM NBA WHERE player_name ='Jayson Christopher Tatum'; player_name |salary | ------------------------+----------+ - Jayson Christopher Tatum|-561885196| + Jayson Christopher Tatum|1500000 | Query the encrypted data using ``WHERE`` clause on an encrypted column @@ -85,6 +85,12 @@ Query the encrypted data using ``WHERE`` clause on an encrypted column SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') FROM NBA WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; + + player_name |salary | + ------------------------+----------+ + Jayson Christopher Tatum|1500000 | + ------------------------+----------+ + Marcus Smart |1350000 | Example of ``COPY TO`` using ``DECRYPT`` From d389ef902ddcf7edef028a1b76407e73fcb10ffa Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:11:54 +0200 Subject: [PATCH 1663/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 665f9d193..86f050544 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -55,7 +55,7 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19053 | Workers connectivity issues | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19051 | Metadata issues causes some data portions to becamoe inaccessible | +| SQ-19051 | Metadata issues with dict compression type | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18745 | Cannot grant select to a role on a table | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 3c4c4fe1ba7055bda397244d94985ff6257a5951 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 27 Nov 2024 08:56:01 +0200 Subject: [PATCH 1664/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 86f050544..96d4b87c1 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -16,7 +16,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================+ -| Supported OS | RHEL 8.x | +| Supported OS | RHEL 8.9 | +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 12.x | +-------------------------+------------------------------------------------------------------------+ From 0ffa7cd009f886f354ddca91854c15a691eeb3ac Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 27 Nov 2024 09:02:53 +0200 Subject: [PATCH 1665/1892] Update 4.9.rst --- releases/4.9.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 96d4b87c1..8a792a428 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -20,7 +20,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 12.x | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 51 | +| Storage version | 57 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.4.1 | | | * ODBC 4.4.4 | @@ -29,7 +29,7 @@ Compatibility Matrix | | * Pysqream 5.3.0 | | | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | -| | * SQLoader As A Service 8.2 | +| | * SQLoader As A Service 8.3 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 6b1ce8a64c38e45f395d80c5158d546cd2352cc6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:25:29 +0200 Subject: [PATCH 1666/1892] Remove encryption from public docs --- feature_guides/data_encryption.rst | 16 --- feature_guides/data_encryption_methods.rst | 17 --- feature_guides/data_encryption_overview.rst | 18 --- feature_guides/data_encryption_syntax.rst | 121 -------------------- feature_guides/data_encryption_types.rst | 14 --- feature_guides/index.rst | 1 - releases/4.9.rst | 4 - releases/index.rst | 4 - 8 files changed, 195 deletions(-) delete mode 100644 feature_guides/data_encryption.rst delete mode 100644 feature_guides/data_encryption_methods.rst delete mode 100644 feature_guides/data_encryption_overview.rst delete mode 100644 feature_guides/data_encryption_syntax.rst delete mode 100644 feature_guides/data_encryption_types.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst deleted file mode 100644 index c38d126fc..000000000 --- a/feature_guides/data_encryption.rst +++ /dev/null @@ -1,16 +0,0 @@ -.. _data_encryption: - -*********************** -Data Encryption -*********************** -The **Data Encryption** page describes the following: - - -.. toctree:: - :maxdepth: 1 - :titlesonly: - - data_encryption_overview - data_encryption_methods - data_encryption_types - data_encryption_syntax \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst deleted file mode 100644 index 250ca06de..000000000 --- a/feature_guides/data_encryption_methods.rst +++ /dev/null @@ -1,17 +0,0 @@ -.. _data_encryption_methods: - -*********************** -Encryption Methods -*********************** -Data exists in one of following states and determines the encryption method: - - -Encrypting Data in Transit ----------------- -**Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. - -For more information, see `Use TLS/SSL When Possible <../operational_guides/security.html#use-tls-ssl-when-possible>`_. - -Encrypting Data at Rest ----------------- -**Data at rest** refers to data stored on your hard drive or on the cloud. Because this data can be potentially intercepted **physically**, it requires a form of encryption that protects your data wherever you store it. SQream facilitates encryption by letting you encrypt any column. \ No newline at end of file diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst deleted file mode 100644 index 3df4820a9..000000000 --- a/feature_guides/data_encryption_overview.rst +++ /dev/null @@ -1,18 +0,0 @@ -.. _data_encryption_overview: - -*********************** -Overview -*********************** -**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - -Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. - -The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. - -SQream enables customers to implement a-Symmetric Encryption solution using Secret Keys that they provide and manage themselves. -The chosen encryption algorithm is AES-256, known for its strength and security. It is crucial to ensure that the Secret Key length is precisely 256 bits or 32 bytes. - - -For more information on the encryption syntax, see :ref:`data_encryption_syntax`. - -For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst deleted file mode 100644 index ff1628891..000000000 --- a/feature_guides/data_encryption_syntax.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _data_encryption_syntax: - -*********************** -Syntax -*********************** -Encrypting columns in a new table - -.. code-block:: psql - - CREATE TABLE <table name> ( - <column_name> <data_type> ENCRYPT, - <column_name> <data_type> NULL ENCRYPT, - <column_name> <data_type> NOT NULL ENCRYPT - ); - -Adding an encrypted column to an existing table - -.. code-block:: psql - - ALTER TABLE <table_name> ADD COLUMN <column_name> <data_type> ENCRYPT; - - -Encryption methods - -.. code-block:: psql - - ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) - - -Decryption method - -.. code-block:: psql - - DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) - -*********************** -Examples -*********************** - -Encrypting a new table - -.. code-block:: psql - - CREATE TABLE client_name ( - id BIGINT NOT NULL ENCRYPT, - first_name TEXT ENCRYPT, - last_name TEXT, - salary INT ENCRYPT); - -Inserting encrypt player salary (``INT`` data type) - -.. code-block:: psql - - INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) - VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); - -Similar example using ``COPY FROM`` - -.. code-block:: psql - - COPY NBA - ( - player_name, team_name, jersey_number, position, age, height, weight, college, - ENCRYPT (salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') - ) - FROM WRAPPER csv_fdw - OPTIONS - (location = '/tmp/source_file.csv', quote='@'); - -Query the encrypted data - -.. code-block:: psql - - SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') FROM NBA - WHERE player_name ='Jayson Christopher Tatum'; - - player_name |salary | - ------------------------+----------+ - Jayson Christopher Tatum|1500000 | - -Query the encrypted data using ``WHERE`` clause on an encrypted column - -.. code-block:: psql - - SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') - FROM NBA - WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; - - player_name |salary | - ------------------------+----------+ - Jayson Christopher Tatum|1500000 | - ------------------------+----------+ - Marcus Smart |1350000 | - -Example of ``COPY TO`` using ``DECRYPT`` - -.. code-block:: psql - - COPY - (SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') - FROM NBA - WHERE player_name ='Jayson Christopher Tatum') - TO WRAPPER parquet_fdw - OPTIONS (LOCATION = '/tmp/file.parquet'); - - -*********************** -Limitations -*********************** -* The following functionality is not supported by the encryption feature: ``Catalog queries``, ``Utility commands``, ``Foreign Tables``, ``Create AS SELECT``. -* A single encryption key must be used per column - using a different key would result in an error. -* Compression of encrypted columns is limited to the following types: ``Flat``, ``LZ4``, ``PD4``, ``DICT``, ``RLE``. -* This feature is not backward compatible with previous versions of SQreamDB. -* The encryption feature affect performance and compression. - - - -*********************** -Permissions -*********************** -The Data Encryption feature does not require a specific permission, users with relevant **TABLE** and **COLUMN** `permissions <../operational_guides/access_control_permissions.html#permissions>`_ may utilize it. \ No newline at end of file diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst deleted file mode 100644 index a42d22da9..000000000 --- a/feature_guides/data_encryption_types.rst +++ /dev/null @@ -1,14 +0,0 @@ -.. _data_encryption_types: - -*********************** -Data Types -*********************** -Typically speaking, sensitive pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. - -SQream's data encryption feature supports encrypting column-based data belonging to the following data types: - -* ``INT`` -* ``BIGINT`` -* ``TEXT`` - -For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 9d29ab3f1..672d7d423 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -15,4 +15,3 @@ The **Feature Guides** section describes background processes that SQreamDB uses python_functions workload_manager concurrency_and_locks - data_encryption diff --git a/releases/4.9.rst b/releases/4.9.rst index 8a792a428..7166d168b 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -36,10 +36,6 @@ New Features and Enhancements ----------------------------- - -► Native `Data Encryption <../feature_guides/data_encryption.html>`_ is now supported using SQL syntax. - - Known Issues ------------ diff --git a/releases/index.rst b/releases/index.rst index baae823ff..cf46f5ee1 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,10 +4,6 @@ Release Notes ************* -:ref:`Version 4.9 - November 28, 2024<4.9>` - -* Native `Data Encryption <../feature_guides/data_encryption.html>`_ is now supported using SQL syntax. - :ref:`Version 4.8 - October 06, 2024<4.8>` From ebf31bca42c8cf82bcbe8dde6e752af1a200a373 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:31:44 +0200 Subject: [PATCH 1667/1892] Remove encryption - part 2 --- releases/4.9.rst | 2 +- releases/index.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 7166d168b..acb7f8cbe 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- - +N/A Known Issues ------------ diff --git a/releases/index.rst b/releases/index.rst index cf46f5ee1..d070c9df6 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,8 @@ Release Notes ************* +:ref:`Version 4.9 - November 28, 2024<4.9>` + :ref:`Version 4.8 - October 06, 2024<4.8>` From 04550e2cff286fd07435a36add325a592d33c704 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 28 Nov 2024 14:37:33 +0200 Subject: [PATCH 1668/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index acb7f8cbe..8c4fc86e3 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -N/A +This release does not include any new features or enhancements Known Issues ------------ From 3f2208006f322b583f0a1f6bd3a50bb1164a2830 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:04:39 +0200 Subject: [PATCH 1669/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 8c4fc86e3..4e31ed08e 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -51,7 +51,7 @@ Version 4.9 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19053 | Workers connectivity issues | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19051 | Metadata issues with dict compression type | +| SQ-19051 | Compression related metadata issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18745 | Cannot grant select to a role on a table | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 99f9165948be4e638f60bfc46c792e5dfba77180 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:40:09 +0200 Subject: [PATCH 1670/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index c647ea69e..1b599393b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -18,6 +18,11 @@ Client Driver Downloads - Docs - Notes - Operating System + * - **SQream DB Java CLI** + - `SQream DB Java Command Line Interface <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ + - :ref:`sqream_sql_cli_reference` + - Replaces the Deprecated Haskell Command Line Tool + - All * - **Apache Spark** - `Apache Spark Connector <https://sq-ftp-public.s3.amazonaws.com/Spark-Sqream-Connector-5.0.0.jar>`_ - :ref:`spark` From 3e2a48769aebec1a975daa7d1c1569a1e2609a78 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:12:44 +0200 Subject: [PATCH 1671/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index 44069a834..8b1abeb26 100644 --- a/conf.py +++ b/conf.py @@ -32,7 +32,7 @@ # The full version, including alpha/beta/rc tags -release = '4.9' +release = '4.10' # -- General configuration --------------------------------------------------- From 3a4db4ee0aac546347f449113198e3fbadf58e95 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:22:27 +0200 Subject: [PATCH 1672/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 47ef58f95..0ec81174e 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -546,6 +546,10 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``true`` - Add an additional ``load_dttm`` column that defines the time and date of loading + - ``loadDttmColumnName`` + - Optional + - ``sq_load_dttm`` + - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the loadDttm parameter. If loadDttm is enabled, the column defined by loadDttmColumnName will be added to the target table. * - ``loadTypeName`` - Optional - ``full`` @@ -618,6 +622,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``true`` - Allows control over the validation of table existence during the load. + * .. _load_type_name: From 8d16373dc08ac6e71647ab1693555eca1e5a16ab Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:28:17 +0200 Subject: [PATCH 1673/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 0ec81174e..881e8ba37 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -545,8 +545,8 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``loadDttm`` - Optional - ``true`` - - Add an additional ``load_dttm`` column that defines the time and date of loading - - ``loadDttmColumnName`` + - Add an additional ``loadDttm`` column that defines the time and date of loading + * - ``loadDttmColumnName`` - Optional - ``sq_load_dttm`` - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the loadDttm parameter. If loadDttm is enabled, the column defined by loadDttmColumnName will be added to the target table. From 49d02e124d75d6bb688b42a700de135cbbf530af Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:33:40 +0200 Subject: [PATCH 1674/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 881e8ba37..502a50f79 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -622,7 +622,6 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``true`` - Allows control over the validation of table existence during the load. - * .. _load_type_name: From f42cc46b22d9d65900d37cdb21edb71dd4d78640 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:38:31 +0200 Subject: [PATCH 1675/1892] Update sqloader_as_a_service.rst --- data_ingestion/sqloader_as_a_service.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst index 502a50f79..4e69147e0 100644 --- a/data_ingestion/sqloader_as_a_service.rst +++ b/data_ingestion/sqloader_as_a_service.rst @@ -549,7 +549,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``loadDttmColumnName`` - Optional - ``sq_load_dttm`` - - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the loadDttm parameter. If loadDttm is enabled, the column defined by loadDttmColumnName will be added to the target table. + - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the ``loadDttm`` parameter. If ``loadDttm`` is enabled, the column defined by ``loadDttmColumnName`` will be added to the target table. * - ``loadTypeName`` - Optional - ``full`` @@ -622,7 +622,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``true`` - Allows control over the validation of table existence during the load. - + .. _load_type_name: Using the ``loadTypeName`` Parameter From 665682de129f16ff0de76140f70cf8de87596953 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Sun, 8 Dec 2024 13:47:38 +0200 Subject: [PATCH 1676/1892] Update 4.0_index.rst --- releases/4.0_index.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index d50c44088..ff752a98e 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -18,4 +18,5 @@ 4.6 4.7 4.8 - 4.9 \ No newline at end of file + 4.9 + 4.10 From e2f4972ab1217169d2114cc27aec5a43d857b9d7 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Tue, 10 Dec 2024 16:46:13 +0200 Subject: [PATCH 1677/1892] Create 4.10.rst --- releases/4.10.rst | 105 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 releases/4.10.rst diff --git a/releases/4.10.rst b/releases/4.10.rst new file mode 100644 index 000000000..533f27b39 --- /dev/null +++ b/releases/4.10.rst @@ -0,0 +1,105 @@ +.. _4.10: + +***************** +Release Notes 4.10 +***************** + +The 4.10 release notes were released on Novemebr 28th, 2024 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | RHEL 8.9 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 12.x | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 57 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.4.1 | +| | * ODBC 4.4.4 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | +| | * Pysqream 5.3.0 | +| | * SQLAlchemy 1.4 | +| | * Spark 5.0.0 | +| | * SQLoader As A Service 8.3 | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- +This release does not include any new features or enhancements + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.10 resolved Issues +--------------------------- + ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-19055 | Illegal memory access was encountered error | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19053 | Workers connectivity issues | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19051 | Compression related metadata issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18745 | Cannot grant select to a role on a table | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16877 | Query run time is longer than expected | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + +Deprecations +------------------- + +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +* REHL 8.x is now officially supported. + +Upgrading to Version 4.10 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + From 797ca54aa7af374acedba715485a780ca34ba9c3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:58:02 +0200 Subject: [PATCH 1678/1892] Update regexp_replace.rst --- .../string/regexp_replace.rst | 49 +++++++++++++------ 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index ff3a0cc6a..698ae19a2 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -41,19 +41,23 @@ The following table shows the ``REGEXP_REPLACE`` arguments: * - ``occurrence`` - (Optional) Sets a specific occurrence to replace. Using ``0`` replaces all occurrences. -Test Patterns -============= +Supported RegEx Patterns +======================== .. list-table:: :widths: auto :header-rows: 1 - * - Test Pattern + * - Pattern - Description + * - ``^`` - Match the beginning of a string + * - ``[^]`` + - Characters that do not match the speciifed string + * - ``$`` - Match the end of a string @@ -67,7 +71,7 @@ Test Patterns - Match the preceding pattern at least once * - ``?`` - - Match the preceding pattern once at most + - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``de|abc`` - Match either ``de`` or ``abc`` @@ -75,18 +79,35 @@ Test Patterns * - ``(abc)*`` - Match zero or more instances of the sequence ``abc`` - * - ``{2}`` - - Match the preceding pattern exactly two times + * - ``{m}`` + - Match the preceding pattern exactly ``m`` times + + * - ``{m,n}`` + - Match the preceding pattern at least ``m`` times but no more than ``n`` times + + * - ``[...]`` + - Match any sing character from the list within the parentheses + + * - ``|`' - * - ``{2,4}`` - - Match the preceding pattern between two and four times + - Means ``OR`` + * - ``(abc)*`` + - Treating the expression within the parentheses as a single unit - * - ``[a-dX]``, ``[^a-dX]`` - - - Matches any character that is (or is not when negated with ``^``) either ``a``, ``b``, ``c``, ``d``, or ``X``. - The ``-`` character between two other characters forms a range that matches all characters from the first character to the second. For example, [0-9] matches any decimal digit. - To include a literal ``]`` character, it must immediately follow the opening bracket [. To include a literal - character, it must be written first or last. - Any character that does not have a defined special meaning inside a [] pair matches only itself. + * - ``\`` + - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters + + * - ``\n`` + - Matching the nth (1-9) preceding subexpression grouped within parentheses + + * - ``*?`` + - Occurs zero or more times + + * - ``+?`` + - Occurs one or more times + + * - ``??`` + - Occurs zero or one times Returns ======= From 741ddab288c2a456b7fd45008040a214ba4846c5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:03:00 +0200 Subject: [PATCH 1679/1892] Update regexp_replace.rst --- .../sql_functions/scalar_functions/string/regexp_replace.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index 698ae19a2..51c4948d4 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -88,7 +88,7 @@ Supported RegEx Patterns * - ``[...]`` - Match any sing character from the list within the parentheses - * - ``|`' + * - ``|`` - Means ``OR`` * - ``(abc)*`` @@ -98,7 +98,7 @@ Supported RegEx Patterns - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters * - ``\n`` - - Matching the nth (1-9) preceding subexpression grouped within parentheses + - Matching the nth (``1``-``9``) preceding subexpression grouped within parentheses * - ``*?`` - Occurs zero or more times From 77f3bd8df77f3033ff5d0af3cabc9b32b58ba742 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:08:10 +0200 Subject: [PATCH 1680/1892] Update regexp_replace.rst --- .../scalar_functions/string/regexp_replace.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index 51c4948d4..5830442e8 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -73,9 +73,6 @@ Supported RegEx Patterns * - ``?`` - Match the preceding pattern once at most (``0`` or ``1`` time) - * - ``de|abc`` - - Match either ``de`` or ``abc`` - * - ``(abc)*`` - Match zero or more instances of the sequence ``abc`` @@ -89,8 +86,8 @@ Supported RegEx Patterns - Match any sing character from the list within the parentheses * - ``|`` - - - Means ``OR`` + - ``OR`` clause + * - ``(abc)*`` - Treating the expression within the parentheses as a single unit From a4513be34b8b811076f6fbdc0c5d947b7d6de1b7 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:17:57 +0200 Subject: [PATCH 1681/1892] RegEx --- .../scalar_functions/string/regexp_count.rst | 50 +++++++++++++------ .../scalar_functions/string/regexp_instr.rst | 50 +++++++++++++------ .../scalar_functions/string/regexp_substr.rst | 50 +++++++++++++------ 3 files changed, 102 insertions(+), 48 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst index 26191eccc..cd0810356 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst @@ -31,8 +31,8 @@ Arguments * - ``start_index`` - The character index offset to start counting from. Defaults to 1 -Test patterns -============== +Supported RegEx Patterns +======================== .. list-table:: :widths: auto @@ -41,9 +41,13 @@ Test patterns * - Pattern - Description + * - ``^`` - Match the beginning of a string + * - ``[^]`` + - Characters that do not match the speciifed string + * - ``$`` - Match the end of a string @@ -57,27 +61,41 @@ Test patterns - Match the preceding pattern at least once * - ``?`` - - Match the preceding pattern once at most - - * - ``de|abc`` - - Match either ``de`` or ``abc`` + - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - Match zero or more instances of the sequence ``abc`` - * - ``{2}`` - - Match the preceding pattern exactly two times + * - ``{m}`` + - Match the preceding pattern exactly ``m`` times - * - ``{2,4}`` - - Match the preceding pattern between two and four times + * - ``{m,n}`` + - Match the preceding pattern at least ``m`` times but no more than ``n`` times - * - ``[a-dX]``, ``[^a-dX]`` - - - Matches any character that is (or is not when negated with ``^``) either ``a``, ``b``, ``c``, ``d``, or ``X``. - The ``-`` character between two other characters forms a range that matches all characters from the first character to the second. For example, [0-9] matches any decimal digit. - To include a literal ``]`` character, it must immediately follow the opening bracket [. To include a literal - character, it must be written first or last. - Any character that does not have a defined special meaning inside a [] pair matches only itself. + * - ``[...]`` + - Match any sing character from the list within the parentheses + + * - ``|`` + - ``OR`` clause + + * - ``(abc)*`` + - Treating the expression within the parentheses as a single unit + * - ``\`` + - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters + + * - ``\n`` + - Matching the nth (``1``-``9``) preceding subexpression grouped within parentheses + + * - ``*?`` + - Occurs zero or more times + + * - ``+?`` + - Occurs one or more times + + * - ``??`` + - Occurs zero or one times + Returns ============ diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst index d72f0af4f..033f632a2 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst @@ -36,8 +36,8 @@ Arguments - Specifies the location within the string to return. Using 0, the function returns the string position of the first character of the substring that matches the pattern. A value greater than 0 returns will return the position of the first character following the end of the pattern. Defaults to 0 -Test patterns -============== +Supported RegEx Patterns +======================== .. list-table:: :widths: auto @@ -46,9 +46,13 @@ Test patterns * - Pattern - Description + * - ``^`` - Match the beginning of a string + * - ``[^]`` + - Characters that do not match the speciifed string + * - ``$`` - Match the end of a string @@ -62,26 +66,40 @@ Test patterns - Match the preceding pattern at least once * - ``?`` - - Match the preceding pattern once at most - - * - ``de|abc`` - - Match either ``de`` or ``abc`` + - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - Match zero or more instances of the sequence ``abc`` - * - ``{2}`` - - Match the preceding pattern exactly two times + * - ``{m}`` + - Match the preceding pattern exactly ``m`` times - * - ``{2,4}`` - - Match the preceding pattern between two and four times + * - ``{m,n}`` + - Match the preceding pattern at least ``m`` times but no more than ``n`` times - * - ``[a-dX]``, ``[^a-dX]`` - - - Matches any character that is (or is not when negated with ``^``) either ``a``, ``b``, ``c``, ``d``, or ``X``. - The ``-`` character between two other characters forms a range that matches all characters from the first character to the second. For example, [0-9] matches any decimal digit. - To include a literal ``]`` character, it must immediately follow the opening bracket [. To include a literal - character, it must be written first or last. - Any character that does not have a defined special meaning inside a [] pair matches only itself. + * - ``[...]`` + - Match any sing character from the list within the parentheses + + * - ``|`` + - ``OR`` clause + + * - ``(abc)*`` + - Treating the expression within the parentheses as a single unit + + * - ``\`` + - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters + + * - ``\n`` + - Matching the nth (``1``-``9``) preceding subexpression grouped within parentheses + + * - ``*?`` + - Occurs zero or more times + + * - ``+?`` + - Occurs one or more times + + * - ``??`` + - Occurs zero or one times Returns ============ diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index 36611424e..f5034e2eb 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -36,8 +36,8 @@ Arguments * - ``return_position`` - Setes the position within the string to return. Using 0, the function returns the string position of the first character of the substring that matches the pattern. Defaults to 0 -Test patterns -============== +Supported RegEx Patterns +======================== .. list-table:: :widths: auto @@ -46,9 +46,13 @@ Test patterns * - Pattern - Description + * - ``^`` - Match the beginning of a string + * - ``[^]`` + - Characters that do not match the speciifed string + * - ``$`` - Match the end of a string @@ -62,26 +66,40 @@ Test patterns - Match the preceding pattern at least once * - ``?`` - - Match the preceding pattern once at most - - * - ``de|abc`` - - Match either ``de`` or ``abc`` + - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - Match zero or more instances of the sequence ``abc`` - * - ``{2}`` - - Match the preceding pattern exactly two times + * - ``{m}`` + - Match the preceding pattern exactly ``m`` times - * - ``{2,4}`` - - Match the preceding pattern between two and four times + * - ``{m,n}`` + - Match the preceding pattern at least ``m`` times but no more than ``n`` times - * - ``[a-dX]``, ``[^a-dX]`` - - - Matches any character that is (or is not when negated with ``^``) either ``a``, ``b``, ``c``, ``d``, or ``X``. - The ``-`` character between two other characters forms a range that matches all characters from the first character to the second. For example, [0-9] matches any decimal digit. - To include a literal ``]`` character, it must immediately follow the opening bracket [. To include a literal - character, it must be written first or last. - Any character that does not have a defined special meaning inside a [] pair matches only itself. + * - ``[...]`` + - Match any sing character from the list within the parentheses + + * - ``|`` + - ``OR`` clause + + * - ``(abc)*`` + - Treating the expression within the parentheses as a single unit + + * - ``\`` + - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters + + * - ``\n`` + - Matching the nth (``1``-``9``) preceding subexpression grouped within parentheses + + * - ``*?`` + - Occurs zero or more times + + * - ``+?`` + - Occurs one or more times + + * - ``??`` + - Occurs zero or one times Returns ============ From 40545cd294fae9a24cbe065a8009c0d18d074327 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 16 Dec 2024 09:29:09 +0200 Subject: [PATCH 1682/1892] RegEx --- .../sql_functions/scalar_functions/string/regexp_count.rst | 5 +---- .../sql_functions/scalar_functions/string/regexp_instr.rst | 5 +---- .../scalar_functions/string/regexp_replace.rst | 7 ++----- .../scalar_functions/string/regexp_substr.rst | 5 +---- 4 files changed, 5 insertions(+), 17 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst index cd0810356..cce99e044 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_count.rst @@ -64,7 +64,7 @@ Supported RegEx Patterns - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - - Match zero or more instances of the sequence ``abc`` + - Match zero or more instances of the sequence ``abc``, treating the expression within the parentheses as a single unit * - ``{m}`` - Match the preceding pattern exactly ``m`` times @@ -77,9 +77,6 @@ Supported RegEx Patterns * - ``|`` - ``OR`` clause - - * - ``(abc)*`` - - Treating the expression within the parentheses as a single unit * - ``\`` - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst index 033f632a2..07b3ec9a8 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_instr.rst @@ -69,7 +69,7 @@ Supported RegEx Patterns - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - - Match zero or more instances of the sequence ``abc`` + - Match zero or more instances of the sequence ``abc``, treating the expression within the parentheses as a single unit * - ``{m}`` - Match the preceding pattern exactly ``m`` times @@ -82,9 +82,6 @@ Supported RegEx Patterns * - ``|`` - ``OR`` clause - - * - ``(abc)*`` - - Treating the expression within the parentheses as a single unit * - ``\`` - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst index 5830442e8..49426f254 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_replace.rst @@ -73,8 +73,8 @@ Supported RegEx Patterns * - ``?`` - Match the preceding pattern once at most (``0`` or ``1`` time) - * - ``(abc)*`` - - Match zero or more instances of the sequence ``abc`` + * - ``(abc)*`` + - Match zero or more instances of the sequence ``abc``, treating the expression within the parentheses as a single unit * - ``{m}`` - Match the preceding pattern exactly ``m`` times @@ -87,9 +87,6 @@ Supported RegEx Patterns * - ``|`` - ``OR`` clause - - * - ``(abc)*`` - - Treating the expression within the parentheses as a single unit * - ``\`` - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index f5034e2eb..37eb840cc 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -69,7 +69,7 @@ Supported RegEx Patterns - Match the preceding pattern once at most (``0`` or ``1`` time) * - ``(abc)*`` - - Match zero or more instances of the sequence ``abc`` + - Match zero or more instances of the sequence ``abc``, treating the expression within the parentheses as a single unit * - ``{m}`` - Match the preceding pattern exactly ``m`` times @@ -82,9 +82,6 @@ Supported RegEx Patterns * - ``|`` - ``OR`` clause - - * - ``(abc)*`` - - Treating the expression within the parentheses as a single unit * - ``\`` - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters From 6296d5cc7771cae43a8d40b87bdbc656cca132f2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 19 Dec 2024 13:31:07 +0200 Subject: [PATCH 1683/1892] Update server_picker.rst --- reference/cli/server_picker.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/cli/server_picker.rst b/reference/cli/server_picker.rst index 47688a2ae..ee3ad40fe 100644 --- a/reference/cli/server_picker.rst +++ b/reference/cli/server_picker.rst @@ -52,7 +52,7 @@ Example .. code-block:: console - server_picker --metadata_ip=127.0.0.1 --metadata_server_port=3105 --port=3118 --ssl_port=3119 --services=sqream23,sqream0 --log4_config=/home/sqream/metadata_log_properties --refresh_interval=10 + server_picker --metadata_server_ip=127.0.0.1 --metadata_server_port=3105 --port=3118 --ssl_port=3119 --services=sqream23,sqream0 --log4_config=/home/sqream/metadata_log_properties --refresh_interval=10 Starting server picker ============================ From 9adc70af109f8b31864ee28ef977a91557b351d5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 14:22:20 +0200 Subject: [PATCH 1684/1892] Update alter_default_permissions.rst --- .../access_control_commands/alter_default_permissions.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 89ce4eb75..048a63663 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -24,7 +24,7 @@ Syntax .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR modifying_role + ALTER DEFAULT PERMISSIONS FOR modifying_role_name [IN schema_name, ...] FOR { SCHEMAS @@ -33,10 +33,11 @@ Syntax | VIEWS | COLUMNS | SAVED_QUERIES + | FUNCTIONS } { grant_clause | DROP grant_clause } - TO ROLE { role_name | public + TO { modified_role_name | public } grant_clause ::= From 77fa4f17def3732d288a5c395865702b3b85dedb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:13:33 +0200 Subject: [PATCH 1685/1892] Alter default permissions --- operational_guides/access_control_permissions.rst | 15 +++++++-------- .../alter_default_permissions.rst | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index 19e5d033f..b3e1152b8 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -371,21 +371,20 @@ schema statement is run. .. code-block:: postgres - ALTER DEFAULT PERMISSIONS FOR modifying_role - [IN <schema_name> [, ...] + ALTER DEFAULT PERMISSIONS FOR modifying_role_name + [IN schema_name, ...] FOR { SCHEMAS | TABLES | FOREIGN TABLES - | VIEWS - | COLUMNS - | CATALOGS - | SERVICES - | SAVED QUERIES + | VIEWS + | COLUMNS + | SAVED_QUERIES + | FUNCTIONS } { grant_clause | DROP grant_clause } - TO ROLE { role_name | public + TO { modified_role_name | public } grant_clause ::= diff --git a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst index 048a63663..212eb662b 100644 --- a/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst +++ b/reference/sql/sql_statements/access_control_commands/alter_default_permissions.rst @@ -33,7 +33,7 @@ Syntax | VIEWS | COLUMNS | SAVED_QUERIES - | FUNCTIONS + | FUNCTIONS } { grant_clause | DROP grant_clause } From ea0ac33eb9134ed31cc60ec22aec2467261fbf17 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:30:02 +0200 Subject: [PATCH 1686/1892] Update 4.10.rst --- releases/4.10.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 533f27b39..c39dbcf9f 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -This release does not include any new features or enhancements +* :ref:`Alter Default Permissions Control<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS`` Known Issues ------------ From b987d9125ac408be7097aeb52800bc165d336369 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:35:09 +0200 Subject: [PATCH 1687/1892] Update 4.10.rst --- releases/4.10.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index c39dbcf9f..f1bfe9a14 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -34,7 +34,7 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -* :ref:`Alter Default Permissions Control<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS`` +* :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS`` Known Issues ------------ From 309e3e641002aeda6e622ddcd0311a31e44494ee Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:38:58 +0200 Subject: [PATCH 1688/1892] Update 4.10.rst --- releases/4.10.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index f1bfe9a14..6534e831a 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -34,7 +34,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -* :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS`` +* :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS``. + +* Enahnced Regular Expresseion (RegEx) support. Known Issues ------------ From 22795c1bbb9deed8dd8fed093a41d381dee8577d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 23 Dec 2024 15:44:36 +0200 Subject: [PATCH 1689/1892] Update 4.10.rst --- releases/4.10.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 6534e831a..215399f1f 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -34,9 +34,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -* :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS``. +► :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS``. -* Enahnced Regular Expresseion (RegEx) support. +► Enahnced Regular Expresseion (RegEx) support. Known Issues ------------ From 87d4dd3ee468303a1687eb0c7ac35d7a2bb371c4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:45:21 +0200 Subject: [PATCH 1690/1892] jdbc5.4.2 --- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.10.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 1b599393b..06e758632 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.4.1 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-driver_sqream-jdbc-5.4.1.jar>`_ + - `sqream-jdbc 5.4.2 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.4.2.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All diff --git a/releases/4.10.rst b/releases/4.10.rst index 215399f1f..c0633492f 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -22,7 +22,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 57 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.4.1 | +| Driver compatibility | * JDBC 5.4.2 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | From 79bf33d1f902244f49bbb045f1aa79ac1e61ac9b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:51:01 +0200 Subject: [PATCH 1691/1892] Update 4.9.rst --- releases/4.9.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.9.rst b/releases/4.9.rst index 4e31ed08e..75f532bf1 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -22,7 +22,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 57 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.4.1 | +| Driver compatibility | * JDBC 5.4.2 | | | * ODBC 4.4.4 | | | * NodeJS 4.2.4 | | | * .NET 5.0.0 | From 7a851fa97902565d3171087762c39a57d6b47f71 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Tue, 24 Dec 2024 18:01:04 +0200 Subject: [PATCH 1692/1892] Update 4.10.rst --- releases/4.10.rst | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index c0633492f..1a48dc2aa 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -30,6 +30,7 @@ Compatibility Matrix | | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.3 | +| | * Java CLI 2.0 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements @@ -49,16 +50,38 @@ Version 4.10 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-19055 | Illegal memory access was encountered error | +| SQ-19275 | Core dump in core-min_maxFder | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19053 | Workers connectivity issues | +| SQ-19048 | Core dump while logging in with LDAP | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19051 | Compression related metadata issue | +| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker crash | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18745 | Cannot grant select to a role on a table | +| SQ-18797 | Worker crash leaves orphan locks | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16877 | Query run time is longer than expected | +| SQ-18752 | SQDB release with python 3.11 | +--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18621 | Core dump following a delete query | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18555 | Enhance set parameter command efficiency | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18553 | Metering Service - Data read/write usage reports | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18504 | Access Control Permissions - Functions | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18301 | Essential Regular Expression | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18253 | A network insert query caused a core dump | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17787 | Error in ChunkCache0 cause a core dump | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-17715 | Regular Expressions (Regex) Enhancements | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16436 | Right function error | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-14398 | Improve orphan locks handling | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + Deprecations From ccbd9578e9531e6f5237955372e612c92785edfc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 25 Dec 2024 14:50:16 +0200 Subject: [PATCH 1693/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 06e758632..0e39c82d0 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.0.0-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From f16c0ae874d4816258347b4529c8fa019b4e7a6a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 25 Dec 2024 16:03:52 +0200 Subject: [PATCH 1694/1892] Update sqream_sql.rst --- reference/cli/sqream_sql.rst | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/reference/cli/sqream_sql.rst b/reference/cli/sqream_sql.rst index baf80e208..ef865032b 100644 --- a/reference/cli/sqream_sql.rst +++ b/reference/cli/sqream_sql.rst @@ -16,10 +16,9 @@ SQreamDB SQL Java-based CLI allows SQL statements to be executed interactively o Before You Begin ================ -* It is essential that you have the following installed: +* It is essential that Java 8 installed. - * `SQreamDB Java CLI <https://storage.cloud.google.com/cicd-storage/jdbc-console/release/jdbc-console-1.0.5-v1.zip>`_ - * Java 8 +* Download the latest CLI from the :ref:`Client Driver Downloads page <client_drivers>` * It is essential you have the Java home path configured in your ``sqream`` file: From 27ebf3882be03d424038645366221b1c024a5a53 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 25 Dec 2024 16:23:26 +0200 Subject: [PATCH 1695/1892] Update 4.10.rst --- releases/4.10.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/releases/4.10.rst b/releases/4.10.rst index 1a48dc2aa..2ab9cb326 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -97,6 +97,10 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re * REHL 8.x is now officially supported. +► **DateTime2 Alias** + +Starting April 2025, The alias ``DateTime2`` for the ``DateTime`` Data Type is being deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. While ``DateTime2`` will remain functional as an alias until April 2025, we recommend updating your code to use ``DateTime`` directly to ensure compatibility. + Upgrading to Version 4.10 ------------------------- From f6bb3c9194c0d78ef7b443fd0e36337150425cd9 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Thu, 26 Dec 2024 10:13:11 +0200 Subject: [PATCH 1696/1892] Update 4.10.rst --- releases/4.10.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 2ab9cb326..810964b5b 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -18,7 +18,7 @@ Compatibility Matrix +=========================+========================================================================+ | Supported OS | RHEL 8.9 | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version 12.x | +| supported Nvidia driver | CUDA version 12.3.2 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 57 | +-------------------------+------------------------------------------------------------------------+ @@ -50,17 +50,17 @@ Version 4.10 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-19275 | Core dump in core-min_maxFder | +| SQ-19275 | Error in core-min_maxFder | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19048 | Core dump while logging in with LDAP | +| SQ-19048 | Error when logging in with LDAP | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker crash | +| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker abnormal behavior | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18797 | Worker crash leaves orphan locks | +| SQ-18797 | Worker failure leaves orphan locks | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18752 | SQDB release with python 3.11 | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18621 | Core dump following a delete query | +| SQ-18621 | Failure following a delete query | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18555 | Enhance set parameter command efficiency | +--------------+---------------------------------------------------------------------------------------------------------------------+ @@ -70,9 +70,9 @@ Version 4.10 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18301 | Essential Regular Expression | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18253 | A network insert query caused a core dump | +| SQ-18253 | A network insert query fails | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17787 | Error in ChunkCache0 cause a core dump | +| SQ-17787 | Error in ChunkCache0 | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-17715 | Regular Expressions (Regex) Enhancements | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 6a9cc6b4b93550a8a54509af296b718de10ff239 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Thu, 26 Dec 2024 17:08:25 +0200 Subject: [PATCH 1697/1892] Update 4.10.rst --- releases/4.10.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 810964b5b..07425fd9c 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -18,7 +18,7 @@ Compatibility Matrix +=========================+========================================================================+ | Supported OS | RHEL 8.9 | +-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version 12.3.2 | +| supported Nvidia driver | CUDA version 12.3.2 | +-------------------------+------------------------------------------------------------------------+ | Storage version | 57 | +-------------------------+------------------------------------------------------------------------+ From cd4fb3d58d12a8735b701a3190bc29e71af0a765 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:13:06 +0200 Subject: [PATCH 1698/1892] global_graceful_shutdown --- reference/sql/sql_statements/index.rst | 4 +- .../global_graceful_shutdown.rst | 55 +++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 0d4ec85c1..9787739d7 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -133,7 +133,9 @@ The following table shows the Utility commands: - View the ``CREATE FUNCTION`` statement for a UDF * - :ref:`GET LICENSE INFO<get_license_info>` - View a user's license information - * - :ref:`GPU METRICS<select_gpu_metrics>` + * - :ref:`GLOBAL GRACEFUL SHUTDOWN<global_graceful_shutdown>` + - Graceful shutdown of all servers in the cluster + * - :ref:`GPU METRICS<select_gpu_metrics>` - Monitor license quota usage by reviewing monthly or daily GPU usage * - :ref:`get_open_snapshots` - Lists information about all currently open snapshots diff --git a/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst b/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst new file mode 100644 index 000000000..a3e34bee4 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst @@ -0,0 +1,55 @@ +:orphan: + +.. _global_graceful_shutdown: + +************************ +GLOBAL GRACEFUL SHUTDOWN +************************ + + +SQream's method for gracefully stopping the all SQream servers in the cluster. Once executed, it causes the servers to wait for any queued statements to complete before shutting down. + +.. contents:: + :local: + :depth: 1 + + +How Does it Work? +======================== +Running the ``GLOBAL GRACEFUL SHUTDOWN`` command gives you more control over the following: + +* Preventing new queries from connecting to the server by: + + * Setting the servers as unavailable in the metadata server. + + :: + + * Unsubscribing the servers from there services. + +* Preventing users from opening new connections to the server. Attempting to connect to the server after activating a graceful shutdown displays the following message: + + .. code-block:: postgres + + Server is shutting down, no new connections are possible at the moment. + + +Syntax +========== +The following is the syntax for using the ``GLOBAL GRACEFUL SHUTDOWN`` command: + +.. code-block:: postgres + + select global_graceful_shutdown(); + +Returns +========== +Running the ``GLOBAL GRACEFUL SHUTDOWN`` command returns no output. + +Parameters +============ +``GLOBAL GRACEFUL SHUTDOWN`` has no input parameters: + + +Permissions +============= +Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file From 6bb37bbedec242a200b3943efff0fc67b2f7f2ac Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:19:46 +0200 Subject: [PATCH 1699/1892] Update index.rst --- reference/sql/sql_statements/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 9787739d7..07b968ff3 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -135,7 +135,7 @@ The following table shows the Utility commands: - View a user's license information * - :ref:`GLOBAL GRACEFUL SHUTDOWN<global_graceful_shutdown>` - Graceful shutdown of all servers in the cluster - * - :ref:`GPU METRICS<select_gpu_metrics>` + * - :ref:`GPU METRICS<select_gpu_metrics>` - Monitor license quota usage by reviewing monthly or daily GPU usage * - :ref:`get_open_snapshots` - Lists information about all currently open snapshots From 493e34dbd104ef3ac26b6d3dcf5466de096e12bf Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:36:13 +0200 Subject: [PATCH 1700/1892] change permissions to superuser --- .../utility_commands/global_graceful_shutdown.rst | 2 +- .../sql_statements/utility_commands/shutdown_server_command.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst b/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst index a3e34bee4..9e6dd392c 100644 --- a/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst +++ b/reference/sql/sql_statements/utility_commands/global_graceful_shutdown.rst @@ -52,4 +52,4 @@ Parameters Permissions ============= -Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file +The ``SUPERUSER`` permission is required to execute ``GLOBAL GRACEFUL SHUTDOWN``. \ No newline at end of file diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index bc3b3a14d..8afa79586 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -110,4 +110,4 @@ The ``timeout`` unit is minutes. Permissions ============= -Using the ``shutdown_server`` command requires no special permissions. \ No newline at end of file +The ``shutdown_server`` permission is required to execute ``GLOBAL GRACEFUL SHUTDOWN``. \ No newline at end of file From 6b1a8d8b5e0b391d1f4457aec1891b17e452bbed Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 2 Jan 2025 17:40:59 +0200 Subject: [PATCH 1701/1892] Update shutdown_server_command.rst --- .../sql_statements/utility_commands/shutdown_server_command.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst index 8afa79586..d46cd592d 100644 --- a/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst +++ b/reference/sql/sql_statements/utility_commands/shutdown_server_command.rst @@ -110,4 +110,4 @@ The ``timeout`` unit is minutes. Permissions ============= -The ``shutdown_server`` permission is required to execute ``GLOBAL GRACEFUL SHUTDOWN``. \ No newline at end of file +The ``SUPERUSER`` permission is required to execute ``shutdown_server``. \ No newline at end of file From 4d6a374bb54e51d5349def6460d8613c9e83df81 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 9 Jan 2025 11:58:41 +0200 Subject: [PATCH 1702/1892] Update index.rst --- index.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/index.rst b/index.rst index 7d41b4984..cc7d23ed0 100644 --- a/index.rst +++ b/index.rst @@ -41,6 +41,8 @@ SQreamDB is a columnar analytic SQL database management system. SQreamDB support +-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`client_drivers` | Describes how to use the SQreamDB client drivers and client applications with SQreamDB. | +-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +| :ref:`sqream_sql_cli_reference` | Describes how to use the SQreamDB client command line tool (CLI) with SQreamDB. | ++-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | **External Storage Platforms** | +-------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ | :ref:`s3` | Describes how to insert data over a native S3 connector. | From d2ad21c794dda9cb3cd6aa8138daa4a6aa185ca1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 07:54:20 +0200 Subject: [PATCH 1703/1892] remove mentions of record_delimiter --- data_ingestion/csv.rst | 13 ++++--------- external_storage_platforms/s3.rst | 7 +++---- .../ddl_commands/create_foreign_table.rst | 5 ----- .../sql/sql_statements/dml_commands/copy_from.rst | 10 +--------- .../sql/sql_statements/dml_commands/copy_to.rst | 6 ------ 5 files changed, 8 insertions(+), 33 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index e7dc19ddf..fb6e9a51e 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -127,7 +127,6 @@ The CSV is a standard CSV, but with two differences from SQream DB defaults: OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - RECORD_DELIMITER = '\r\n', OFFSET = 2; ); @@ -252,8 +251,7 @@ Loading Files Formatted for Windows (``\r\n``) OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - DELIMITER = '|', - RECORD_DELIMITER = '\r\n' + DELIMITER = '|' ); Loading a File From a Public S3 Bucket @@ -271,8 +269,7 @@ Loading a File From a Public S3 Bucket OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - OFFSET = 2, - RECORD_DELIMITER = '\r\n' + OFFSET = 2 ); Loading files from an authenticated S3 bucket @@ -288,8 +285,7 @@ Loading files from an authenticated S3 bucket OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - OFFSET = 2, - RECORD_DELIMITER = '\r\n', + OFFSET = 2 AWS_ID = '12345678', AWS_SECRET = 'super_secretive_secret' ); @@ -309,8 +305,7 @@ Loading files from an HDFS storage OPTIONS ( LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', - OFFSET = 2, - RECORD DELIMITER = '\r\n' + OFFSET = 2 ); Saving rejected rows to a file diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index 39aaec59f..38d1e80a1 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -88,8 +88,7 @@ Based on the source file's structure, you can create a foreign table with the ap WRAPPER csv_fdw OPTIONS ( - LOCATION = 's3://sqream-demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n' -- DOS delimited file + LOCATION = 's3://sqream-demo-data/nba_players.csv' ) ; @@ -125,7 +124,7 @@ The bucket must be publicly available and objects must be listed. .. code-block:: postgres - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; + COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2; Loading Files from an Authenticated S3 Bucket @@ -133,6 +132,6 @@ Loading Files from an Authenticated S3 Bucket .. code-block:: postgres - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' + COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2' AWS_ID '12345678' AWS_SECRET 'super_secretive_secret'; \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 15a5c3a06..69484406f 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -27,7 +27,6 @@ Syntax LOCATION = '{ path_spec }' [ | DELIMITER = '{ field_delimiter }' -- for CSV only - | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only | AWS_ID '{ AWS ID }' | AWS_SECRET '{ AWS SECRET }' | QUOTE = {'C' | E'\ooo') -- for CSV only @@ -36,8 +35,6 @@ Syntax path_spec ::= { GS URI | S3 URI | HDFS URI } field_delimiter ::= delimiter_character - - record_delimiter ::= delimiter_character column_def ::= { column_name type_name [ default ] [ column_constraint ] } @@ -76,8 +73,6 @@ Parameters - Specifies a path or URI of the source files, such as ``/path/to/*.parquet`` * - ``DELIMITER = ...`` - Specifies the field delimiter for CSV files. Defaults to ``,`` - * - ``RECORD_DELIMITER = ...`` - - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` * - ``AWS_ID``, ``AWS_SECRET`` - Credentials for authenticated S3 access * - ``OFFSET`` diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 450573068..0e79e1b62 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -45,8 +45,6 @@ Syntax | DELIMITER = '{ delimiter }' - | RECORD_DELIMITER = '{ record delimiter }' - | ERROR_LOG = '{ local filepath }' | REJECTED_DATA = '{ local filepath }' @@ -69,8 +67,6 @@ Syntax delimiter ::= string - record delimiter ::= string - error count ::= integer parser_format ::= see supported parser table below @@ -84,7 +80,7 @@ Syntax Some options are applicable to CSVs only. These include: - ``OFFSET``, ``LIMIT``, ``DELIMITER``, ``RECORD_DELIMITER``, ``REJECTED_DATA``, ``DATETIME_FORMAT`` + ``OFFSET``, ``LIMIT``, ``DELIMITER``, ``REJECTED_DATA``, ``DATETIME_FORMAT`` .. _copy_from_config_options: @@ -127,10 +123,6 @@ Elements - ``','`` - Almost any ASCII character, :ref:`See field delimiters section below<field_delimiters>` - Specifies the field terminator - the character (or characters) that separates fields or columns within each row of the file. - * - ``RECORD_DELIMITER`` - - ``\n`` (UNIX style newline) - - ``\n``, ``\r\n``, ``\r`` - - Specifies the row terminator - the character that separates lines or rows, also known as a new line separator. * - ``ERROR_LOG`` - No error log - diff --git a/reference/sql/sql_statements/dml_commands/copy_to.rst b/reference/sql/sql_statements/dml_commands/copy_to.rst index c64e4b655..0ba6ed451 100644 --- a/reference/sql/sql_statements/dml_commands/copy_to.rst +++ b/reference/sql/sql_statements/dml_commands/copy_to.rst @@ -45,8 +45,6 @@ The following is the correct syntax for using the **COPY TO** statement: | DELIMITER = '{ delimiter }' - | RECORD_DELIMITER = '{ record delimiter }' - | HEADER = { true | false } | AWS_ID = '{ AWS ID }' @@ -60,8 +58,6 @@ The following is the correct syntax for using the **COPY TO** statement: delimiter ::= string - record delimiter ::= string - AWS ID ::= string AWS Secret ::= string @@ -92,8 +88,6 @@ The following table shows the ``COPY_TO`` elements: - The CSV file will contain a header line with the names of each column in the file. This option is allowed only when using CSV format. * - ``DELIMITER`` - Specifies the character or string that separates fields (columns) within each row of the file. The default is a comma character (``,``). This option is allowed only when using CSV format. - * - ``RECORD_DELIMITER`` - - Specifies the character or string that separates records in a data set. This option is allowed only when using CSV format. * - ``AWS_ID``, ``AWS_SECRET`` - Specifies the authentication details for secured S3 buckets * - ``MAX_FILE_SIZE`` From 2167fc125fc322f2c9795b5e81c5078d5dc21f37 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:21:00 +0200 Subject: [PATCH 1704/1892] revert record_delimiter removal - should only be removed from copy_to --- data_ingestion/csv.rst | 3 +++ external_storage_platforms/s3.rst | 7 ++++--- .../ddl_commands/create_foreign_table.rst | 5 +++++ .../sql/sql_statements/dml_commands/copy_from.rst | 10 +++++++++- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index fb6e9a51e..edaac8c69 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -127,6 +127,7 @@ The CSV is a standard CSV, but with two differences from SQream DB defaults: OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', + RECORD_DELIMITER = '\r\n', OFFSET = 2; ); @@ -251,6 +252,7 @@ Loading Files Formatted for Windows (``\r\n``) OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', + RECORD_DELIMITER = '\r\n', DELIMITER = '|' ); @@ -305,6 +307,7 @@ Loading files from an HDFS storage OPTIONS ( LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', + RECORD DELIMITER = '\r\n', OFFSET = 2 ); diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index 38d1e80a1..e33a8e6be 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -88,7 +88,8 @@ Based on the source file's structure, you can create a foreign table with the ap WRAPPER csv_fdw OPTIONS ( - LOCATION = 's3://sqream-demo-data/nba_players.csv' + LOCATION = 's3://sqream-demo-data/nba_players.csv', + RECORD_DELIMITER = '\r\n' -- DOS delimited file ) ; @@ -124,7 +125,7 @@ The bucket must be publicly available and objects must be listed. .. code-block:: postgres - COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2; + COPY nba FROM 's3://sqream-demo-data/nba.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n'; Loading Files from an Authenticated S3 Bucket @@ -132,6 +133,6 @@ Loading Files from an Authenticated S3 Bucket .. code-block:: postgres - COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2' + COPY nba FROM 's3://secret-bucket/*.csv' WITH OFFSET 2 RECORD DELIMITER '\r\n' AWS_ID '12345678' AWS_SECRET 'super_secretive_secret'; \ No newline at end of file diff --git a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst index 69484406f..d5aa2c4d1 100644 --- a/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst +++ b/reference/sql/sql_statements/ddl_commands/create_foreign_table.rst @@ -27,6 +27,7 @@ Syntax LOCATION = '{ path_spec }' [ | DELIMITER = '{ field_delimiter }' -- for CSV only + | RECORD_DELIMITER = '{ record_delimiter }' -- for CSV only | AWS_ID '{ AWS ID }' | AWS_SECRET '{ AWS SECRET }' | QUOTE = {'C' | E'\ooo') -- for CSV only @@ -35,6 +36,8 @@ Syntax path_spec ::= { GS URI | S3 URI | HDFS URI } field_delimiter ::= delimiter_character + + record_delimiter ::= delimiter_character column_def ::= { column_name type_name [ default ] [ column_constraint ] } @@ -73,6 +76,8 @@ Parameters - Specifies a path or URI of the source files, such as ``/path/to/*.parquet`` * - ``DELIMITER = ...`` - Specifies the field delimiter for CSV files. Defaults to ``,`` + * - ``RECORD_DELIMITER = ...`` + - Specifies the record delimiter for CSV files. Defaults to a newline, ``\n`` * - ``AWS_ID``, ``AWS_SECRET`` - Credentials for authenticated S3 access * - ``OFFSET`` diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 0e79e1b62..347c21986 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -44,6 +44,8 @@ Syntax | LIMIT = { limit } | DELIMITER = '{ delimiter }' + + | RECORD_DELIMITER = '{ record delimiter }' | ERROR_LOG = '{ local filepath }' @@ -66,6 +68,8 @@ Syntax limit ::= positive integer delimiter ::= string + + record delimiter ::= string error count ::= integer @@ -80,7 +84,7 @@ Syntax Some options are applicable to CSVs only. These include: - ``OFFSET``, ``LIMIT``, ``DELIMITER``, ``REJECTED_DATA``, ``DATETIME_FORMAT`` + ``OFFSET``, ``LIMIT``, ``DELIMITER``, ``RECORD_DELIMITER``, ``REJECTED_DATA``, ``DATETIME_FORMAT`` .. _copy_from_config_options: @@ -123,6 +127,10 @@ Elements - ``','`` - Almost any ASCII character, :ref:`See field delimiters section below<field_delimiters>` - Specifies the field terminator - the character (or characters) that separates fields or columns within each row of the file. + * - ``RECORD_DELIMITER`` + - ``\n`` (UNIX style newline) + - ``\n``, ``\r\n``, ``\r`` + - Specifies the row terminator - the character that separates lines or rows, also known as a new line separator. * - ``ERROR_LOG`` - No error log - From e63bafb36bd50bf5000fbf0088bb4bfa611c8aae Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:25:26 +0200 Subject: [PATCH 1705/1892] Update s3.rst --- external_storage_platforms/s3.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external_storage_platforms/s3.rst b/external_storage_platforms/s3.rst index e33a8e6be..39aaec59f 100644 --- a/external_storage_platforms/s3.rst +++ b/external_storage_platforms/s3.rst @@ -89,7 +89,7 @@ Based on the source file's structure, you can create a foreign table with the ap OPTIONS ( LOCATION = 's3://sqream-demo-data/nba_players.csv', - RECORD_DELIMITER = '\r\n' -- DOS delimited file + RECORD_DELIMITER = '\r\n' -- DOS delimited file ) ; From 61c63b9755ba918c9b346d43ed4b12439a43daae Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:28:12 +0200 Subject: [PATCH 1706/1892] Update copy_from.rst --- reference/sql/sql_statements/dml_commands/copy_from.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/dml_commands/copy_from.rst b/reference/sql/sql_statements/dml_commands/copy_from.rst index 347c21986..713ec6563 100644 --- a/reference/sql/sql_statements/dml_commands/copy_from.rst +++ b/reference/sql/sql_statements/dml_commands/copy_from.rst @@ -45,7 +45,7 @@ Syntax | DELIMITER = '{ delimiter }' - | RECORD_DELIMITER = '{ record delimiter }' + | RECORD_DELIMITER = '{ record delimiter }' | ERROR_LOG = '{ local filepath }' From 6bc26d685d91eaee97665c77afe6462bf253eb3a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:36:33 +0200 Subject: [PATCH 1707/1892] Update csv.rst --- data_ingestion/csv.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index edaac8c69..62ec8620a 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -252,7 +252,7 @@ Loading Files Formatted for Windows (``\r\n``) OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - RECORD_DELIMITER = '\r\n', + RECORD_DELIMITER = '\r\n', DELIMITER = '|' ); @@ -307,7 +307,7 @@ Loading files from an HDFS storage OPTIONS ( LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', - RECORD DELIMITER = '\r\n', + RECORD DELIMITER = '\r\n', OFFSET = 2 ); From 8d118c56dd12e8c043e69a95603a2816445eaa43 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:41:08 +0200 Subject: [PATCH 1708/1892] Update csv.rst --- data_ingestion/csv.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_ingestion/csv.rst b/data_ingestion/csv.rst index 62ec8620a..5ea3733fa 100644 --- a/data_ingestion/csv.rst +++ b/data_ingestion/csv.rst @@ -252,7 +252,7 @@ Loading Files Formatted for Windows (``\r\n``) OPTIONS ( LOCATION = 's3://sqream-docs/nba.csv', - RECORD_DELIMITER = '\r\n', + RECORD_DELIMITER = '\r\n', DELIMITER = '|' ); @@ -306,8 +306,8 @@ Loading files from an HDFS storage csv_fdw OPTIONS ( - LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', - RECORD DELIMITER = '\r\n', + LOCATION = 'hdfs://hadoop-nn.piedpiper.com/rhendricks/*.csv', + RECORD DELIMITER = '\r\n', OFFSET = 2 ); From 1c75029eb42cb83f87f814af0d32eeca5dfd9331 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:09:04 +0200 Subject: [PATCH 1709/1892] Update python_functions.rst --- feature_guides/python_functions.rst | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 8212fab98..62f193c49 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -15,7 +15,7 @@ To enable UDFs, in your :ref:`legacy configuration file<current_method_modificat Before You Begin ================= -* Ensure you have Python 3.9 or newer installed +* Ensure you have Python 3.11 or newer installed * Enable UDFs by setting the ``enablePythonUdfs`` configuration flag to ``true`` in your :ref:`legacy configuration file<current_method_modification_methods>` @@ -44,10 +44,7 @@ To find which version of Python is installed for use by SQreamDB, create and run . $$ LANGUAGE PYTHON; executed master=> SELECT py_version(); - py_version - ------------------------------------------------------------------------------------- - Python version: 3.9.13 (default, Jul 22 2019, 11:03:54) [GCC 5.4.0]. - Path: /opt/sqream/python-3.9.13 + "Python version: 3.11.7 (main, Dec 22 2024, 18:29:20) [GCC 11.1.0]. Path: /usr/local" Using Modules --------------------- From a3ba8733a1c59c9e1c6ae65934269824469974cf Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 20 Jan 2025 14:44:50 +0200 Subject: [PATCH 1710/1892] 4.10 --- conf.py | 2 +- releases/4.10.rst | 4 +++- releases/index.rst | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/conf.py b/conf.py index 8b1abeb26..aa75acaff 100644 --- a/conf.py +++ b/conf.py @@ -27,7 +27,7 @@ # -- Project information ----------------------------------------------------- project = 'SQreamDB' -copyright = '2024 SQreamDB' +copyright = '2025 SQreamDB' author = 'SQreamDB Documentation' diff --git a/releases/4.10.rst b/releases/4.10.rst index 07425fd9c..dfaf4279b 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -4,7 +4,7 @@ Release Notes 4.10 ***************** -The 4.10 release notes were released on Novemebr 28th, 2024 +The 4.10 release notes were released on January 20th, 2025 .. contents:: :local: @@ -39,6 +39,8 @@ New Features and Enhancements ► Enahnced Regular Expresseion (RegEx) support. +► Python version for :ref:`Python User Defined Functions<python_functions>` has been upgraded to Python 3.11. + Known Issues ------------ diff --git a/releases/index.rst b/releases/index.rst index d070c9df6..26a85c6e5 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,8 +4,9 @@ Release Notes ************* -:ref:`Version 4.9 - November 28, 2024<4.9>` +:ref:`Version 4.10 - January 20, 2025<4.10>` +:ref:`Version 4.9 - November 28, 2024<4.9>` :ref:`Version 4.8 - October 06, 2024<4.8>` From 8e529754d2923966a37f794431eed9a57bd65bac Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 20 Jan 2025 15:31:30 +0200 Subject: [PATCH 1711/1892] Update 4.10.rst --- releases/4.10.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index dfaf4279b..8099aecda 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -20,7 +20,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 12.3.2 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 57 | +| Storage version | 58 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.4.2 | | | * ODBC 4.4.4 | @@ -29,7 +29,7 @@ Compatibility Matrix | | * Pysqream 5.3.0 | | | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | -| | * SQLoader As A Service 8.3 | +| | * SQLoader As A Service 8.3.1 | | | * Java CLI 2.0 | +-------------------------+------------------------------------------------------------------------+ From 69156ea43b52f109ed143e325295d51807a97fa4 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Tue, 21 Jan 2025 10:15:40 +0200 Subject: [PATCH 1712/1892] Update 4.10.rst --- releases/4.10.rst | 8 -------- 1 file changed, 8 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 8099aecda..48f37bdef 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -60,24 +60,16 @@ Version 4.10 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18797 | Worker failure leaves orphan locks | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18752 | SQDB release with python 3.11 | -+--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18621 | Failure following a delete query | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18555 | Enhance set parameter command efficiency | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18553 | Metering Service - Data read/write usage reports | -+--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18504 | Access Control Permissions - Functions | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18301 | Essential Regular Expression | -+--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-18253 | A network insert query fails | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-17787 | Error in ChunkCache0 | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17715 | Regular Expressions (Regex) Enhancements | -+--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-16436 | Right function error | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-14398 | Improve orphan locks handling | From 28a69da1d2e96c49bd82b6d065f0cfd2c43fe6e5 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Tue, 21 Jan 2025 10:35:20 +0200 Subject: [PATCH 1713/1892] Update 4.10.rst --- releases/4.10.rst | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 48f37bdef..14494c19a 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -52,27 +52,19 @@ Version 4.10 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-19275 | Error in core-min_maxFder | +| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker abnormal behavior | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19048 | Error when logging in with LDAP | +| SQ-18797 | Worker failure leaves orphan locks | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker abnormal behavior | +| SQ-18555 | Enhance set parameter command efficiency | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18797 | Worker failure leaves orphan locks | +| SQ-18504 | Access Control Permissions - Functions | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18621 | Failure following a delete query | +| SQ-18253 | A network insert query fails | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18555 | Enhance set parameter command efficiency | +| SQ-16436 | Right function error | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18504 | Access Control Permissions - Functions | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18253 | A network insert query fails | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-17787 | Error in ChunkCache0 | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16436 | Right function error | -+--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-14398 | Improve orphan locks handling | +| SQ-14398 | Improve orphan locks handling | +--------------+---------------------------------------------------------------------------------------------------------------------+ From a124128445797a0bbdd5ea32ec8caf230a01b8ef Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 26 Jan 2025 13:51:32 +0200 Subject: [PATCH 1714/1892] CLI 2.1 --- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.10.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 0e39c82d0..5b408cd6a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.0.0-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.1-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All diff --git a/releases/4.10.rst b/releases/4.10.rst index 14494c19a..c92da8ed1 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -30,7 +30,7 @@ Compatibility Matrix | | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.3.1 | -| | * Java CLI 2.0 | +| | * Java CLI 2.1 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 866c2581711b80e0f2aef07ed538b05105e4ae9b Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Thu, 30 Jan 2025 16:25:23 +0200 Subject: [PATCH 1715/1892] Update access_control_departmental_example.rst --- operational_guides/access_control_departmental_example.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/operational_guides/access_control_departmental_example.rst b/operational_guides/access_control_departmental_example.rst index e17ce4717..0358f3a3e 100644 --- a/operational_guides/access_control_departmental_example.rst +++ b/operational_guides/access_control_departmental_example.rst @@ -120,12 +120,14 @@ After the group roles have been created, you can now create user roles for each GRANT LOGIN TO ecodd; GRANT PASSWORD 'Passw0rd!' TO ecodd; GRANT CONNECT ON DATABASE my_database TO ecodd; + GRANT USAGE ON SERVICE sqream TO ecodd; GRANT my_schema_database_designers TO ecodd; CREATE ROLE ebachmann; GRANT LOGIN TO ebachmann; GRANT PASSWORD 'Passw0rd!!!' TO ebachmann; GRANT CONNECT ON DATABASE my_database TO ebachmann; + GRANT USAGE ON SERVICE sqream TO ebachmann; GRANT my_database_designers TO ebachmann; -- If a user already exists, we can assign that user directly to the group @@ -138,18 +140,21 @@ After the group roles have been created, you can now create user roles for each GRANT LOGIN TO jbarker; GRANT PASSWORD 'action_jacC%k' TO jbarker; GRANT CONNECT ON DATABASE my_database TO jbarker; + GRANT USAGE ON SERVICE sqream TO jbarker; GRANT my_schema_readers TO jbarker; CREATE ROLE lbream; GRANT LOGIN TO lbream; GRANT PASSWORD 'artichoke123O$' TO lbream; GRANT CONNECT ON DATABASE my_database TO lbream; + GRANT USAGE ON SERVICE sqream TO lbream; GRANT my_schema_readers TO lbream; CREATE ROLE pgregory; GRANT LOGIN TO pgregory; GRANT PASSWORD 'c1ca6aG$' TO pgregory; GRANT CONNECT ON DATABASE my_database TO pgregory; + GRANT USAGE ON SERVICE sqream TO pgregory; GRANT my_schema_readers TO pgregory; -- Create users in the security officers group @@ -158,6 +163,7 @@ After the group roles have been created, you can now create user roles for each GRANT LOGIN TO hoover; GRANT PASSWORD 'mint*Rchip' TO hoover; GRANT CONNECT ON DATABASE my_database TO hoover; + GRANT USAGE ON SERVICE sqream TO hoover; GRANT my_schema_security_officers TO hoover; From 12e6b1a8e02413626d1d142a6285d82c7cbf64fc Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:43:15 +0200 Subject: [PATCH 1716/1892] updated slide --- .../SQream_Architecture_Turbo Booster.png | Bin 0 -> 229586 bytes .../client_platforms/index.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 _static/images/SQream_Architecture_Turbo Booster.png diff --git a/_static/images/SQream_Architecture_Turbo Booster.png b/_static/images/SQream_Architecture_Turbo Booster.png new file mode 100644 index 0000000000000000000000000000000000000000..961cdd45d606e85252d49c05ba8656fd05a00d82 GIT binary patch literal 229586 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 UQ-4CQxI@5k2Nx{S&L`!+01{&e2mk;8 literal 0 HcmV?d00001 diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index 37451c115..aa4ca4bce 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -6,7 +6,7 @@ Client Platforms SQreamDB is designed to work with the most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. -.. figure:: /_static/images/connectivity_ecosystem.png +.. figure:: /_static/images/SQream_Architecture_Turbo Booster.png :align: right :width: 800 From 4a2756b7b63b6d20d9c033c0c5267493cd44e7f2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 4 Feb 2025 11:47:56 +0200 Subject: [PATCH 1717/1892] updated diagram --- ...cture_Turbo Booster.png => SQDBArchitecture.png} | Bin connecting_to_sqream/client_platforms/index.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename _static/images/{SQream_Architecture_Turbo Booster.png => SQDBArchitecture.png} (100%) diff --git a/_static/images/SQream_Architecture_Turbo Booster.png b/_static/images/SQDBArchitecture.png similarity index 100% rename from _static/images/SQream_Architecture_Turbo Booster.png rename to _static/images/SQDBArchitecture.png diff --git a/connecting_to_sqream/client_platforms/index.rst b/connecting_to_sqream/client_platforms/index.rst index aa4ca4bce..5c36ff281 100644 --- a/connecting_to_sqream/client_platforms/index.rst +++ b/connecting_to_sqream/client_platforms/index.rst @@ -6,7 +6,7 @@ Client Platforms SQreamDB is designed to work with the most common database tools and interfaces, allowing you direct access through a variety of drivers, connectors, visualization tools, and utilities. -.. figure:: /_static/images/SQream_Architecture_Turbo Booster.png +.. figure:: /_static/images/SQDBArchitecture.png :align: right :width: 800 From 24258515a2943321a751070b9ce859fca00a4319 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Feb 2025 14:41:07 +0200 Subject: [PATCH 1718/1892] CLI_2.2 --- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.10.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 5b408cd6a..286ce65e0 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.1-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.2-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All diff --git a/releases/4.10.rst b/releases/4.10.rst index c92da8ed1..4dd6d879a 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -30,7 +30,7 @@ Compatibility Matrix | | * SQLAlchemy 1.4 | | | * Spark 5.0.0 | | | * SQLoader As A Service 8.3.1 | -| | * Java CLI 2.1 | +| | * Java CLI 2.2 | +-------------------------+------------------------------------------------------------------------+ New Features and Enhancements From 4ba0b3f77188c7c3bfcb044b24e0209bfaefee0c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 11 Feb 2025 15:17:47 +0200 Subject: [PATCH 1719/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 286ce65e0..849c37124 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -64,7 +64,7 @@ Client Driver Downloads - - All * - **Tableau** - - `Tableau Connector <https://sq-ftp-public.s3.amazonaws.com/SQreamDB.taco>`_ + - `Tableau Connector <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqreamDB-v1.1.taco>`_ - :ref:`tableau` - - All From ab1ec03d9ba10525f21e859ad1334ec26240aede Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Thu, 13 Feb 2025 09:56:59 +0200 Subject: [PATCH 1720/1892] Update update.rst --- .../sql_statements/dml_commands/update.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/reference/sql/sql_statements/dml_commands/update.rst b/reference/sql/sql_statements/dml_commands/update.rst index ad2c149c8..79ffc7bf7 100644 --- a/reference/sql/sql_statements/dml_commands/update.rst +++ b/reference/sql/sql_statements/dml_commands/update.rst @@ -77,13 +77,13 @@ To be able to follow the examples, create these two tables: +----+--------+--------------+ | id | name | records_sold | +====+========+==============+ -| 1 | Israel | null | +| 1 | Israel | 0 | +----+--------+--------------+ -| 2 | UK | null | +| 2 | UK | 0 | +----+--------+--------------+ -| 3 | USA | null | +| 3 | USA | 0 | +----+--------+--------------+ -| 4 | Sweden | null | +| 4 | Sweden | 0 | +----+--------+--------------+ **bands** @@ -103,10 +103,10 @@ To be able to follow the examples, create these two tables: .. code-block:: postgres create or replace table countries ( id int, name text, records_sold int); - insert into countries values (1, 'Israel', null); - insert into countries values (2, 'UK', null); - insert into countries values (3, 'USA', null); - insert into countries values (4, 'Sweden', null); + insert into countries values (1, 'Israel', 0); + insert into countries values (2, 'UK', 0); + insert into countries values (3, 'USA', 0); + insert into countries values (4, 'Sweden', 0); create or replace table bands ( id int, name text, country_id int); insert into bands values (1, 'The Beatles', 2); @@ -178,7 +178,8 @@ The following shows an example of updating tables that contain multi-table expre Triggering a Cleanup -------------------- -When an ``UPDATE`` statement is executed, it creates a new table that contains the updated data, while the original table remains intact. As a result, residual data may be left behind, and a cleanup operation is necessary to ensure the database remains in a consistent state. +When an ``UPDATE`` statement is executed, it creates new chunks that contain the updated data. As a result, residual data may be left behind, and a cleanup operation is necessary to complete the physical removal of data. +This cleanup is usually done automatically overnight, but you can choose to do so yourself to remove the redundant files immediately. The following is the syntax for triggering a cleanup: From bb2a6b02be077a0771ddff7f4ac5fdce71eddc22 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:20:10 +0200 Subject: [PATCH 1721/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index aa75acaff..d1f0e04d4 100644 --- a/conf.py +++ b/conf.py @@ -32,7 +32,7 @@ # The full version, including alpha/beta/rc tags -release = '4.10' +release = '4.11' # -- General configuration --------------------------------------------------- From b69723830796fe398e03f5b37addda7ac7df869e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:32:48 +0200 Subject: [PATCH 1722/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 7890f4aa1..5aba8856b 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -307,7 +307,8 @@ Using the ``||`` (Concatenate) function with two different data types requires e ``UNNEST`` """""""""" -It is possible to use the ``UNNEST`` operator within a statement only once. +The ``UNNEST`` function is computationally intensive; therefore, it is recommended to use up to 10 ``UNNEST`` clauses per statement as a best practice. +To improve performance, consider filtering the SQL results before applying UNNEST to reduce data volume and optimize query runtime. Window """""" From e333b51827948b0ff164bab27e27bd744c4936bb Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:38:09 +0200 Subject: [PATCH 1723/1892] Update sql_data_type_array.rst --- data_type_guides/sql_data_type_array.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data_type_guides/sql_data_type_array.rst b/data_type_guides/sql_data_type_array.rst index 5aba8856b..03ccffec7 100644 --- a/data_type_guides/sql_data_type_array.rst +++ b/data_type_guides/sql_data_type_array.rst @@ -295,8 +295,8 @@ Please note that SQLAlchemy does not support the ``ARRAY`` data type. Functions --------- -``|| (Concatenate)`` -"""""""""""""""""""" +|| (Concatenate) +"""""""""""""""" Using the ``||`` (Concatenate) function with two different data types requires explicit casting. @@ -304,11 +304,11 @@ Using the ``||`` (Concatenate) function with two different data types requires e SELECT (clmn1, 4::tinyint) || (clmn2, 5::tinyint) FROM my_array; -``UNNEST`` -"""""""""" +UNNEST +"""""" The ``UNNEST`` function is computationally intensive; therefore, it is recommended to use up to 10 ``UNNEST`` clauses per statement as a best practice. -To improve performance, consider filtering the SQL results before applying UNNEST to reduce data volume and optimize query runtime. +To improve performance, consider filtering the results before applying ``UNNEST`` to reduce data volume and optimize query runtime. Window """""" From 4f662ae3a11e176cc822415480d8f3024e7cdd9e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 19 Feb 2025 13:24:42 +0200 Subject: [PATCH 1724/1892] 4.11 --- releases/4.0_index.rst | 1 + releases/4.11.rst | 120 +++++++++++++++++++++++++++++++++++++++++ releases/index.rst | 2 + 3 files changed, 123 insertions(+) create mode 100644 releases/4.11.rst diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index ff752a98e..a061d116f 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -20,3 +20,4 @@ 4.8 4.9 4.10 + 4.11 diff --git a/releases/4.11.rst b/releases/4.11.rst new file mode 100644 index 000000000..99696f2e1 --- /dev/null +++ b/releases/4.11.rst @@ -0,0 +1,120 @@ +.. _4.11: + +***************** +Release Notes 4.11 +***************** + +The 4.11 release notes were released on March 30th, 2025 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | RHEL 8.9 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 12.3.2 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 58 | ++-------------------------+------------------------------------------------------------------------+ +| Driver compatibility | * JDBC 5.4.2 | +| | * ODBC 4.4.4 | +| | * NodeJS 4.2.4 | +| | * .NET 5.0.0 | +| | * Pysqream 5.3.0 | +| | * SQLAlchemy 1.4 | +| | * Spark 5.0.0 | +| | * SQLoader As A Service 8.3.1 | +| | * Java CLI 2.2 | ++-------------------------+------------------------------------------------------------------------+ + +New Features and Enhancements +----------------------------- +► :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS``. + +► Enahnced Regular Expresseion (RegEx) support. + +► Python version for :ref:`Python User Defined Functions<python_functions>` has been upgraded to Python 3.11. + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.11 resolved Issues +--------------------------- + ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker abnormal behavior | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18797 | Worker failure leaves orphan locks | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18555 | Enhance set parameter command efficiency | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18504 | Access Control Permissions - Functions | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-18253 | A network insert query fails | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-16436 | Right function error | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-14398 | Improve orphan locks handling | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + + + +Deprecations +------------------- + +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. + +* REHL 8.x is now officially supported. + +► **DateTime2 Alias** + +Starting April 2025, The alias ``DateTime2`` for the ``DateTime`` Data Type is being deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. While ``DateTime2`` will remain functional as an alias until April 2025, we recommend updating your code to use ``DateTime`` directly to ensure compatibility. + +Upgrading to Version 4.11 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/index.rst b/releases/index.rst index 26a85c6e5..ed054b96b 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,8 @@ Release Notes ************* +:ref:`Version 4.11 - March 30, 2025<4.11>` + :ref:`Version 4.10 - January 20, 2025<4.10>` :ref:`Version 4.9 - November 28, 2024<4.9>` From 58c9a3738361413079cbc8cee8e8e8b8e8a97125 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 08:08:35 +0200 Subject: [PATCH 1725/1892] Update 4.11.rst --- releases/4.11.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index 99696f2e1..fd58a41af 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -85,7 +85,7 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re ► **DateTime2 Alias** -Starting April 2025, The alias ``DateTime2`` for the ``DateTime`` Data Type is being deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. While ``DateTime2`` will remain functional as an alias until April 2025, we recommend updating your code to use ``DateTime`` directly to ensure compatibility. +As of April 2025, The alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. Upgrading to Version 4.11 ------------------------- From 1410c23c062fdb63432fa4cada4c59857e1cb1e1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 08:49:24 +0200 Subject: [PATCH 1726/1892] DateTime2 --- .../converting_and_casting_types.rst | 2 + data_type_guides/sql_data_types_date.rst | 4 +- data_type_guides/sql_data_types_datetime2.rst | 80 +++++++++++++++++++ .../sql_data_types_primitives.rst | 7 +- data_type_guides/supported_casts.rst | 1 + 5 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 data_type_guides/sql_data_types_datetime2.rst diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index fab954ee1..2dea391dd 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -60,6 +60,8 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **DATE**/**DATETIME** | ✗ | ✗ | ✗ | ✗ | N/A | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ +| **DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ | **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ diff --git a/data_type_guides/sql_data_types_date.rst b/data_type_guides/sql_data_types_date.rst index 33b3f7ec5..f4bcf7421 100644 --- a/data_type_guides/sql_data_types_date.rst +++ b/data_type_guides/sql_data_types_date.rst @@ -40,7 +40,7 @@ Syntax ``DATE`` values are formatted as string literals. -The following is an example of the DATETIME syntax: +The following is an example of the DATE syntax: .. code-block:: console @@ -64,7 +64,7 @@ SQream attempts to guess if the string literal is a date or datetime based on co Size ^^^^^^ -A ``DATE`` column is 4 bytes in length, while a ``DATETIME`` column is 8 bytes in length. +A ``DATE`` column is 4 bytes, while a ``DATETIME`` column is 8 bytes. However, the size of these values is compressed by SQream DB. diff --git a/data_type_guides/sql_data_types_datetime2.rst b/data_type_guides/sql_data_types_datetime2.rst new file mode 100644 index 000000000..ada2a553f --- /dev/null +++ b/data_type_guides/sql_data_types_datetime2.rst @@ -0,0 +1,80 @@ +.. _sql_data_types_date: + +************************* +DateTime2 +************************* + +``DATETIME2`` is a type designed for storing year, month, day, hour, minute, seconds, milliseconds, microseconds, nanoseconds and UTC offset with 1 nanosecond precision. + + +Aliases +^^^^^^^^^^ + +NA + + +Syntax +^^^^^^^^ + +``DATETIME2`` values are formatted as string literals. + +The following is an example of the DATETIME2 syntax: + +.. code-block:: console + + ``1955-11-05 01:24:00.000000000 +00:00:00`` + + +``DATETIME2`` values are formatted as string literals conforming to `ISO 8601 <https://en.wikipedia.org/wiki/ISO_8601>`_. + +SQream attempts to guess if the string literal is a datetime2 based on context, for example when used in date-specific functions. + +Size +^^^^^^ + +A ``DATETIME2`` column is 16 bytes. + +However, the size of these values is compressed by SQream DB. + +Date Examples +^^^^^^^^^^^^^ + +The following is an example of the Date syntax: + +.. code-block:: postgres + + CREATE TABLE important_dates (a DATETIME2); + + INSERT INTO important_dates VALUES ('1955-11-05 01:24:00.000000000 -08:00:00'); + + SELECT * FROM important_dates; + +The following is an example of the correct output: + +.. code-block:: text + + 1955-11-05 01:24:00.000000000 -08:00:00 + + + +Date Casts and Conversions +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following table shows the possible ``DATETIME2`` value conversions: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Type + - Details + * - ``TEXT`` + - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` + * - Type + - Details + * - ``DATE`` + - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'`` + * - Type + - Details + * - ``DATETIME`` + - ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` \ No newline at end of file diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index 7a76dbe8e..cb9076947 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -69,5 +69,10 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da - Date and time pairing in UTC - 8 bytes - ``'1955-11-05 01:24:00.000'`` - - ``TIMESTAMP``, ``DATETIME2`` + - ``TIMESTAMP`` + * - ``DATETIME2`` + - Date and time in nanosecond precision including UTC offset + - 16 bytes + - ``'1955-11-05 01:24:00.000000000 +00:00:00'`` + - NA diff --git a/data_type_guides/supported_casts.rst b/data_type_guides/supported_casts.rst index a6b7a3a32..4c0bb08f2 100644 --- a/data_type_guides/supported_casts.rst +++ b/data_type_guides/supported_casts.rst @@ -16,3 +16,4 @@ The **Supported Casts** section describes supported casts for the following type sql_data_types_floating_point sql_data_types_string sql_data_types_date + sql_data_types_datetime2 From 79244c329fe677b63666179ef733963e70fa896b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 08:59:15 +0200 Subject: [PATCH 1727/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 32 +++++++++---------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 2dea391dd..7ebc18398 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,23 +47,21 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME** | **VARCHAR**/**TEXT** | -+==============================================+===========+==============================================+=================+==============+========================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **DATE**/**DATETIME** | ✗ | ✗ | ✗ | ✗ | N/A | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ -| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+------------------------+-----------------------+ ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **VARCHAR**/**TEXT** | ++==============================================+===========+==============================================+=================+==============+======================================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ +| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ Value Dependent Conversions --------------------------- From fbdc0d6ae8bb3010d9b992fa7cf084e4f23fcc3b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:05:47 +0200 Subject: [PATCH 1728/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 7ebc18398..cf7c0a7d3 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,17 +50,17 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ | **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **VARCHAR**/**TEXT** | +==============================================+===========+==============================================+=================+==============+======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ Value Dependent Conversions From 2ebc3f7d06a1b9e49f8ce64ffa871a535845433b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:10:20 +0200 Subject: [PATCH 1729/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index cf7c0a7d3..23a790ddc 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,17 +50,17 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ | **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **VARCHAR**/**TEXT** | +==============================================+===========+==============================================+=================+==============+======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ Value Dependent Conversions From b714dab47fa8a596b4d04d584376253e6d06c16d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:16:00 +0200 Subject: [PATCH 1730/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 23a790ddc..e31e970dd 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -63,6 +63,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra | **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ + Value Dependent Conversions --------------------------- From 4914e36fc122e391cc464ef984702bbde4c62886 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:27:24 +0200 Subject: [PATCH 1731/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index e31e970dd..75699f9f4 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,21 +47,21 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **VARCHAR**/**TEXT** | -+==============================================+===========+==============================================+=================+==============+======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ -| **VARCHAR**/**TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+----------------------------------------------+-----------+----------------------------------------------+-----------------+--------------+--------------------------------------+-----------------------+ ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | ++===============================================+===========+===============================================+===================+===============+=======================================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **VARCHAR** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ Value Dependent Conversions From 19ccfc13dfca3357f59f55be8c786f98c27d000b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:31:48 +0200 Subject: [PATCH 1732/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 75699f9f4..604863e9f 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -60,7 +60,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ | **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **VARCHAR** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ From afa53f6de59ab099c2ecca2f1c4a20103fdcec6c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:01:32 +0200 Subject: [PATCH 1733/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 604863e9f..f96d237bd 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,21 +47,21 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | -+===============================================+===========+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | ++===============================================+===============+===============================================+===================+===============+=======================================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ Value Dependent Conversions From bfe027c501ff414b56e2eea6324c7214b5bc2df1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 13:49:53 +0200 Subject: [PATCH 1734/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 23 +++++++------------ 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index f96d237bd..a363bfbfc 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,21 +47,14 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | -+===============================================+===============+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| FROM / TO | BOOL | TINYINT/SMALLINT/INT/BIGINT | REAL/FLOAT | NUMERIC | DATE/DATETIME/DATETIME2 | TEXT | +|---|---|---|---|---|---|---| +| BOOL | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| TINYINT/SMALLINT/INT/BIGINT | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| REAL/FLOAT | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| NUMERIC | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| DATE/DATETIME/DATETIME2 | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| TEXT | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | Value Dependent Conversions From 107ed9bf594a01173022546f616a73aafbecb9f6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:00:09 +0200 Subject: [PATCH 1735/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index a363bfbfc..250adc5b4 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,14 +47,21 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -| FROM / TO | BOOL | TINYINT/SMALLINT/INT/BIGINT | REAL/FLOAT | NUMERIC | DATE/DATETIME/DATETIME2 | TEXT | -|---|---|---|---|---|---|---| -| BOOL | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -| TINYINT/SMALLINT/INT/BIGINT | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -| REAL/FLOAT | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -| NUMERIC | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -| DATE/DATETIME/DATETIME2 | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -| TEXT | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | ++===============================================+===============+===============================================+===================+===============+=======================================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ Value Dependent Conversions From 4c2e8dea29c37dee1e7a3579a4b9cd9a19f48210 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:04:30 +0200 Subject: [PATCH 1736/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 250adc5b4..f87d01540 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -48,19 +48,19 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +===============================================+===============+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ From 36333fa0c00b43c3e58151459334d8f8b064d0d6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:15:04 +0200 Subject: [PATCH 1737/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index f87d01540..a6430d1d0 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -48,19 +48,19 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +===============================================+===============+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ From c1a6d1c7235ec2a3fc244180e3a6ac5c9825842a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:23:16 +0200 Subject: [PATCH 1738/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index a6430d1d0..115e88b1c 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -48,19 +48,19 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | +===============================================+===============+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | +-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ From 39d5235ca7760340479c090568f3033b42ab1735 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:18:22 +0200 Subject: [PATCH 1739/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 115e88b1c..604863e9f 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,21 +47,21 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT/SMALLINT/INT/BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE/DATETIME/DATETIME2** | **TEXT** | -+===============================================+===============+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT/SMALLINT/INT/BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE/DATETIME/DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+-----------------------------------------------+---------------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | ++===============================================+===========+===============================================+===================+===============+=======================================+=======================+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ +| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | ++-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ Value Dependent Conversions From e121d7dc4e04c6e434c8e985c2f35e67ee7adcf4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:23:42 +0200 Subject: [PATCH 1740/1892] Update sql_data_types_datetime2.rst --- data_type_guides/sql_data_types_datetime2.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/data_type_guides/sql_data_types_datetime2.rst b/data_type_guides/sql_data_types_datetime2.rst index ada2a553f..0bd00bbf6 100644 --- a/data_type_guides/sql_data_types_datetime2.rst +++ b/data_type_guides/sql_data_types_datetime2.rst @@ -70,11 +70,7 @@ The following table shows the possible ``DATETIME2`` value conversions: - Details * - ``TEXT`` - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` - * - Type - - Details * - ``DATE`` - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'`` - * - Type - - Details * - ``DATETIME`` - ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` \ No newline at end of file From 016281df0007067edd8ce391ba969480dc007891 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:35:59 +0200 Subject: [PATCH 1741/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 604863e9f..a3b318180 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,6 +47,20 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +* - **FROM / TO** + - **BOOL** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** +* - **BOOL** + - N/A + - ✓ + - ✗ + - ✗ + - ✗ + - ✓ +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ | **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | +===============================================+===========+===============================================+===================+===============+=======================================+=======================+ From f0a687d05407014eea3c8e190c475d395b17a70d Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:39:41 +0200 Subject: [PATCH 1742/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index a3b318180..b01ea12c1 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,6 +47,10 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +.. list-table:: + :widths: auto + :header-rows: 1 + * - **FROM / TO** - **BOOL** - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** @@ -61,6 +65,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - ✗ - ✗ - ✓ + +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ | **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | +===============================================+===========+===============================================+===================+===============+=======================================+=======================+ From 7f63616aa540bae8cb530e6badd4a376a946d56f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:43:10 +0200 Subject: [PATCH 1743/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index b01ea12c1..5b8a243f7 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -51,20 +51,20 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra :widths: auto :header-rows: 1 -* - **FROM / TO** - - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** -* - **BOOL** - - N/A - - ✓ - - ✗ - - ✗ - - ✗ - - ✓ + * - **FROM / TO** + - **BOOL** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** + * - **BOOL** + - N/A + - ✓ + - ✗ + - ✗ + - ✗ + - ✓ +-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ | **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | From 6a47b62c41397343a2e43f0b4f48a7ad7a7c4ac4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:47:51 +0200 Subject: [PATCH 1744/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 45 ++++++------------- 1 file changed, 14 insertions(+), 31 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 5b8a243f7..acaab5729 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -51,37 +51,20 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra :widths: auto :header-rows: 1 - * - **FROM / TO** - - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** - * - **BOOL** - - N/A - - ✓ - - ✗ - - ✗ - - ✗ - - ✓ - -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **FROM / TO** | **BOOL** | **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | **REAL/FLOAT** | **NUMERIC** | **DATE**/**DATETIME**/**DATETIME2** | **TEXT** | -+===============================================+===========+===============================================+===================+===============+=======================================+=======================+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TINYINT**/**SMALLINT**/**INT**/**BIGINT** | ✓ | N/A | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **REAL/FLOAT** | ✗ | ✓ | N/A | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **NUMERIC** | ✗ | ✓ | ✓ | ✓ | ✗ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **DATE**/**DATETIME**/**DATETIME2** | ✗ | ✗ | ✗ | ✗ | ✓ | ✓ | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ -| **TEXT** | ✓ | ✓ | ✓ | ✓ | ✓ | N/A | -+-----------------------------------------------+-----------+-----------------------------------------------+-------------------+---------------+---------------------------------------+-----------------------+ - + * - **FROM / TO** + - **BOOL** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** + * - **BOOL** + - N/A + - ✓ + - ✗ + - ✗ + - ✗ + - ✓ Value Dependent Conversions --------------------------- From a390643b1d7be427db17ffd26ea6431b30c239a5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:51:44 +0200 Subject: [PATCH 1745/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index acaab5729..c103e2a2f 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -56,14 +56,14 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - **REAL/FLOAT** - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** + - **DATE**/**DATETIME**/**DATETIME2** - **TEXT** * - **BOOL** - N/A - ✓ - ✗ - ✗ - - ✗ + - ✗ - ✓ Value Dependent Conversions From c80603af88d3751f98d170f01049ad7e34c4ca4c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 09:55:19 +0200 Subject: [PATCH 1746/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index c103e2a2f..ad5780db8 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -54,10 +54,10 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra * - **FROM / TO** - **BOOL** - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** + - **REAL/FLOAT** - **NUMERIC** - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** + - **TEXT** * - **BOOL** - N/A - ✓ From 1641e484231ed5547b1c441e2cfd010c8ee5825b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 10:03:59 +0200 Subject: [PATCH 1747/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index ad5780db8..538c0afe5 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -53,18 +53,11 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra * - **FROM / TO** - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** - * - **BOOL** - - N/A - - ✓ - - ✗ - - ✗ - - ✗ - - ✓ + - **TINYINT** / **SMALLINT** / **INT** / **BIGINT** + - **REAL / FLOAT** + - **NUMERIC** + - **DATE** / **DATETIME** / **DATETIME2** + - **TEXT** Value Dependent Conversions --------------------------- From 314275a384403c1979c1df9f7acfb779bdddcb20 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 10:27:22 +0200 Subject: [PATCH 1748/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 538c0afe5..abf7f66c0 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,17 +47,10 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -.. list-table:: - :widths: auto - :header-rows: 1 - - * - **FROM / TO** - - **BOOL** - - **TINYINT** / **SMALLINT** / **INT** / **BIGINT** - - **REAL / FLOAT** - - **NUMERIC** - - **DATE** / **DATETIME** / **DATETIME2** - - **TEXT** +| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | + Value Dependent Conversions --------------------------- From ce418a738e24872431ca6ec3f7d4cd8bac3baa0e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 10:32:27 +0200 Subject: [PATCH 1749/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index abf7f66c0..bacb4e130 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,9 +47,11 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. +|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | |---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| Value Dependent Conversions From a50cc3b02075ff49f1b68bae17474af80e67321c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 10:40:09 +0200 Subject: [PATCH 1750/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index bacb4e130..7adf01535 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,11 +47,11 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| ++---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | -|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -|---------------|----------|----------------------------------------------------|------------------|-------------|-----------------------------------------|----------| ++===============+==========+====================================================+==================+=============+=========================================+==========+ +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | ++---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ Value Dependent Conversions From 66aa0c6b2fe4b6afe53b8ed69068f6b805477311 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 11:30:14 +0200 Subject: [PATCH 1751/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 7adf01535..c0450e657 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ From 9180900100ad28f21157e8460c6589ff0403de86 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 11:37:06 +0200 Subject: [PATCH 1752/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index c0450e657..9f11fe8ac 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,8 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ + Value Dependent Conversions From cc3224b458c183b8b4102f7e59668e6879d30a0b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 11:45:08 +0200 Subject: [PATCH 1753/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 9f11fe8ac..9f7ad48f2 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,8 +50,8 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ - - +| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | ++---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ Value Dependent Conversions --------------------------- From c8e95151b25217e2edd413fd040420db9eda1dd7 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 11:53:45 +0200 Subject: [PATCH 1754/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 9f7ad48f2..ff6ed0b0c 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ -| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ Value Dependent Conversions From aadf32ab7ffd766ff24fe4dd56ab9dff959d3dfe Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 11:57:07 +0200 Subject: [PATCH 1755/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index ff6ed0b0c..7c82f5b33 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ Value Dependent Conversions From 40d93d3ea4ba330b3b64e6ea73b7602aa8c70eb9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:06:33 +0200 Subject: [PATCH 1756/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 7c82f5b33..150839778 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -53,6 +53,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra | **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ + Value Dependent Conversions --------------------------- From 8b973ea84a743aedd9db04b10fd23eec497f30aa Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:15:45 +0200 Subject: [PATCH 1757/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 150839778..7a51073fb 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+=============+=========================================+==========+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | +---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ From 2cc5dec66abaffe1a7052ac677871fb763c06a4f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:39:46 +0200 Subject: [PATCH 1758/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 7a51073fb..100ce57a8 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,11 +47,11 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ -| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | -+===============+==========+====================================================+==================+=============+=========================================+==========+ -| **BOOL** | N/A | ✓ | ✗ | ✗ | ✗ | ✓ | -+---------------+----------+----------------------------------------------------+------------------+-------------+-----------------------------------------+----------+ ++---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ +| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | ++===============+==========+====================================================+==================+===============+=========================================+===========+ +| **BOOL** | N/A | Supported | Not Supported | Not Supported | Not Supported | Supported | ++---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ Value Dependent Conversions From 000fa2138d9c7ab5cf53e34d52d619d11c6e17b9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:44:04 +0200 Subject: [PATCH 1759/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 100ce57a8..9021057b6 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | Supported | Not Supported | Not Supported | Not Supported | Supported | +| **BOOL** | N/A | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From 92aa1c78df08f792326f3900cabd4ca9152faba6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:47:28 +0200 Subject: [PATCH 1760/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 9021057b6..3b672781a 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +| **BOOL** | N/A | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | ✗ | ✗ | ✗ | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From 7804dd96067e41859e4d1609a1a26eebba01bbf4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:50:38 +0200 Subject: [PATCH 1761/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 3b672781a..d66abb481 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | ✗ | ✗ | ✗ | **TEXT** | +| **BOOL** | N/A | ✓ | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From 9de31aaee3d4bc958b6477e45f36351c1bd75719 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:53:35 +0200 Subject: [PATCH 1762/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index d66abb481..e3e9665f5 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | ✓ | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +| **BOOL** | N/A | ✓ | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From f6e4fc4a46e80a9a1e17ad0f8b3b05ed7d9c63e2 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 12:56:38 +0200 Subject: [PATCH 1763/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index e3e9665f5..4f154dc1c 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | ✓ | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +| **BOOL** | N/A | ✓ | ✗ | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From f58523e4b4b2f52aa6087c458a35d173204fad46 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 14:29:21 +0200 Subject: [PATCH 1764/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 4f154dc1c..aa1f9000c 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -50,7 +50,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ | **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | ✓ | ✗ | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +| **BOOL** | N/A | ✓ | ✗ | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | +---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ From c2098e2ff9a6328070307afba1e73e689ebe0363 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 14:34:50 +0200 Subject: [PATCH 1765/1892] Encryption --- feature_guides/data_encryption.rst | 16 +++ feature_guides/data_encryption_methods.rst | 17 +++ feature_guides/data_encryption_overview.rst | 18 +++ feature_guides/data_encryption_syntax.rst | 121 ++++++++++++++++++++ feature_guides/data_encryption_types.rst | 14 +++ feature_guides/index.rst | 1 + 6 files changed, 187 insertions(+) create mode 100644 feature_guides/data_encryption.rst create mode 100644 feature_guides/data_encryption_methods.rst create mode 100644 feature_guides/data_encryption_overview.rst create mode 100644 feature_guides/data_encryption_syntax.rst create mode 100644 feature_guides/data_encryption_types.rst diff --git a/feature_guides/data_encryption.rst b/feature_guides/data_encryption.rst new file mode 100644 index 000000000..c38d126fc --- /dev/null +++ b/feature_guides/data_encryption.rst @@ -0,0 +1,16 @@ +.. _data_encryption: + +*********************** +Data Encryption +*********************** +The **Data Encryption** page describes the following: + + +.. toctree:: + :maxdepth: 1 + :titlesonly: + + data_encryption_overview + data_encryption_methods + data_encryption_types + data_encryption_syntax \ No newline at end of file diff --git a/feature_guides/data_encryption_methods.rst b/feature_guides/data_encryption_methods.rst new file mode 100644 index 000000000..250ca06de --- /dev/null +++ b/feature_guides/data_encryption_methods.rst @@ -0,0 +1,17 @@ +.. _data_encryption_methods: + +*********************** +Encryption Methods +*********************** +Data exists in one of following states and determines the encryption method: + + +Encrypting Data in Transit +---------------- +**Data in transit** refers to data you use on a regular basis, usually stored on a database and accessed through applications or programs. This data is typically transferred between several physical or remote locations through email or uploading documents to the cloud. This type of data must therefore be protected while **in transit**. SQream encrypts data in transit using SSL when, for example, users insert data files from external repositories over a JDBC or ODBC connection. + +For more information, see `Use TLS/SSL When Possible <../operational_guides/security.html#use-tls-ssl-when-possible>`_. + +Encrypting Data at Rest +---------------- +**Data at rest** refers to data stored on your hard drive or on the cloud. Because this data can be potentially intercepted **physically**, it requires a form of encryption that protects your data wherever you store it. SQream facilitates encryption by letting you encrypt any column. \ No newline at end of file diff --git a/feature_guides/data_encryption_overview.rst b/feature_guides/data_encryption_overview.rst new file mode 100644 index 000000000..3df4820a9 --- /dev/null +++ b/feature_guides/data_encryption_overview.rst @@ -0,0 +1,18 @@ +.. _data_encryption_overview: + +*********************** +Overview +*********************** +**Data Encryption** helps protect sensitive data at rest by concealing it from unauthorized users in the event of a breach. This is achieved by scrambling the content into an unreadable format based on encryption and decryption keys. Typically speaking, this data pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +Users encrypt their data on a column basis by specifying ``column_name`` in the encryption syntax. + +The demand for confidentiality has steadily increased to protect the growing volumes of private data stored on computer systems and transmitted over the internet. To this end, regulatory bodies such as the **General Data Protection Regulation (GDPR)** have produced requirements to standardize and enforce compliance aimed at protecting customer data. + +SQream enables customers to implement a-Symmetric Encryption solution using Secret Keys that they provide and manage themselves. +The chosen encryption algorithm is AES-256, known for its strength and security. It is crucial to ensure that the Secret Key length is precisely 256 bits or 32 bytes. + + +For more information on the encryption syntax, see :ref:`data_encryption_syntax`. + +For more information on GDPR compliance requirements, see the `GDPR checklist <https://gdpr.eu/checklist/>`_. \ No newline at end of file diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst new file mode 100644 index 000000000..ff1628891 --- /dev/null +++ b/feature_guides/data_encryption_syntax.rst @@ -0,0 +1,121 @@ +.. _data_encryption_syntax: + +*********************** +Syntax +*********************** +Encrypting columns in a new table + +.. code-block:: psql + + CREATE TABLE <table name> ( + <column_name> <data_type> ENCRYPT, + <column_name> <data_type> NULL ENCRYPT, + <column_name> <data_type> NOT NULL ENCRYPT + ); + +Adding an encrypted column to an existing table + +.. code-block:: psql + + ALTER TABLE <table_name> ADD COLUMN <column_name> <data_type> ENCRYPT; + + +Encryption methods + +.. code-block:: psql + + ENCRYPT ( <column name to encrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + + +Decryption method + +.. code-block:: psql + + DECRYPT ( <column name to decrypt> , <Secret Key of exactly 256-bit (32-byte) length> ) + +*********************** +Examples +*********************** + +Encrypting a new table + +.. code-block:: psql + + CREATE TABLE client_name ( + id BIGINT NOT NULL ENCRYPT, + first_name TEXT ENCRYPT, + last_name TEXT, + salary INT ENCRYPT); + +Inserting encrypt player salary (``INT`` data type) + +.. code-block:: psql + + INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) + VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); + +Similar example using ``COPY FROM`` + +.. code-block:: psql + + COPY NBA + ( + player_name, team_name, jersey_number, position, age, height, weight, college, + ENCRYPT (salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + ) + FROM WRAPPER csv_fdw + OPTIONS + (location = '/tmp/source_file.csv', quote='@'); + +Query the encrypted data + +.. code-block:: psql + + SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') FROM NBA + WHERE player_name ='Jayson Christopher Tatum'; + + player_name |salary | + ------------------------+----------+ + Jayson Christopher Tatum|1500000 | + +Query the encrypted data using ``WHERE`` clause on an encrypted column + +.. code-block:: psql + + SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + FROM NBA + WHERE DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') > 1000000; + + player_name |salary | + ------------------------+----------+ + Jayson Christopher Tatum|1500000 | + ------------------------+----------+ + Marcus Smart |1350000 | + +Example of ``COPY TO`` using ``DECRYPT`` + +.. code-block:: psql + + COPY + (SELECT player_name, DECRYPT( salary, '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f') + FROM NBA + WHERE player_name ='Jayson Christopher Tatum') + TO WRAPPER parquet_fdw + OPTIONS (LOCATION = '/tmp/file.parquet'); + + +*********************** +Limitations +*********************** +* The following functionality is not supported by the encryption feature: ``Catalog queries``, ``Utility commands``, ``Foreign Tables``, ``Create AS SELECT``. +* A single encryption key must be used per column - using a different key would result in an error. +* Compression of encrypted columns is limited to the following types: ``Flat``, ``LZ4``, ``PD4``, ``DICT``, ``RLE``. +* This feature is not backward compatible with previous versions of SQreamDB. +* The encryption feature affect performance and compression. + + + +*********************** +Permissions +*********************** +The Data Encryption feature does not require a specific permission, users with relevant **TABLE** and **COLUMN** `permissions <../operational_guides/access_control_permissions.html#permissions>`_ may utilize it. \ No newline at end of file diff --git a/feature_guides/data_encryption_types.rst b/feature_guides/data_encryption_types.rst new file mode 100644 index 000000000..a42d22da9 --- /dev/null +++ b/feature_guides/data_encryption_types.rst @@ -0,0 +1,14 @@ +.. _data_encryption_types: + +*********************** +Data Types +*********************** +Typically speaking, sensitive pertains to **PII (Personally Identifiable Information)**, which is sensitive information such as credit card numbers and other information related to an identifiable person. + +SQream's data encryption feature supports encrypting column-based data belonging to the following data types: + +* ``INT`` +* ``BIGINT`` +* ``TEXT`` + +For more information on the above data types, see :ref:`supported_data_types`. \ No newline at end of file diff --git a/feature_guides/index.rst b/feature_guides/index.rst index 672d7d423..c94069c6b 100644 --- a/feature_guides/index.rst +++ b/feature_guides/index.rst @@ -15,3 +15,4 @@ The **Feature Guides** section describes background processes that SQreamDB uses python_functions workload_manager concurrency_and_locks + data_encryption \ No newline at end of file From c90306d40349b9af2285652d70b3fdf663b47120 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 14:49:12 +0200 Subject: [PATCH 1766/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index aa1f9000c..29804f030 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -47,11 +47,17 @@ Supported Casts The listed table of supported casts also applies to the :ref:`sql_data_type_array` data type. For instance, you can cast a ``NUMERIC[]`` array to a ``TEXT[]`` array. -+---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ -| **FROM / TO** | **BOOL** | **TINYINT** / **SMALLINT** / **INT** / **BIGINT** | **REAL / FLOAT** | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | -+===============+==========+====================================================+==================+===============+=========================================+===========+ -| **BOOL** | N/A | ✓ | ✗ | **NUMERIC** | **DATE** / **DATETIME** / **DATETIME2** | **TEXT** | -+---------------+----------+----------------------------------------------------+------------------+---------------+-----------------------------------------+-----------+ +.. list-table:: + :widths: auto + :header-rows: 1 + + * - **FROM / TO** + - **BOOL** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** Value Dependent Conversions From 058d5e2229ee0de7e7e55c7f38c527ae450c538b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 14:59:12 +0200 Subject: [PATCH 1767/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 29804f030..6e192cc8b 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -58,7 +58,13 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - **NUMERIC** - **DATE**/**DATETIME**/**DATETIME2** - **TEXT** - + * - **FROM / TO** + - **BOOL** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** Value Dependent Conversions --------------------------- From e832a822127a4fe80d1501f5fba8cc24a13e22bd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:02:19 +0200 Subject: [PATCH 1768/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 6e192cc8b..f713256a8 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -53,18 +53,18 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra * - **FROM / TO** - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** * - **FROM / TO** - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** + - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - **REAL/FLOAT** + - **NUMERIC** + - **DATE**/**DATETIME**/**DATETIME2** + - **TEXT** Value Dependent Conversions --------------------------- From ab2c55deed5ebbdc934d875b10338ec2258860a9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:05:22 +0200 Subject: [PATCH 1769/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index f713256a8..81d52c34b 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -57,7 +57,7 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - **REAL/FLOAT** - **NUMERIC** - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** + - **TEXT** * - **FROM / TO** - **BOOL** - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** From a83e26dce2aa7a3df175640038a9c25d4302f2db Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:10:22 +0200 Subject: [PATCH 1770/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 81d52c34b..d9bc27b75 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -58,13 +58,13 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - **NUMERIC** - **DATE**/**DATETIME**/**DATETIME2** - **TEXT** - * - **FROM / TO** - - **BOOL** - - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** - - **REAL/FLOAT** - - **NUMERIC** - - **DATE**/**DATETIME**/**DATETIME2** - - **TEXT** + * - **BOOL** + - N/A + - ✓ + - ✗ + - ✗ + - ✗ + - ✓ Value Dependent Conversions --------------------------- From 5f26c092896a1e3473ce8401e37ed0b610120531 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:14:28 +0200 Subject: [PATCH 1771/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index d9bc27b75..491fc24e6 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -65,6 +65,13 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - ✗ - ✗ - ✓ + * - **TINYINT**/**SMALLINT**/**INT**/**BIGINT** + - ✓ + - N/A + - ✓ + - ✓ + - ✗ + - ✓ Value Dependent Conversions --------------------------- From 9b10c1639bb012c90a21156b062791b1d0c35e25 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:18:10 +0200 Subject: [PATCH 1772/1892] Update converting_and_casting_types.rst --- .../converting_and_casting_types.rst | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 491fc24e6..2bddc2da0 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -72,6 +72,27 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - ✓ - ✗ - ✓ + * - **REAL/FLOAT** + - ✗ + - ✓ + - N/A + - ✓ + - ✗ + - ✓ + * - **NUMERIC** + - ✗ + - ✓ + - ✓ + - ✓ + - ✗ + - ✓ + * - **DATE**/**DATETIME**/**DATETIME2** + - ✗ + - ✗ + - ✗ + - ✗ + - ✓ + - ✓ Value Dependent Conversions --------------------------- From 0baa84b7b0a95b45376964c2746ca05cc939901a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 23 Feb 2025 16:21:01 +0200 Subject: [PATCH 1773/1892] Update converting_and_casting_types.rst --- data_type_guides/converting_and_casting_types.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/data_type_guides/converting_and_casting_types.rst b/data_type_guides/converting_and_casting_types.rst index 2bddc2da0..ba9efc9fd 100644 --- a/data_type_guides/converting_and_casting_types.rst +++ b/data_type_guides/converting_and_casting_types.rst @@ -93,6 +93,13 @@ The listed table of supported casts also applies to the :ref:`sql_data_type_arra - ✗ - ✓ - ✓ + * - **TEXT** + - ✓ + - ✓ + - ✓ + - ✓ + - ✓ + - N/A Value Dependent Conversions --------------------------- From b24301a1a3befd31e91c4ac271d7b0520c50a59f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 2 Mar 2025 09:33:52 +0200 Subject: [PATCH 1774/1892] Update sql_data_types_datetime2.rst --- data_type_guides/sql_data_types_datetime2.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/data_type_guides/sql_data_types_datetime2.rst b/data_type_guides/sql_data_types_datetime2.rst index 0bd00bbf6..5ff081ed0 100644 --- a/data_type_guides/sql_data_types_datetime2.rst +++ b/data_type_guides/sql_data_types_datetime2.rst @@ -22,7 +22,7 @@ The following is an example of the DATETIME2 syntax: .. code-block:: console - ``1955-11-05 01:24:00.000000000 +00:00:00`` + ``1955-11-05 01:24:00.000000000 +00:00`` ``DATETIME2`` values are formatted as string literals conforming to `ISO 8601 <https://en.wikipedia.org/wiki/ISO_8601>`_. @@ -45,7 +45,7 @@ The following is an example of the Date syntax: CREATE TABLE important_dates (a DATETIME2); - INSERT INTO important_dates VALUES ('1955-11-05 01:24:00.000000000 -08:00:00'); + INSERT INTO important_dates VALUES ('1955-11-05 01:24:00.000000000 -08:00'); SELECT * FROM important_dates; @@ -53,7 +53,9 @@ The following is an example of the correct output: .. code-block:: text - 1955-11-05 01:24:00.000000000 -08:00:00 +| a | ++--------------------------------+ +| 1955-11-05 01:24:00.000 -0800| @@ -69,8 +71,8 @@ The following table shows the possible ``DATETIME2`` value conversions: * - Type - Details * - ``TEXT`` - - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` + - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00'``, ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00'`` * - ``DATE`` - - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00:00'`` + - ``'1997-01-01'`` → ``'1997-01-01 00:00:00.000000 +00:00'`` * - ``DATETIME`` - - ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00:00'`` \ No newline at end of file + - ``'1955-11-05 01:24'`` → ``'1955-11-05 01:24:00.000000 +00:00'`` \ No newline at end of file From be80b8aa982d82e0336b0ad5ab3c609459b309cd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 2 Mar 2025 09:58:49 +0200 Subject: [PATCH 1775/1892] Update sql_data_types_datetime2.rst --- data_type_guides/sql_data_types_datetime2.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data_type_guides/sql_data_types_datetime2.rst b/data_type_guides/sql_data_types_datetime2.rst index 5ff081ed0..004bffc84 100644 --- a/data_type_guides/sql_data_types_datetime2.rst +++ b/data_type_guides/sql_data_types_datetime2.rst @@ -53,9 +53,7 @@ The following is an example of the correct output: .. code-block:: text -| a | -+--------------------------------+ -| 1955-11-05 01:24:00.000 -0800| + 1955-11-05 01:24:00.000 -0800 From b6987c2ccbe44a233faa8c48f945f89cdc4201ca Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 5 Mar 2025 12:40:05 +0200 Subject: [PATCH 1776/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 849c37124..3856ebb4e 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -54,10 +54,15 @@ Client Driver Downloads - - All * - **Python** - - `pysqream v5.3.0 <https://github.com/SQream/pysqream/releases>`_ + - `pysqream <https://pypi.org/project/pysqream/>`_ - :ref:`pysqream` - Recommended installation via ``pip`` - All + * - **Python-SQLAlchemy** + - `pysqream-sqlalchemy <https://pypi.org/project/pysqream-sqlalchemy/>`_ + - :ref:`pysqream<sqlalchemy>` + - Recommended installation via ``pip`` + - All * - **SQreamNet** - `.NET .dll file <https://sq-ftp-public.s3.amazonaws.com/SqreamNet6.0_v5.0.0.zip>`_ - :ref:`net` From fe387471ffcc290547e1dc0970db1b3c57761c24 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Mar 2025 08:54:12 +0200 Subject: [PATCH 1777/1892] Datetime2 functions --- .../date_and_time/datepart.rst | 18 ++++++++++-------- .../scalar_functions/numeric/trunc.rst | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst index a779663b5..1db3095b6 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst @@ -4,7 +4,7 @@ DATEPART ************************** -Extracts a date or time part from a ``DATE`` or ``DATETIME`` value. +Extracts a date or time part from a ``DATE``, ``DATETIME`` or ``DATETIME2`` value. .. note:: SQream DB also supports the ANSI :ref:`EXTRACT<extract>` syntax. @@ -27,6 +27,8 @@ Syntax | MINUTE | MI | N | SECOND | SS | S | MILLISECOND | MS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ @@ -40,7 +42,7 @@ Arguments * - ``interval`` - An interval representing a date part. See the table below or the syntax reference above for valid date parts * - ``date_expr`` - - A ``DATE`` or ``DATETIME`` expression + - A ``DATE``, ``DATETIME`` or ``DATETIME2`` expression Valid date parts @@ -86,6 +88,12 @@ Valid date parts * - ``MILLISECOND`` - ``MS`` - Milliseconds (0-999) + * - ``MICROSECOND`` + - ``MU`` + - Microseconds (0-999) + * - ``NANOSECOND`` + - ``NS`` + - Nanoseconds (0-999) .. note:: * The first day of the week is Sunday, when used with ``WEEKDAY``. @@ -95,12 +103,6 @@ Returns * An integer representing the date part value -Notes -======== - -* All date parts work on a ``DATETIME``. - -* The ``HOUR``, ``MINUTE``, ``SECOND``, and ``MILLISECOND`` date parts work only on ``DATETIME``. Using them on ``DATE`` will result in an error. Examples =========== diff --git a/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst b/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst index 643bfd6d9..75dc684b7 100644 --- a/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/numeric/trunc.rst @@ -6,7 +6,7 @@ TRUNC Rounds a number to its integer representation towards 0. -.. note:: This function is overloaded. The function :ref:`TRUNC<date_trunc>` can also modify the precision of ``DATE`` and ``DATETIME`` values. +.. note:: This function is overloaded. The function :ref:`TRUNC<date_trunc>` can also modify the precision of ``DATE``, ``DATETIME`` and ``DATETIME2`` values. See also :ref:`ROUND<round>`. From 82516a47e71615de726ae09ec9c34bc909209e0f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Mar 2025 08:59:21 +0200 Subject: [PATCH 1778/1892] datetime2 functions --- .../scalar_functions/date_and_time/dateadd.rst | 14 ++++++++++++-- .../scalar_functions/date_and_time/datepart.rst | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst index 240b0bf2e..25c8ccaab 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/dateadd.rst @@ -4,7 +4,7 @@ DATEADD ************************** -Adds or subtracts an interval to ``DATE`` or ``DATETIME`` value. +Adds or subtracts an interval to ``DATE`` , ``DATETIME`` or ``DATETIME2`` value. .. note:: SQream DB does not support the ``INTERVAL`` ANSI syntax. Use ``DATEADD`` to add or subtract date intervals. @@ -26,6 +26,8 @@ Syntax | MINUTE | MI | N | SECOND | SS | S | MILLISECOND | MS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ @@ -41,7 +43,7 @@ Arguments * - ``number`` - An integer expression * - ``date_expr`` - - A ``DATE`` or ``DATETIME`` expression + - A ``DATE`` , ``DATETIME`` or ``DATETIME2`` expression Valid date parts @@ -81,6 +83,12 @@ Valid date parts * - ``MILLISECOND`` - ``MS`` - Milliseconds (0-999) + * - ``MICROSECOND`` + - ``MU`` + - Microseconds (0-999) + * - ``NANOSECOND`` + - ``NS`` + - Nanoseconds (0-999) .. note:: * The first day of the week is Sunday, when used with ``weekday``. @@ -90,6 +98,8 @@ Returns * If ``HOUR``, ``MINUTE``, ``SECOND``, or ``MILLISECOND`` are added to a ``DATE``, the return type will be ``DATETIME``. +* If ``MICROSECOND`` or ``NANOSECOND`` are added to a ``DATE`` or ``DATETIME``, the return type will be ``DATETIME2``. + * For all other date parts, the return type is the same as the argument supplied. Notes diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst index 1db3095b6..8c3ccb0f3 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datepart.rst @@ -27,8 +27,8 @@ Syntax | MINUTE | MI | N | SECOND | SS | S | MILLISECOND | MS - | MICROSECOND | MU - | NANOSECOND | NS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ From a87d4cac3d2ec1e19da2f75e616cc074b43eeaad Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:01:14 +0200 Subject: [PATCH 1779/1892] Create current_timestamp2.rst --- .../date_and_time/current_timestamp2.rst | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 reference/sql/sql_functions/scalar_functions/date_and_time/current_timestamp2.rst diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/current_timestamp2.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/current_timestamp2.rst new file mode 100644 index 000000000..c47947ca6 --- /dev/null +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/current_timestamp2.rst @@ -0,0 +1,63 @@ +.. _current_timestamp2: + +************************** +CURRENT_TIMESTAMP2 +************************** + +Returns the current date and time of the system. + +.. note:: This function has a special ANSI SQL form and can be called without parentheses. + +Syntax +========== + +.. code-block:: postgres + + CURRENT_TIMESTAMP2() --> DATETIME2 + + CURRENT_TIMESTAMP2 --> DATETIME2 + +Arguments +============ + +None + +Returns +============ + +The current system date and time, with type ``DATETIME2``. + +Notes +======== + +* This function has a special ANSI SQL form and can be called without parentheses. + +* Aliases to this function include :ref:`SYSDATE2<sysdate2>` and :ref:`GETDATE2<getdate2>`. + +* To get the date only, see :ref:`CURRENT_DATE<current_date>`. + +Examples +=========== + +Get the current system date and time +---------------------------------------- + +.. code-block:: psql + + master=> SELECT CURRENT_TIMESTAMP2, CURRENT_TIMESTAMP2(), SYSDATE2, GETDATE2(); + getdate0 | getdate1 | getdate2 | getdate3 + -------------------------------------+--------------------------------------+--------------------------------------+------------------------------------- + 2019-12-07 23:04:26.300032671 +02:00 | 2019-12-07 23:04:26.300032671 +02:00 | 2019-12-07 23:04:26.300032671 +02:00 | 2019-12-07 23:04:26.300032671 +02:00 + + +Find events that happen before this month +-------------------------------------------- + +We will use :ref:`TRUNC<date_trunc>` to get the date at the beginning of this month, and then filter. + +.. code-block:: psql + + master=> SELECT COUNT(*) FROM cool_dates WHERE dt <= TRUNC(CURRENT_TIMESTAMP2, month); + count + ----- + 5 From b92ccf136950e7ae6785f85653cad47d9dceca36 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:11:31 +0200 Subject: [PATCH 1780/1892] Update index.rst --- reference/sql/sql_functions/scalar_functions/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/reference/sql/sql_functions/scalar_functions/index.rst b/reference/sql/sql_functions/scalar_functions/index.rst index 6183682ad..faeee6bd1 100644 --- a/reference/sql/sql_functions/scalar_functions/index.rst +++ b/reference/sql/sql_functions/scalar_functions/index.rst @@ -29,6 +29,7 @@ The **Built-In Scalar Functions** page describes functions that return one value * :ref:`curdate` * :ref:`current_date` * :ref:`current_timestamp` + * :ref:`current_timestamp2` * :ref:`dateadd` * :ref:`datediff` * :ref:`datepart` From 0c368771acd427862675e3ded85f071d5a0344d5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 08:18:03 +0200 Subject: [PATCH 1781/1892] Update current_method_configuration_levels.rst --- .../current_method_configuration_levels.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 0d79a3df2..00594f6ad 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -360,4 +360,10 @@ Flag List - Terminates queries that have exceeded a predefined time limit in the queue. - integer - Default value: 0. Minimum values: 1 minute. Maximum value: 4320 minutes (72 hours) + * - ``timezone`` + - Anyone + - Session + - The timezone flag dictates the timezone context used when SQDB encounters ``DATETIME2`` values during data ingestion. This includes overriding any existing timezone information within those values. + - Text + - Default value: ``null``. ``local`` local system timezone of the SQDB server. ``+hh:mm`` or ``-hh:mm`` explicitly defines the timezone for all incoming ``DATETIME2`` values, overriding any existing timezone information. From 9d8f3bfbca85de966b20d1613cd53ea776495661 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 08:32:17 +0200 Subject: [PATCH 1782/1892] datetime2 --- .../current_method_configuration_levels.rst | 6 ----- .../date_and_time/datediff.rst | 24 +++++++++++-------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index 00594f6ad..f0d0bb714 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -336,12 +336,6 @@ Flag List - Sets the hash table size of the CpuReduce. - uint - ``10000`` - * - ``externalTableBlobEstimate`` - - ? - - Session - - ? - - ? - - ? * - ``maxPinnedPercentageOfTotalRAM`` - SUPERUSER - Session diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index f5b37c79e..1fa49203a 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -4,7 +4,7 @@ DATEDIFF ************************** -Calculates the difference between two ``DATE`` or ``DATETIME`` expressions, in terms of a specific date part. +Calculates the difference between two ``DATE`` , ``DATETIME``or ``DATETIME2`` expressions, in terms of a specific date part. .. note:: Results are given in integers, rather than ``INTERVAL``, which SQream DB does not support. @@ -26,6 +26,8 @@ Syntax | MINUTE | MI | N | SECOND | SS | S | MILLISECOND | MS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ @@ -39,7 +41,7 @@ Arguments * - ``interval`` - An interval representing a date part. See the table below or the syntax reference above for valid date parts * - ``date_expr1``, ``date_expr2`` - - A ``DATE`` or ``DATETIME`` expression. The function calculates ``date_expr2 - date_expr1``. + - A ``DATE``, ``DATETIME`` or ``DATETIME2`` expression. The function calculates ``date_expr2 - date_expr1``. Valid date parts @@ -79,6 +81,12 @@ Valid date parts * - ``MILLISECOND`` - ``MS`` - Milliseconds (0-999) + * - ``MICROSECOND`` + - ``MU`` + - Microseconds (0-999) + * - ``NANOSECOND`` + - ``NS`` + - Nanoseconds (0-999) Returns @@ -104,7 +112,6 @@ For these examples, consider the following table and contents: INSERT INTO cool_dates VALUES ('Marty McFly goes back to this time','1955-11-05','1955-11-05 01:21:00.000') , ('Marty McFly came from this time', '1985-10-26', '1985-10-26 01:22:00.000') - , ('Vesuvius erupts', '79-08-24', '79-08-24 13:00:00.000') , ('1997 begins', '1997-01-01', '1997-01-01') , ('1997 ends', '1997-12-31','1997-12-31 23:59:59.999'); @@ -120,11 +127,10 @@ In years master=> SELECT d AS original_date, DATEDIFF(YEAR, CURRENT_DATE, d) AS "was ... years ago" FROM cool_dates; original_date | was ... years ago --------------+------------------ - 1955-11-05 | -64 - 1985-10-26 | -34 - 0079-08-24 | -1940 - 1997-01-01 | -22 - 1997-12-31 | -22 + 1955-11-05 | -70 + 1985-10-26 | -40 + 1997-01-01 | -28 + 1997-12-31 | -28 In days ^^^^^^^^^^^^^ @@ -136,7 +142,6 @@ In days --------------+----------------- 1955-11-05 | -23408 1985-10-26 | -12460 - 0079-08-24 | -708675 1997-01-01 | -8375 1997-12-31 | -8011 @@ -155,6 +160,5 @@ In hours --------------------+---------------------+------------------ 2019-12-07 22:35:50 | 1955-11-05 01:21:00 | -561813 2019-12-07 22:35:50 | 1985-10-26 01:22:00 | -299061 - 2019-12-07 22:35:50 | 0079-08-24 13:00:00 | -17008209 2019-12-07 22:35:50 | 1997-01-01 00:00:00 | -201022 2019-12-07 22:35:50 | 1997-12-31 23:59:59 | -192263 From f6a744bbd136cdffda9220439b8da4d5f1e0ed3b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 08:51:13 +0200 Subject: [PATCH 1783/1892] datetime2 --- .../scalar_functions/date_and_time/eomonth.rst | 6 +++--- .../scalar_functions/date_and_time/extract.rst | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst index 50bcf7410..bd7227f0d 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst @@ -4,9 +4,9 @@ EOMONTH ************************** -Returns a ``DATE`` or ``DATETIME`` value, reset to midnight on the last day of the month. +Returns a ``DATE`` , ``DATETIME` or ``DATETIME2`` value, reset to midnight on the last day of the month. -.. note:: This function is provided for SQL Server compatability. +.. note:: This function is provided for SQL Server compatibility. Syntax ========== @@ -26,7 +26,7 @@ Arguments * - Parameter - Description * - ``date_expr`` - - A ``DATE`` or ``DATETIME`` expression + - A ``DATE``, ``DATETIME` or ``DATETIME2`` expression Returns diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst index f0ca54a58..c3eb31412 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/extract.rst @@ -4,7 +4,7 @@ EXTRACT ************************** -Extracts a date or time part from a ``DATE`` or ``DATETIME`` value. +Extracts a date or time part from a ``DATE`` , ``DATETIME` or ``DATETIME2`` value. .. note:: SQream DB also supports the SQL Server :ref:`DATEPART<datepart>` syntax, which contains more date parts for use. @@ -25,6 +25,8 @@ Syntax | MINUTE | SECOND | MILLISECONDS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ @@ -38,7 +40,7 @@ Arguments * - ``interval`` - An interval representing a date part. See the table below or the syntax reference above for valid date parts * - ``date_expr`` - - A ``DATE`` or ``DATETIME`` expression + - A ``DATE`` , ``DATETIME`` or ``DATETIME2`` expression Valid date parts @@ -68,6 +70,12 @@ Valid date parts - Seconds (0.0-59.0) * - ``MILLISECONDS`` - Milliseconds (0.0-999.0) + * - ``MICROSECOND`` + - ``MU`` + - Microseconds (0-999) + * - ``NANOSECOND`` + - ``NS`` + - Nanoseconds (0-999) Returns ============ @@ -77,7 +85,9 @@ Returns Notes ======== -* The ``HOUR``, ``MINUTE``, ``SECOND``, and ``MILLISECOND`` date parts work only on ``DATETIME``. Using them on ``DATE`` will result in an error. +* The ``HOUR``, ``MINUTE``, ``SECOND``, and ``MILLISECOND`` date parts work on ``DATETIME`` or ``DATETIME2``. Using them on ``DATE`` will result in an error. +* The ``MICROSECOND`` and ``NANOSECOND`` date parts work only on ``DATETIME2``. Using them on ``DATE`` or ``DATETIME`` will result in an error. + Examples =========== From ea50e33f1c6cf6ad85e360c757a910294ba424b9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 08:56:51 +0200 Subject: [PATCH 1784/1892] datetime2 --- .../sql_functions/scalar_functions/date_and_time/datediff.rst | 2 +- .../sql_functions/scalar_functions/date_and_time/eomonth.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst index 1fa49203a..573312e89 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/datediff.rst @@ -4,7 +4,7 @@ DATEDIFF ************************** -Calculates the difference between two ``DATE`` , ``DATETIME``or ``DATETIME2`` expressions, in terms of a specific date part. +Calculates the difference between two ``DATE`` , ``DATETIME`` or ``DATETIME2`` expressions, in terms of a specific date part. .. note:: Results are given in integers, rather than ``INTERVAL``, which SQream DB does not support. diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst index bd7227f0d..04861df7e 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/eomonth.rst @@ -4,7 +4,7 @@ EOMONTH ************************** -Returns a ``DATE`` , ``DATETIME` or ``DATETIME2`` value, reset to midnight on the last day of the month. +Returns a ``DATE`` , ``DATETIME`` or ``DATETIME2`` value, reset to midnight on the last day of the month. .. note:: This function is provided for SQL Server compatibility. @@ -26,7 +26,7 @@ Arguments * - Parameter - Description * - ``date_expr`` - - A ``DATE``, ``DATETIME` or ``DATETIME2`` expression + - A ``DATE``, ``DATETIME`` or ``DATETIME2`` expression Returns From a556e0497cd91c3b10faf6715cc5e4aee7bc8345 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 09:09:05 +0200 Subject: [PATCH 1785/1892] Update trunc.rst --- .../scalar_functions/date_and_time/trunc.rst | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index c367a05b8..09757a7aa 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -4,12 +4,12 @@ Date and Time TRUNC ************************** -Truncates a ``DATE`` or ``DATETIME`` value to a specified resolution. +Truncates a ``DATE`` , ``DATETIME` or ``DATETIME2`` value to a specified resolution. For example, truncating a ``DATE`` down to the nearest month returns the date of the first day of the month. .. note:: * This function is overloaded. The function :ref:`TRUNC<trunc>` can also round numbers towards zero. - * Specifying the ``MILLISECOND`` interval with the ``TRUNC`` function is redundant, as there is nothing smaller than milliseconds. + * Specifying the ``NANOSECOND`` interval with the ``TRUNC`` function is redundant, as there is nothing smaller than nanoseconds. Syntax ========== @@ -28,6 +28,8 @@ Syntax | MINUTE | MI | N | SECOND | SS | S | MILLISECOND | MS + | MICROSECOND | MU + | NANOSECOND | NS Arguments ============ @@ -39,7 +41,7 @@ Arguments * - Parameter - Description * - ``date_expr`` - - A ``DATE`` or ``DATETIME`` expression + - A ``DATE`` , ``DATETIME`` or ``DATETIME2`` expression * - ``interval`` - An interval representing a date part. See the table below or the syntax reference above for valid date parts. If not specified, sets the value to to midnight and returns a ``DATETIME``. @@ -81,6 +83,12 @@ Valid date parts * - ``MILLISECOND`` - ``MS`` - Milliseconds (0-999) + * - ``MICROSECOND`` + - ``MU`` + - Microseconds (0-999) + * - ``NANOSECOND`` + - ``NS`` + - Nanoseconds (0-999) Returns ============ @@ -90,11 +98,13 @@ If no date part is specified, the return type is ``DATETIME``. Otherwise, the re Notes ======== -* All date parts work on a ``DATETIME``. +* All date parts work on a ``DATETIME2``. -* The ``HOUR``, ``MINUTE``, ``SECOND``, and ``MILLISECOND`` date parts work only on ``DATETIME``. Using them on ``DATE`` will result in an error. +* The ``HOUR``, ``MINUTE``, ``SECOND``, and ``MILLISECOND`` date parts work on ``DATETIME`` or ``DATETIME2``. Using them on ``DATE`` will result in an error. -* If no date part is specified, the ``DATE`` or ``DATETIME`` value will be set to midnight on the date value. See examples below +* The ``MICROSECOND`` and ``NANOSECOND`` date parts work only on ``DATETIME2``. Using them on ``DATE`` or ``DATETIME`` will result in an error. + +* If no date part is specified, the ``DATE``, ``DATETIME`` or ``DATETIME2`` value will be set to midnight on the date value. See examples below * See also :ref:`EOMONTH<eomonth>` to find the last day of the month. From ef38faba9c7536cf8db7e73684974e22981d4594 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 09:12:53 +0200 Subject: [PATCH 1786/1892] Update trunc.rst --- .../sql/sql_functions/scalar_functions/date_and_time/trunc.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst index 09757a7aa..628dc9ea0 100644 --- a/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst +++ b/reference/sql/sql_functions/scalar_functions/date_and_time/trunc.rst @@ -4,7 +4,7 @@ Date and Time TRUNC ************************** -Truncates a ``DATE`` , ``DATETIME` or ``DATETIME2`` value to a specified resolution. +Truncates a ``DATE`` , ``DATETIME`` or ``DATETIME2`` value to a specified resolution. For example, truncating a ``DATE`` down to the nearest month returns the date of the first day of the month. From ade5e789a89e930ae98d68096ff2a719d10b5e72 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 9 Mar 2025 09:45:30 +0200 Subject: [PATCH 1787/1892] Update 4.11.rst --- releases/4.11.rst | 37 +++++++++++-------------------------- 1 file changed, 11 insertions(+), 26 deletions(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index fd58a41af..019d2cfee 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -22,24 +22,12 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | Storage version | 58 | +-------------------------+------------------------------------------------------------------------+ -| Driver compatibility | * JDBC 5.4.2 | -| | * ODBC 4.4.4 | -| | * NodeJS 4.2.4 | -| | * .NET 5.0.0 | -| | * Pysqream 5.3.0 | -| | * SQLAlchemy 1.4 | -| | * Spark 5.0.0 | -| | * SQLoader As A Service 8.3.1 | -| | * Java CLI 2.2 | -+-------------------------+------------------------------------------------------------------------+ + New Features and Enhancements ----------------------------- -► :ref:`Alter Default Permissions<alter_default_permissions>` is now enhanced to include support for ``USER DEFINED FUNCTIONS``. - -► Enahnced Regular Expresseion (RegEx) support. +► SQDB's new ``DATETIME2`` data type delivers nanosecond precision and timezone control, for reliable and accurate time-based data.. -► Python version for :ref:`Python User Defined Functions<python_functions>` has been upgraded to Python 3.11. Known Issues ------------ @@ -52,25 +40,24 @@ Version 4.11 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-18800 | Running Create Table As Select from a table with delete predicates causes worker abnormal behavior | +| SQ-18621 | ``DELETE`` statement causes Worker stability issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18797 | Worker failure leaves orphan locks | +| SQ-19275 | Compression issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18555 | Enhance set parameter command efficiency | +| SQ-19485 | Issue using ``COPY FROM`` JSON file containing ``ARRAY`` data | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18504 | Access Control Permissions - Functions | +| SQ-19534 | Issue with ``ARRAY`` containing large ``TEXT`` | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-18253 | A network insert query fails | +| SQ-19541 | Issue using ``DISTINCT`` clause on ``ARRAY`` | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-16436 | Right function error | +| SQ-19571 | ``LZ4`` is not permitted for ``FLOAT`` cell of ``ARRAY`` | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-14398 | Improve orphan locks handling | +| SQ-19635 | ``DICT`` Compression issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ - -Deprecations +Deprecation ------------------- ► **Haskell CLI** @@ -79,9 +66,7 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re ► **CentOS Linux 7.x** -* As of June 2024, CentOS Linux 7.x will reach its End of Life and will not be supported by SQreamDB. This announcement provides a one-year advance notice for our users to plan for this change. We recommend users to explore migration or upgrade options to maintain ongoing support and security beyond this date. - -* REHL 8.x is now officially supported. +* As of June 2024, CentOS Linux 7.x has reached its End of Life and is no longer supported by SQreamDB. ► **DateTime2 Alias** From d13341a181b2012f2028e0bc8adcfd38a84b26d4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:02:00 +0200 Subject: [PATCH 1788/1892] Update 4.11.rst --- releases/4.11.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index fd58a41af..ca09070dc 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -20,7 +20,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 12.3.2 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 58 | +| Storage version | 59 | +-------------------------+------------------------------------------------------------------------+ | Driver compatibility | * JDBC 5.4.2 | | | * ODBC 4.4.4 | From a5c4aeae8e837ec0dca4424cc9670116f586c05e Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:51:34 +0200 Subject: [PATCH 1789/1892] releasePolicy --- releases/2022.1.1.rst | 116 ------------------------------ releases/2022.1.2.rst | 106 --------------------------- releases/2022.1.3.rst | 123 -------------------------------- releases/2022.1.4.rst | 107 ---------------------------- releases/2022.1.5.rst | 123 -------------------------------- releases/2022.1.6.rst | 106 --------------------------- releases/2022.1.7.rst | 96 ------------------------- releases/2022.1.rst | 142 ------------------------------------- releases/2022.1_index.rst | 24 ------- releases/4.0_index.rst | 4 -- releases/index.rst | 3 +- releases/releasePolicy.rst | 53 ++++++++++++++ 12 files changed, 54 insertions(+), 949 deletions(-) delete mode 100644 releases/2022.1.1.rst delete mode 100644 releases/2022.1.2.rst delete mode 100644 releases/2022.1.3.rst delete mode 100644 releases/2022.1.4.rst delete mode 100644 releases/2022.1.5.rst delete mode 100644 releases/2022.1.6.rst delete mode 100644 releases/2022.1.7.rst delete mode 100644 releases/2022.1.rst delete mode 100644 releases/2022.1_index.rst create mode 100644 releases/releasePolicy.rst diff --git a/releases/2022.1.1.rst b/releases/2022.1.1.rst deleted file mode 100644 index 2690139bf..000000000 --- a/releases/2022.1.1.rst +++ /dev/null @@ -1,116 +0,0 @@ -.. _2022.1.1: - -********************** -Release Notes 2022.1.1 -********************** - -The 2022.1.1 release notes were released on 7/19/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ---------------- - -The 2022.1.1 Release Notes describes the following: - -* Enhanced security features -* For more information, see :ref:`SQream Acceleration Studio 5.4.7 <sqream_studio_>`. - -Storage Version ---------------- - -The storage version presently in effect is version 40. - -New Features ------------- - -The 2022.1.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Password Security Compliance -**************************** - -In compliance with GDPR standards, SQream now requires a strong password policy when accessing the CLI or Studio. - -For more information, see :ref:`Password Policy <access_control_password_policy>`. - -Known Issues ------------- - -There were no known issues in Version 2022.1.1. - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2022.1.1: - -+-------------+------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+================================================================================================+ -| SQ-6419 | An internal compiler error occurred when casting Numeric literals in an aggregation function. | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-10873 | Inserting 100K bytes into a text column resulted in an unclear error message. | -+-------------+------------------------------------------------------------------------------------------------+ -| SQ-10955 | Unneeded reads were occurring when filtering by date. | -+-------------+------------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes ------------------------------------- - -The ``login_max_retries`` configuration flag is required for adjusting the permitted log-in attempts. - -For more information, see :ref:`Adjusting the Permitted Log-In Attempts <login_max_retries>`. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -In :ref:`SQream Acceleration Studio 5.4.7 <sqream_studio_>`, the **Configuration** section has been temporarily disabled and will be enabled at a later date. In addition, the **Log Lines** tab in the **Log** section has been removed. - -End of Support --------------- - -The End of Support section is not relevant to Version 2022.1.1. - -Upgrading to v2022.1.1 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - -3. Extract the recently created back-up file. - - -4. Replace your current metadata with the metadata you stored in the back-up file. - - -5. Navigate to the new SQream package bin folder. - - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. - diff --git a/releases/2022.1.2.rst b/releases/2022.1.2.rst deleted file mode 100644 index b45f10af5..000000000 --- a/releases/2022.1.2.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. _2022.1.2: - -********************** -Release Notes 2022.1.2 -********************** - -The 2022.1.2 release notes were released on 8/24/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ---------------- - -The 2022.1.2 Release Notes describes the following: - -* Automatic schema identification. - -* Optimized queries on external Parquet tables. - -Storage Version ---------------- - -The storage version presently in effect is version 41. - -New Features ------------- - -The 2022.1.2 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Parquet Read Optimization -************************* - -Querying Parquet foreign tables has been optimized and is now up to 20x faster than in previous versions. - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2022.1.2: - -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================================================================+ -| SQ-10892 | An incorrect error message was displayed when users ran the ``UPDATE`` command on foreign tables. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ -| SQ-11273 | Clustering optimization only occurs when copying data from CSV files. | -+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes ------------------------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -No features were deprecated for Version 2022.1.2. - -End of Support --------------- - -The End of Support section is not relevant to Version 2022.1.2. - -Upgrading to v2022.1.2 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - - -3. Extract the recently created back-up file. - - -4. Replace your current metadata with the metadata you stored in the back-up file. - - -5. Navigate to the new SQream package bin folder. - - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the :ref:`Upgrading SQream Version <installing_sqream_with_binary>` procedure. - diff --git a/releases/2022.1.3.rst b/releases/2022.1.3.rst deleted file mode 100644 index 1c073760b..000000000 --- a/releases/2022.1.3.rst +++ /dev/null @@ -1,123 +0,0 @@ -.. _2022.1.3: - -********************** -Release Notes 2022.1.3 -********************** - -The 2022.1.3 release notes were released on 9/20/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ---------------- - -The 2022.1.3 Release Notes describes the following: - -* Optimize the delete operation by removing redundant calls. - -* Support LIKE condition for filtering metadata. - -* Migration tool for converting VARCHAR columns into TEXT columns. - -* Support sub-queries in the UPDATE condition. - -Storage Version ---------------- - -The storage version presently in effect is version 42. - - -Known Issues ------------- - -The following table lists the issues that are known limitations in Version 2022.1.3: - -+-------------+--------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+============================================================================================+ -| SQ-11677 | UPADTE or DELETE using a sub-query that includes '%' (modulo) is crashing SQreamDB worker | -+-------------+--------------------------------------------------------------------------------------------+ - - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2022.1.3: - -+-------------+-------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+=================================================================================================+ -| SQ-11487 | COPY FROM with offset = 0 (which is an unsupported option) is stuck up to the query timeout. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11373 | SQL statement fails after changing the foreign table the statement tries to query. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11320 | Locked users are not being released on system reset. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11310 | Using "create table like" on foreign tables results in flat compression of the created table. | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11287 | SQL User Defined Function fails when function definition contain parenthesis | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-11187 | FLAT compression is wrongly chosen when dealing with data sets starting with all-nulls | -+-------------+-------------------------------------------------------------------------------------------------+ -| SQ-10892 | Update - enhanced error message when trying to run update on foreign table. | -+-------------+-------------------------------------------------------------------------------------------------+ - - - -Operations and Configuration Changes ------------------------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective immediately. - -TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - -As part of this release 2022.1.3, SQream provides an automated and secured migration tool to help customers with the conversion phase from VARCHAR to TEXT data type, please address delivery for further information. - -End of Support --------------- - -No End of Support changes were made. - -Upgrading to v2022.1.3 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1.4.rst b/releases/2022.1.4.rst deleted file mode 100644 index d4fa19783..000000000 --- a/releases/2022.1.4.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. _2022.1.4: - -********************** -Release Notes 2022.1.4 -********************** - -The 2022.1.4 release notes were released on 10/11/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ---------------- - -The 2022.1.4 Release Notes describes the following: - -* Security enhancement - Disable Python UDFs by default. - - -Storage Version ---------------- - -The storage version presently in effect is version 42. - -Known Issues ------------- - -No relevant Known Issues. - - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2022.1.4: - -+---------------------+------------------------------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=====================+==================================================================================================================+ -| SQ-11782 | Alter default permissions to grant update results in error | -+---------------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11740 | A correlated subquery is blocked when having 'not exist' where clause in update query | -+---------------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-11686, SQ-11584 | CUDA malloc error | -+---------------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-10602 | Group by clause error | -+---------------------+------------------------------------------------------------------------------------------------------------------+ -| SQ-9813 | When executing copy from a parquet file that contain date values earlier than 1970, values are changed to 1970. | -+---------------------+------------------------------------------------------------------------------------------------------------------+ - - - - -Operations and Configuration Changes ------------------------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support --------------- - -No End of Support changes were made. - -Upgrading to v2022.1.4 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1.5.rst b/releases/2022.1.5.rst deleted file mode 100644 index 7a26cf30a..000000000 --- a/releases/2022.1.5.rst +++ /dev/null @@ -1,123 +0,0 @@ -.. _2022.1.5: - -********************** -Release Notes 2022.1.5 -********************** - -The 2022.1.5 release notes were released on 11/02/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - -The 2022.1.5 Release Notes include the following new features: - -* ``keys_evaluate`` utility function enhancement - add problematic chunk ID to the function's output report - -* Automatically close database client connections that have been open for 24 hours without any active statements - -* ``release_defunct_locks`` utility function enhancement to receive new optional input parameter to specify timeout - for more details see :ref:`Lock Related Issues <lock_related_issues>`. - -* Metadata scale up process improvement through RocksDB configuration improvements - -Storage Version ---------------- - -The storage version presently in effect is version 42. - - -Known Issues ------------- - -Recently discovered issue with the encryption feature, at this time SQream recommends to avoid using this feature - a fix will be introduced in the near future. - - -Resolved Issues ---------------- - -The following table lists the issues that were resolved in Version 2022.1.5: - -+--------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+==============+==========================================================================================+ -| SQ-11081 | Tableau connection are not getting closed | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11473 | SQream Command Line Interface connectivity issues | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11551 | SQream Studio Logs pages filtering issues | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11631 | Log related configuration flags are not working as expected | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11745 | Missing validation of sufficient GPU memory | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11792 | CUME_DIST function causes query execution errors | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-11905 | GetDate casting to as text returns DATE with 0s in the time part or no time part at all | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-12580 | Server Picker and Meta Data server may not be deployed on servers without GPU | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-12690 | Worker thread increase | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-13775 | Worker down issue | -+--------------+------------------------------------------------------------------------------------------+ -| SQ-13947 | Non-Unicode character query execution error | -+--------------+------------------------------------------------------------------------------------------+ - - -Operations and Configuration Changes ------------------------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support --------------- - -No End of Support changes were made. - -Upgrading to v2022.1.5 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1.6.rst b/releases/2022.1.6.rst deleted file mode 100644 index 6734ef097..000000000 --- a/releases/2022.1.6.rst +++ /dev/null @@ -1,106 +0,0 @@ -.. _2022.1.6: - -********************** -Release Notes 2022.1.6 -********************** - -The 2022.1.6 release notes were released on 12/11/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - -* :ref:`.Net Driver<net>` now supports .NET version 6 or newer. - -Storage Version ---------------- - -The storage version presently in effect is version 42. - -Known Issues ------------- - -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 2022.1.6 resolved Issues --------------------------------- - -+--------------------------------+------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+================================+==========================================================================================+ -| SQ-10160 | Spotfire casting issues when reading SQream data | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-11295 | ``max_file_size`` when executing ``COPY_TO`` is imprecise | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-11940, SQ-11926, SQ-11874 | Known encryption issues | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-11975 | Internal runtime error | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-12019 | Using ``PERCENTILE_DISC`` function with ``PARTITION BY`` function causes internal error | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-12089 | ``COUNT (*)`` execution fails when using foreign table | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-12117 | Running TCPH-21 results in out of memory | -+--------------------------------+------------------------------------------------------------------------------------------+ -| SQ-12204 | Possible issue when trying to INSERT Unicode data using .Net client | -+--------------------------------+------------------------------------------------------------------------------------------+ - - - -Configuration Changes ---------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support --------------- - -No End of Support changes were made. - -Upgrading to v2022.1.6 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1.7.rst b/releases/2022.1.7.rst deleted file mode 100644 index a8a61202f..000000000 --- a/releases/2022.1.7.rst +++ /dev/null @@ -1,96 +0,0 @@ -.. _2022.1.7: - -********************** -Release Notes 2022.1.7 -********************** - -The 2022.1.7 release notes were released on 12/15/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -New Features ------------- - - * Ingesting data from :ref:`JSON<json>` files. - - * ZLIB compression performance enhancements. - -Storage Version ---------------- - -The storage version presently in effect is version 43. - -Known Issues ------------- - -:ref:`Percentile<percentile_disc>` is not supported for Window functions. - -Version 2022.1.7 resolved Issues --------------------------------- - -+------------------+-----------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+==================+=======================================================================+ -| SQ-11523 | ``SAVED QUERY`` execution internal error | -+------------------+-----------------------------------------------------------------------+ -| SQ-11811 | Missing metadata optimization when joining ``TEXT`` columns | -+------------------+-----------------------------------------------------------------------+ -| SQ-12178 | SQreamNet does not support the ``ExecuteNonQuery`` ADO.NET command | -+------------------+-----------------------------------------------------------------------+ - -Configuration Changes ---------------------- - -No configuration changes were made. - -Naming Changes --------------- - -No relevant naming changes were made. - -Deprecated Features -------------------- - -SQream is declaring end of support of VARCHAR data type, the decision resulted by SQream's effort to enhance its core functionalities and with respect to ever changing echo system requirements. - -VARCHAR is no longer supported for new customers - effective from Version 2022.1.3 (September 2022). - -TEXT data type is replacing VARCHAR and NVARCHAR - SQream will maintain VARCHAR data type support until 09/30/2023. - - -End of Support --------------- - -No End of Support changes were made. - -Upgrading to v2022.1.7 ----------------------- - -1. Generate a back-up of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path'); - - .. tip:: SQream recommends storing the generated back-up locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created back-up file. - -4. Replace your current metadata with the metadata you stored in the back-up file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - diff --git a/releases/2022.1.rst b/releases/2022.1.rst deleted file mode 100644 index c748e12d4..000000000 --- a/releases/2022.1.rst +++ /dev/null @@ -1,142 +0,0 @@ -.. _2022.1: - -************************** -Release Notes 2022.1 -************************** - -The 2022.1 release notes were released on 7/19/2022 and describe the following: - -.. contents:: - :local: - :depth: 1 - -Version Content ----------------- - -The 2022.1 Release Notes describe the following: - -* Enhanced security features. -* New data manipulation command. -* Additional data ingestion format. - -Storage Version ---------------- - -The storage version presently in effect is version 40. - -New Features -------------- - -The 2022.1 Release Notes include the following new features: - -.. contents:: - :local: - :depth: 1 - -Data Encryption -***************** - -SQream now supports data encryption mechanisms in accordance with **General Data Protection Regulation (GDPR)** standards. - -Using the data encryption feature may lead to a maximum of a 10% increase in performance degradation. - -For more information, see `Data Encryption <https://docs.sqream.com/en/v2022.1/feature_guides/data_encryption.html>`_. - -Update Feature -**************** - -SQream now supports the DML **Update** feature, which is used for modifying the value of certain columns in existing rows. - -For more information, see `UPDATE <https://docs.sqream.com/en/v2022.1/reference/sql/sql_statements/dml_commands/update.html#update>`_. - -Avro Ingestion -*************** - -SQream now supports ingesting data from Avro files. - -For more information, see `Inserting Data from Avro <https://docs.sqream.com/en/v2022.1/data_ingestion/avro.html>`_. - -Known Issues -------------- - -The following table lists the known issues for Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-7732 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-9889 | Running a query including Thai characters generated an internal runtime error. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10071 | Error on existing subqueries with TEXT and VARCHAR equality condition | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10191 | The ``ALTER DEFAULT SCHEMA`` command was not functioning correctly. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10629 | Inserting data into a table significantly slowed down running queries. | -+-------------+-------------------------------------------------------------------------------------------+ -| SQ-10659 | Using a comment generated a compile error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Resolved Issues ----------------- - -The following table lists the issues that were resolved in Version 2022.1: - -+-------------+-------------------------------------------------------------------------------------------+ -| **SQ No.** | **Description** | -+=============+===========================================================================================+ -| SQ-10111 | Reading numeric columns from an external Parquet file generated an error. | -+-------------+-------------------------------------------------------------------------------------------+ - -Operations and Configuration Changes ----------------------------------------- - -No relevant operations and configuration changes were made. - -Naming Changes ------------------ - -No relevant naming changes were made. - -Deprecated Features ---------------------- - -In SQream version 2022.1 the ``VARCHAR`` data type has been deprecated and replaced with ``TEXT``. SQream will maintain ``VARCHAR`` in all previous versions until completing the migration to ``TEXT``, at which point it will be deprecated in all earlier versions. SQream also provides an automated and secure tool to facilitate and simplify migration from ``VARCHAR`` to ``TEXT``. - -If you are using an earlier version of SQream, see the `Using Legacy String Literals <https://docs.sqream.com/en/v2022.1/configuration_guides/use_legacy_string_literals.html>`_ configuration flag. - -End of Support ----------------- - -The End of Support section is not relevant to Version 2022.1. - -Upgrading to v2022.1 ------------------------ - -1. Generate a backup of the metadata by running the following command: - - .. code-block:: console - - $ select backup_metadata('out_path', 'single_file'); - - .. tip:: SQream recommends storing the generated backup locally in case needed. - - SQream runs the Garbage Collector and creates a clean backup tarball package. - -2. Shut down all SQream services. - -3. Extract the recently created backup file. - -4. Replace your current metadata with the metadata you stored in the backup file. - -5. Navigate to the new SQream package bin folder. - -6. Run the following command: - - .. code-block:: console - - $ ./upgrade_storage <levelDB path> - - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQream Version <https://docs.sqream.com/en/v2022.1/installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. - - diff --git a/releases/2022.1_index.rst b/releases/2022.1_index.rst deleted file mode 100644 index 302ae3a96..000000000 --- a/releases/2022.1_index.rst +++ /dev/null @@ -1,24 +0,0 @@ -.. _2022.1_index: - -******************** -Release Notes 2022.1 -******************** - -The 2022.1 Release Notes describe the following releases: - -.. contents:: - :local: - :depth: 1 - -.. toctree:: - :maxdepth: 1 - :glob: - - 2022.1.7 - 2022.1.6 - 2022.1.5 - 2022.1.4 - 2022.1.3 - 2022.1.2 - 2022.1.1 - 2022.1 \ No newline at end of file diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index a061d116f..4e8404fc8 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -13,11 +13,7 @@ :glob: 4.3 - 4.4 4.5 - 4.6 - 4.7 - 4.8 4.9 4.10 4.11 diff --git a/releases/index.rst b/releases/index.rst index ed054b96b..4b16cf404 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -75,8 +75,7 @@ Release Notes :glob: :hidden: + releasePolicy 4.0_index - 2022.1_index - diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst new file mode 100644 index 000000000..f439fc0c0 --- /dev/null +++ b/releases/releasePolicy.rst @@ -0,0 +1,53 @@ +.. _releasePolicy: + +******************* +SQDB release policy +******************* + + +Release Cadence +=============== +New product versions will be released as per the established product roadmap or when significant features, improvements, or bug fixes are ready for deployment. + + +Transition to Maintenance Mode +============================== +Upon release of a new version, the previous versions immediately transitions into Maintenance Mode. +During Maintenance Mode support would be limited to high-priority issues and showstopper bugs that impact critical functionality. + +End of Support Timeline +======================= +End of Support (EOS) for each version is scheduled one year after the version's release date. +After the EOS date, no further updates or bug fixes will be provided for that version, and customers will be encouraged to upgrade to a supported version to receive continued updates and support. + +Blue Releases Timeline +====================== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Release + - Release Date + - Maintenance Mode + - End of Support + * - ``4.11`` + - March 31st 2025 + - TBD + - March 31st 2026 + * - ``4.10`` + - January 20th 2025 + - March 31st 2025 + - December 31st 2025 + * - ``4.9`` + - November 29th 2024 + - January 20th 2025 + - December 31st 2025 + * - ``4.5`` + - December 5th 2023 + - Decemeber 5th 2024 + - June 30th 2025 + * - ``4.3`` + - June 11th 2023 + - Decemeber 31st 2023 + - December 31st 2024 \ No newline at end of file From ee1e77eca8701dc16ebd5f49efdbbf6cc01127bf Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 13 Mar 2025 14:57:18 +0200 Subject: [PATCH 1790/1892] Update releasePolicy.rst --- releases/releasePolicy.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index f439fc0c0..171b404e3 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -20,7 +20,7 @@ End of Support Timeline End of Support (EOS) for each version is scheduled one year after the version's release date. After the EOS date, no further updates or bug fixes will be provided for that version, and customers will be encouraged to upgrade to a supported version to receive continued updates and support. -Blue Releases Timeline +SQDB Releases Timeline ====================== .. list-table:: @@ -39,7 +39,7 @@ Blue Releases Timeline - January 20th 2025 - March 31st 2025 - December 31st 2025 - * - ``4.9`` + * - ``4.9`` - November 29th 2024 - January 20th 2025 - December 31st 2025 From b323d138194afc48972f2a8fce879be5180828f8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 13 Mar 2025 15:40:28 +0200 Subject: [PATCH 1791/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 3856ebb4e..c1c2ba96a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -44,7 +44,7 @@ Client Driver Downloads - Recommended installation via ``npm`` - All * - **ODBC** - - For the **ODBC installer**, please contact your `SQreamDB representative <https://sqream.atlassian.net/servicedesk/customer/portal/2>`_ + - `Windows ODBC Installer <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream_odbc_jdbc_installer_25072022_x86_64bit_windows.zip>`_ , `Linux ODBC <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream_odbc_v4.4_x86_64_linux.tar.gz>`_ - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` - - Windows, Linux From ee1aa475e823b2769b8853f63c31e81f2eb67bd1 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 16 Mar 2025 07:49:09 +0200 Subject: [PATCH 1792/1892] releasepolicy --- releases/4.0_index.rst | 1 + releases/releasePolicy.rst | 28 ++++++++++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 4e8404fc8..0d689dbf8 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -14,6 +14,7 @@ 4.3 4.5 + 4.8 4.9 4.10 4.11 diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 171b404e3..1132586b4 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -7,13 +7,17 @@ SQDB release policy Release Cadence =============== -New product versions will be released as per the established product roadmap or when significant features, improvements, or bug fixes are ready for deployment. +* **Major Versions** Major product versions are released when significant architectural changes, or substantial improvements are ready for deployment. There is no fixed release cadence for major versions. +* **Minor Versions** SQream releases minor product versions once per quarter. Assuring our customers benefit new features and improvements. +* **Patches** Patches and hotfixes will be releases as needed to address specific issues. Transition to Maintenance Mode ============================== -Upon release of a new version, the previous versions immediately transitions into Maintenance Mode. -During Maintenance Mode support would be limited to high-priority issues and showstopper bugs that impact critical functionality. +* Upon release of a new version, the previous versions immediately transitions into Maintenance Mode. +* **Minimum Full Support Period** Each minor version will receive full support for a minimum of three months from its release date before transitioning to maintenance mode. Major versions will also have a minimum of 3 months of full support. +* During Maintenance Mode, support will be limited to high-priority issues and showstopper bugs that impact critical functionality. + End of Support Timeline ======================= @@ -37,17 +41,21 @@ SQDB Releases Timeline - March 31st 2026 * - ``4.10`` - January 20th 2025 - - March 31st 2025 - - December 31st 2025 + - April 20th 2025 + - January 20th 2026 * - ``4.9`` - November 29th 2024 - - January 20th 2025 - - December 31st 2025 + - February 29th 2025 + - November 29th 2025 + * - ``4.8`` + - October 6th 2024 + - January 6th 2025 + - October 6th 2025 * - ``4.5`` - December 5th 2023 - - Decemeber 5th 2024 + - March 5th 2024 - June 30th 2025 * - ``4.3`` - June 11th 2023 - - Decemeber 31st 2023 - - December 31st 2024 \ No newline at end of file + - September 11th 2023 + - June 11th 2024 \ No newline at end of file From 96c0577e7542e922fbbe43c637251443019951cf Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 17 Mar 2025 11:17:31 +0200 Subject: [PATCH 1793/1892] Update releasePolicy.rst --- releases/releasePolicy.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 1132586b4..7a06c0688 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -54,7 +54,7 @@ SQDB Releases Timeline * - ``4.5`` - December 5th 2023 - March 5th 2024 - - June 30th 2025 + - September 30th 2025 * - ``4.3`` - June 11th 2023 - September 11th 2023 From cf87de6a5227d52fc1aa8dac4fcdf1b1cd7c6876 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 24 Mar 2025 13:33:40 +0200 Subject: [PATCH 1794/1892] SQloader updates --- data_ingestion/sqloader.rst | 1117 +++++++++++++++++++++- data_ingestion/sqloader_as_a_service.rst | 1063 -------------------- 2 files changed, 1111 insertions(+), 1069 deletions(-) delete mode 100644 data_ingestion/sqloader_as_a_service.rst diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 2c778fca2..e7c83ad02 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -1,17 +1,1122 @@ .. _sqloader: -******** -SQLoader -******** +********************* +SQLoader As a Service +********************* -:ref:`sqloader_as_a_service` enables you to load data into SQreamDB from other DBMS and DBaaS. +The **SQLoader** is a Java service that enables you to ingest data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. + +**SQLoader** supports ingesting data from the following DBMSs: + +* Greenplum +* Microsoft SQL Server +* Oracle (including Oracle Autonomous Database) +* Postgresql +* SAP HANA +* Sybase +* Teradata +* SQreamDB 4.5.15 or later (Full Load only) + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following: + +* Java 17 +* :ref:`SQLoader configuration files<getting_the_sqloader_configuration_and_jar_files>` +* :ref:`SQLoader.jar file<getting_the_sqloader_configuration_and_jar_files>` + +Minimum Hardware Requirements +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - CPU cores + - 16 + * - RAM + - 32GB + +.. _sqloader_thread_sizing_guideline: + +Sizing Guidelines +------------------ + +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader request runs on a single table, meaning concurrent imports of multiple tables require multiple requests. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. + +Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + +Installation and Connectivity +============================= + +.. _getting_the_sqloader_configuration_and_jar_files: + +Getting All Configuration and JAR Files +--------------------------------------- + +#. Download the SQLoader zip file: + + .. code-block:: console + + https://storage.cloud.google.com/cicd-storage/sqloader_release/sqloader-release-v1.1.zip + +#. Extract the ``.tar`` file using the following command: + + .. code-block:: bash + + tar -xf sqloader_srv_v8.2.tar.gz + + A folder named ``sqloader`` with the following files is created: + + .. code-block:: + + ├── sqloader-v1.sh + ├── bin + │ ├── sqloader-admin-server-1.1.jar + │ └── sqloader-service-8.2.jar + ├── config + ├── reserved_words.txt + ├── sqload-jdbc.properties + └── sqream-mapping.json + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - File Name + - Description + * - ``sqream-mapping.json`` + - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion + * - ``sqload-jdbc.properties`` + - Used for defining a connection string and may also be used to reconfigure data loading + * - ``reserved_words.txt`` + - A list of reserved words which cannot be used as table and/or column names. + * - ``sqloader-service-8.2.jar`` + - The SQLoader service JAR file + * - ``sqloader-admin-server-1.0.jar`` + - The SQLoader admin server JAR file + * - ``sqloader-v1.sh`` + - SQLoader service installer bash file + +Installation +------------ + +Deployment Parameters +^^^^^^^^^^^^^^^^^^^^^ + +When using the ``sqloader-v1.sh`` file (installer), the following flags are already configured. + +All deployment flags are not dynamically adjustable at runtime. + + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Default + - Example + - Description + * - ``configDir`` + - Optional + - ``config`` + - ``java -jar sqloaderService-8.2.jar --configDir=</path/to/directory/>`` + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file + * - ``hzClusterName=<TEXT>`` + - Optional + - + - ``java -jar sqloader-service-8.2.jar --hzClusterName=<TEXT>`` + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. + * - ``LOG_DIR`` + - Optional + - ``logs`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.2.jar`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``spring.boot.admin.client.url`` + - Optional + - ``http://localhost:7070`` + - ``java -jar sqloader-service-8.2.jar --spring.boot.admin.client.url=http://IP:PORT`` + - SQLoader admin server connection flag + * - ``Xmx`` + - Optional + - + - ``java -jar -Xmx<number>g sqloader-service-8.2.jar`` + - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + * - ``DEFAULT_PROPERTIES`` + - Mandatory + - ``sqload-jdbc.properties`` + - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.2.jar`` + - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. + +Installing the Admin Server and SQLoader Service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. To install the admin server, run the following command (install it only once on one machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -admin + +Output: + +.. code-block:: + + ################################################################################## + Welcome to SQloader Admin-Service installation + ################################################################################## + Please Enter JAVA_HOME PATH + /opt/java + ################################################################################## + The default PATH to install SQloader Admin Service is /usr/local/sqloader-admin + Do you want to change the default PATH ? (y/N) + ################################################################################## + The default PATH to SQloader-Admin logs directory is /var/log/sqloader-admin/logs + Do you want to change the default? (y/N) + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + SQloader-Admin default port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader-admin/ + LOG_DIR=/var/log/sqloader-admin/ + JAR=sqloader-admin-server-1.0.jar + ADMINPORT=7070 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader-Admin Service installed successfuly ####################### + ################################################################################## + To Start SQLoader-Admin Service: sudo systemctl start sqloader-admin + To View SQLoader-Admin Service status: sudo systemctl status sqloader-admin + ################################################################################## + +2. To start the admin server, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-admin + +3. To verify admin server start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-admin + +4. To install SQLoader service, run the following command (you can install per machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -service + +Output: + +.. code-block:: + + ################################################################################## + Welocome to SQloader service installation + ################################################################################## + Please Enter JAVA_HOME Path + /opt/java + ################################################################################## + The Default PATH to install SQloader Service is /usr/local/sqloader + Do you want to change the default? (y/N) + ################################################################################## + The default PATH to SQloader Service logs directory is /var/log/sqloader-service + Do you want to change The default? (y/N) + ################################################################################## + Please enter SQloader Admin IP address + 192.168.5.234 + ################################################################################## + Please enter SQloader MEM size in GB + 20 + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + Default CONFDIR is /usr/local/sqloader/config , Do you want to change the default CONFDIR ? (y/N) + ################################################################################## + Default SQloader Admin port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + Default SQloader Service port is 6060 , Do you want to change the default port ? (y/N) + ################################################################################## + Default sqload-jdbc.properties is /usr/local/sqloader/config, Do you want to change the default? (y/N) + Using default sqload-jdbc.properties PATH + /usr/local/sqloader/config + ################################################################################## + ################################################################################## + Using /usr/local/sqloader/config/sqload-jdbc.properties + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader/bin + LOG_DIR=/var/log/sqloader-service + CONFDIR=/usr/local/sqloader/config + JAR=sqloader-service-8.2.jar + PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties + PORT=6060 + ADMINIP=192.168.5.234 + ADMINPORT=7070 + MEM=20 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader Service installed successfuly ####################### + ################################################################################## + To Start SQLoader Service: sudo systemctl start sqloader-service + To View SQLoader Service status: sudo systemctl status sqloader-service + ################################################################################## + +5. To start the SQLoader service, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-service + +6. To verify SQLoader service start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-service + +Reconfiguration +--------------- + +**Admin server** + +You may reconfigure the admin server even after you have started it. + + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-admin.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader-admin/config/sqloader_admin.conf + +2. Restart the admin server: + +.. code-block:: + + sudo systemctl restart sqloader-admin + +**SQLoader service** + +You may reconfigure the SQLoader service even after you have started it. + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-service.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader/config/sqloader_service.conf + +2. Restart the SQLoader service: + +.. code-block:: + + sudo systemctl restart sqloader-service + +Connection String +----------------- + +It is recommended that the ``sqload-jdbc.properties`` file will contain a connection string. + +1. Open the ``sqload-jdbc.properties`` file. +2. Configure connection parameters for: + + a. The source connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase or Teradata + b. The target connection string: SQreamDB + c. The :ref:`catalog<creating_catalog_tables>` connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, SQreamDB, Sybase, or Teradata + +.. list-table:: Connection String Parameters + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``HostIp:port`` + - The host and IP address number + * - ``database_name`` + - The name of the database from which data is loaded + * - ``user`` + - Username of a role to use for connection + * - ``password`` + - Specifies the password of the selected role + * - ``ssl`` + - Specifies SSL for this connection + +.. literalinclude:: connection_string.ini + :language: ini + :caption: Properties File Sample + :linenos: + +SQLoader Service Interface +========================== + +The SQLoader service automatically detects the IP addresses of incoming HTTP requests, even if the request originates from the same IP address as the one hosting the service. If you are accessing the service using a proxy server, you can include the client IP address in the request itself by using the ``X-Forwarded-For`` HTTP header, as in the following example: + +.. code-block:: + + curl -X POST -H 'X-Forwarded-For: 192.168.1.2' -H 'Content-Type: application/json' --data '{"loadTypeName": "inc", "sourceSchema": "QA", "sourceTable": "MY_TABLE", "sqreamTable": "MY_TABLE", "sqreamSchema": "QA"}' http://MyPc:6060/load + +Supported HTTP Requests +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Request Type + - Request Name + - cURL Command + - Description + - Example + * - POST + - ``load`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/load`` + - Sends a request to the service and returns immediately. This HTTP request is utilized within a load-balancing queue shared across multiple instances. This setup ensures efficient resource utilization by distributing incoming load requests evenly across all available instances. Additionally, the system incorporates :ref:`high availability<high_availability>` mechanisms to recover failed jobs in case an instance crashes, ensuring continuous operation and reliability even during instance failures. Note that if all instances crash, at least one instance must remain operational to recover and execute pending jobs. + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/load`` + * - POST + - ``syncLoad`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/syncLoad`` + - Sends a request to the service and returns once the request is complete. There's no load-balancing queue shared across multiple instances; therefore, it's advised that ``syncLoad`` requests be monitored by the user and not heavily sent. Monitor using the ``getActiveLoads`` cURL. + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/syncLoad`` + * - POST + - ``filterLogs`` + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"", "outputFilePath": ""}' http://127.0.0.1:6060/filterLogs`` + - Retrieves logs for a specific request ID + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"request-1-6a2884a3", "outputFilePath": "/home/avivs/sqloader_request.log"}' http://127.0.0.1:6060/filterLogs`` + * - GET + - ``getActiveLoads`` + - ``curl --header "Content-Type: application/json" --request GET http://127.0.0.1:6060/getActiveLoads`` + - Returns a list of all active loads currently running across all services + - + * - GET + - ``cancelRequest`` + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/<RequestId>`` + - Cancels an active request by request ID + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/request-2-6aa3c53d`` + +.. _high_availability: + +High Availability +----------------- + +SQLoader as a service supports high availability for asynchronous load requests only. When a service crashes, another service will take over the tasks and execute them from the beginning. However, there are some limited cases where high availability will not provide coverage: + +* **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. + +* **Limitations for specific tasks**: When any of the following is configured: + + * A task involving a ``clustered`` flag must be set to ``true`` to enable high availability. + + * A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. + +This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. + +Log Rotation +------------ + +Log rotation is based on time and size. At midnight (00:00) or when the file reaches 100MB, rotation occurs. Rotation means the log file ``SQLoader_service.log`` is renamed to ``SQLoader_service_%d_%i.log`` (%d=date, %i=rotation number), and a new, empty ``SQLoader_service.log`` file is created for the SQLoader service to continue writing to. + +Log Automatic cleanup +^^^^^^^^^^^^^^^^^^^^^ + +The maximum number of archived log files to keep is set to 360, so Logback will retain the latest 360 log files in the logs directory. Additionally, the total file size in the directory is limited to 50 GB. If the total size of archived log files exceeds this limit, older log files will be deleted to make room for new ones. + +SQLoader Request Parameters +--------------------------- + +Mandatory flags must be configured using HTTP flags or the ``properties`` file. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - HTTP Parameter + - State + - Default + - Description + * - ``clustered`` + - Optional + - ``true`` + - This flag is relevant only for ``load`` requests (``async``), not for ``syncLoad``. Note that this flag affects :ref:`high availability<high_availability>`. When set to ``true``: the request is directed to one of the available instances within a cluster, often through a load balancer. When set to ``false``: the request goes directly to the specified host without load balancing. + * - ``configFile`` + - Optional + - ``sqload-jdbc.properties`` + - Defines the path to the configuration file you wish to use. If not specified, the service will use the default path provided upon service deployment. + * - ``connectionStringSqream`` + - Mandatory + - + - JDBC connection string to SQreamDB + * - ``connectionStringSource`` + - Mandatory + - + - JDBC connection string to source database + * - ``connectionStringCatalog`` + - Mandatory + - + - JDBC connection string to catalog database + * - ``cdcCatalogTable`` + - Optional + - + - Part of the schema within the catalog database. Holds all inc/cdc tables and their settings + * - ``cdcTrackingTable`` + - Optional + - + - Part of the schema within the catalog database. Holds the last tracking value for every inc/cdc table from ``cdcCatalogTable`` table + * - ``cdcPrimaryKeyTable`` + - Optional + - + - Part of the schema within the catalog database. Holds all primary keys for every inc/cdc table from ``cdcCatalogTable`` table + * - ``loadSummaryTable`` + - Mandatory + - + - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load + * - ``batchSize`` + - Optional + - ``10.000`` + - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. + * - ``caseSensitive`` + - Optional + - ``false`` + - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB + * - ``checkCdcChain`` + - Optional + - ``false`` + - Check CDC chain between tracking table and source table + * - ``chunkSize`` + - Optional + - ``0`` + - The number of records read at once from the source database + * - ``columnListFilePath`` + - Optional + - + - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` + * - ``columns`` + - Optional + - All columns + - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true + * - ``count`` + - Optional + - ``true`` + - Defines whether or not table rows will be counted before being loaded into SQreamDB + * - ``cdcDelete`` + - Optional + - ``true`` + - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows + * - ``drop`` + - Optional + - ``false`` + - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter + * - ``fetchSize`` + - Optional + - ``100000`` + - The number of records to be read at once from source database. + * - ``filter`` + - Optional + - ``1=1`` + - Defines whether or not only records with SQL conditions are loaded + * - ``h, help`` + - Optional + - + - Displays the help menu and exits + * - ``limit`` + - Optional + - ``0`` (no limit) + - Limits the number of rows to be loaded + * - ``loadDttm`` + - Optional + - ``true`` + - Add an additional ``loadDttm`` column that defines the time and date of loading + * - ``loadDttmColumnName`` + - Optional + - ``sq_load_dttm`` + - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the ``loadDttm`` parameter. If ``loadDttm`` is enabled, the column defined by ``loadDttmColumnName`` will be added to the target table. + * - ``loadTypeName`` + - Optional + - ``full`` + - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc`` is supported for Oracle only and that ``inc`` is supported for Oracle and Postgresql + * - ``lockCheck`` + - Optional + - ``true`` + - Defines whether or not SQLoader will check source table is locked before the loading starts + * - ``lockTable`` + - Optional + - ``true`` + - Defines whether or not SQLoader will lock target table before the loading starts + * - ``partitionName`` + - Optional + - + - Specifies the number of table partitions. If configured, ``partition`` ensures that data is loaded according to the specified partition. You may configure the ``thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. + * - ``port`` + - Optional + - ``6060`` + - + * - ``rowid`` + - Optional + - ``false`` + - Defines whether or not SQLoader will get row IDs from Oracle tables + * - ``sourceDatabaseName`` + - Optional + - ``ORCL`` + - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. + * - ``splitByColumn`` + - Optional + - + - Column name for split (required for multi-thread loads) + * - ``sourceSchema`` + - Mandatory + - + - Source schema name to load data from + * - ``sourceTable`` + - Mandatory + - + - Source table name to load data from + * - ``sqreamSchema`` + - Optional + - The schema name defined in the ``sourceSchema`` flag + - Target schema name to load data into + * - ``sqreamTable`` + - Optional + - The table name defined in the ``sourceTable`` flag + - Target table name to load data into + * - ``threadCount`` + - Optional + - ``1`` + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guideline>` + * - ``truncate`` + - Optional + - ``false`` + - Truncate target table before loading + * - ``typeMappingPath`` + - Optional + - ``config/sqream-mapping.json`` + - A mapping file that converts source data types into SQreamDB data types. + * - ``useDbmsLob`` + - Optional + - ``true`` + - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types + * - ``usePartitions`` + - Optional + - ``true`` + - Defines whether or not SQLoader uses partitions in ``SELECT`` statements + * - ``validateSourceTable`` + - Optional + - ``true`` + - Allows control over the validation of table existence during the load. + +.. _load_type_name: + +Using the ``loadTypeName`` Parameter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Loading Type + - Parameter Option + - Description + * - Full Table + - ``full`` + - The entire data of the source table is loaded into SQreamDB + * - Change Data Capture (CDC) + - ``cdc`` + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only + * - Incremental + - ``inc`` + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle and Postgresql + + + + +Using the SQLoader Service Web Interface +---------------------------------------- + +The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. + + +SQLoader Service Web Interface Features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Monitor Services: + + * Health Checks: Monitor the health status of services to ensure they are functioning properly. + * Metrics: Monitor real-time performance metrics, including CPU usage, memory usage, and response times. + * Logging: View logs generated by services for troubleshooting and debugging purposes, and dynamically modify log levels during runtime to adjust verbosity for troubleshooting or performance monitoring. + +* Manage Active Load Requests: + + * View a list of currently active data loading requests, including their status, progress, and relevant metadata. + +Creating Summary and Catalog Tables +=================================== + +The summary and catalog tables are pre-aggregated tables that store summarized or aggregated data. + +Creating a Summary Table +------------------------ + +The summary table is part of the schema within the database catalog. + +The following summary table DDL uses Oracle syntax. + +.. note:: + + If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following column to your existing summary table instead of re-creating it. + + .. code-block:: sql + + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + +.. code-block:: sql + + # Use this DDL to create summary tables on none SQDB databases + CREATE TABLE public.SQLOAD_SUMMARY ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + UPDATED_DTTM_FROM DATE VISIBLE, + UPDATED_DTTM_TO DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + START_TIME TIMESTAMP(6) VISIBLE, + FINISH_TIME TIMESTAMP(6) VISIBLE, + ELAPSED_SEC NUMBER VISIBLE, + ROW_COUNT NUMBER VISIBLE, + SQL_FILTER TEXT(200 BYTE) VISIBLE, + PARTITION TEXT(200 BYTE) VISIBLE, + STMT_TYPE TEXT(200 BYTE) VISIBLE, + STATUS TEXT(200 BYTE) VISIBLE, + LOG_FILE TEXT(200 BYTE) VISIBLE, + DB_URL TEXT(200 BYTE) VISIBLE, + PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, + THREAD_COUNT NUMBER VISIBLE DEFAULT 1, + ELAPSED_MS NUMBER VISIBLE DEFAULT 0, + STATUS_CODE NUMBER VISIBLE DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, + TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, + SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, + CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, + REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, + ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + ); + +.. code-block:: sql + + # Use this DDL to create summary tables SQDB databases + CREATE TABLE sqload_summary ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LOAD_TYPE TEXT, + UPDATED_DTTM_FROM DATE , + UPDATED_DTTM_TO DATE , + LAST_VAL_INT NUMBER, + LAST_VAL_TS DATETIME , + START_TIME DATETIME , + FINISH_TIME DATETIME , + ELAPSED_SEC NUMBER , + ROW_COUNT NUMBER , + SQL_FILTER TEXT, + PARTITION TEXT, + STMT_TYPE TEXT, + STATUS TEXT, + LOG_FILE TEXT, + DB_URL TEXT, + PARTITION_COUNT NUMBER DEFAULT 0, + THREAD_COUNT NUMBER DEFAULT 1, + ELAPSED_MS NUMBER DEFAULT 0, + STATUS_CODE NUMBER DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER DEFAULT NULL, + TARGET_DB_URL TEXT DEFAULT NULL, + SQLOADER_VERSION TEXT DEFAULT NULL, + CLIENT_IP TEXT DEFAULT NULL, + REQUESTED_HOST TEXT DEFAULT NULL, + ACQUIRED_HOST TEXT DEFAULT NULL, + REQUEST_ID TEXT DEFAULT NULL +); + +.. _creating_catalog_tables: + +Creating Catalog Tables +----------------------- + +CDC (Change Data Capture) and Incremental tables are database tables that record changes made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. + +See :ref:`load_type_name` + +.. code-block:: sql + + #To be used for Oracle + CREATE TABLE public.CDC_TRACKING ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LAST_UPDATED_DTTM DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + LAST_VAL_DT DATE VISIBLE + ); + +.. code-block:: sql + + #To be used for SQDB + CREATE TABLE cdc_tracking ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LAST_UPDATED_DTTM DATE , + LAST_VAL_INT NUMBER DEFAULT 0, + LAST_VAL_TS DATETIME, + LAST_VAL_DT DATETIME + ); + +.. code-block:: sql + + CREATE TABLE public.CDC_TABLES ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, + INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, + INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_INTERVAL NUMBER(22,0) VISIBLE, + IS_ACTIVE NUMBER VISIBLE DEFAULT 0, + STATUS_LOAD NUMBER VISIBLE DEFAULT 0, + INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 + ); + + CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, + COLUMN_NAME TEXT(200 BYTE) VISIBLE, + IS_NULLABLE NUMBER VISIBLE DEFAULT 0 + ); + + +Data Type Mapping +================= + +.. contents:: + :local: + :depth: 1 + +Automatic Mapping +------------------ + +The **SQLoader** automatically maps data types used in Greenplum, Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. + +Greenplum +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Greenplum Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +Microsoft SQL Server +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Microsoft SQL Server Type + - SQreamDB Type + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` + - ``TEXT`` + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL`` + - ``REAL`` + * - ``VARBINARY`` + - ``TEXT`` + +Oracle +^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` + - ``BIGINT`` + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``DATE``, ``DATETIME`` + - ``DATETIME`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``CLOB`` + - ``TEXT`` + * - ``BLOB`` + - ``TEXT`` + * - ``RAW`` + - ``TEXT`` + + +Postgresql +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Postgresql Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +SAP HANA +^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SAP HANA Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` + - ``BIGINT`` + * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` + - ``TEXT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``TEXT`` + * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` + - ``NUMERIC`` + * - ``DOUBLE``, ``REAL`` + - ``FLOAT`` + * - ``TEXT`` + - ``TEXT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``INT`` + - ``INT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``DATETIME`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOL`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``FLOAT`` + - ``FLOAT`` + * - ``REAL`` + - ``REAL`` + +Sybase +^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Sybase Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``LONG VARCHAR``, ``CHARACTER``, ``TEXT`` + - ``TEXT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT``, ``INTEGER`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``NUMERIC(126,38)`` + - ``NUMERIC(38,10)`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``DATETIME``, ``TIMESTAMP``, ``TIME`` + - ``DATETIME`` + * - ``BIT`` + - ``BOOL`` + * - ``VARBINARY``, ``BINARY``, ``LONG BINARY`` + - ``TEXT`` + +Teradata +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Teradata Type + - SQreamDB Type + * - ``F`` + - ``DOUBLE`` + * - ``N``, ``D`` + - ``NUMERIC`` + * - ``CO`` + - ``TEXT`` + * - ``BO`` + - ``TEXT`` + * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` + - ``TEXT`` + * - ``I``, ``I4``, ``I(4)`` + - ``INT`` + * - ``I2``, ``I(2)`` + - ``SMALLINT`` + * - ``I1``, ``I(1)`` + - ``TINYINT`` + * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` + - ``BIGINT`` + * - ``TS``, ``DATETIME`` + - ``DATETIME`` + * - ``DA`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``REAL``, ``DOUBLE`` + - ``DOUBLE`` + +Manually Adjusting Mapping +---------------------------- + +You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. + +``names`` Method +^^^^^^^^^^^^^^^^^ + +To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. + +In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. + +.. code-block:: json + + { + "oracle": [ + { + "names": ["column1", "column2", "column3"], + "sqream": "bigint", + "java": "int", + "length": false + }, + { + "type": ["bigint","int","smallint","integer"], + "sqream": "bigint", + "java": "int", + "length": false + } + } -For loading data from Oracle, check out this :ref:`preparing_oracle_for_data_migration` .. toctree:: :maxdepth: 1 :glob: :hidden: - sqloader_as_a_service preparing_oracle_for_data_migration \ No newline at end of file diff --git a/data_ingestion/sqloader_as_a_service.rst b/data_ingestion/sqloader_as_a_service.rst deleted file mode 100644 index 4e69147e0..000000000 --- a/data_ingestion/sqloader_as_a_service.rst +++ /dev/null @@ -1,1063 +0,0 @@ -.. _sqloader_as_a_service: - -********************* -SQLoader As a Service -********************* - -The **SQLoader** is a Java service that enables you to ingest data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. - -**SQLoader** supports ingesting data from the following DBMSs: - -* Greenplum -* Microsoft SQL Server -* Oracle (including Oracle Autonomous Database) -* Postgresql -* SAP HANA -* Sybase -* Teradata -* SQreamDB 4.5.15 or later (Full Load only) - -.. contents:: - :local: - :depth: 1 - -Before You Begin -================ - -It is essential that you have the following: - -* Java 17 -* :ref:`SQLoader configuration files<getting_the_sqloader_configuration_and_jar_files>` -* :ref:`SQLoader.jar file<getting_the_sqloader_configuration_and_jar_files>` - -Minimum Hardware Requirements ------------------------------- - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Component - - Type - * - CPU cores - - 16 - * - RAM - - 32GB - -.. _sqloader_thread_sizing_guideline: - -Sizing Guidelines ------------------- - -The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader request runs on a single table, meaning concurrent imports of multiple tables require multiple requests. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. - -Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` - -Installation and Connectivity -============================= - -.. _getting_the_sqloader_configuration_and_jar_files: - -Getting All Configuration and JAR Files ---------------------------------------- - -#. Download the SQLoader zip file: - - .. code-block:: console - - https://storage.cloud.google.com/cicd-storage/sqloader_release/sqloader-release-v1.1.zip - -#. Extract the ``.tar`` file using the following command: - - .. code-block:: bash - - tar -xf sqloader_srv_v8.2.tar.gz - - A folder named ``sqloader`` with the following files is created: - - .. code-block:: - - ├── sqloader-v1.sh - ├── bin - │ ├── sqloader-admin-server-1.1.jar - │ └── sqloader-service-8.2.jar - ├── config - ├── reserved_words.txt - ├── sqload-jdbc.properties - └── sqream-mapping.json - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - File Name - - Description - * - ``sqream-mapping.json`` - - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion - * - ``sqload-jdbc.properties`` - - Used for defining a connection string and may also be used to reconfigure data loading - * - ``reserved_words.txt`` - - A list of reserved words which cannot be used as table and/or column names. - * - ``sqloader-service-8.2.jar`` - - The SQLoader service JAR file - * - ``sqloader-admin-server-1.0.jar`` - - The SQLoader admin server JAR file - * - ``sqloader-v1.sh`` - - SQLoader service installer bash file - -Installation ------------- - -Deployment Parameters -^^^^^^^^^^^^^^^^^^^^^ - -When using the ``sqloader-v1.sh`` file (installer), the following flags are already configured. - -All deployment flags are not dynamically adjustable at runtime. - - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Parameter - - State - - Default - - Example - - Description - * - ``configDir`` - - Optional - - ``config`` - - ``java -jar sqloaderService-8.2.jar --configDir=</path/to/directory/>`` - - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file - * - ``hzClusterName=<TEXT>`` - - Optional - - - - ``java -jar sqloader-service-8.2.jar --hzClusterName=<TEXT>`` - - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. - * - ``LOG_DIR`` - - Optional - - ``logs`` - - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.2.jar`` - - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file - * - ``spring.boot.admin.client.url`` - - Optional - - ``http://localhost:7070`` - - ``java -jar sqloader-service-8.2.jar --spring.boot.admin.client.url=http://IP:PORT`` - - SQLoader admin server connection flag - * - ``Xmx`` - - Optional - - - - ``java -jar -Xmx<number>g sqloader-service-8.2.jar`` - - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` - * - ``DEFAULT_PROPERTIES`` - - Mandatory - - ``sqload-jdbc.properties`` - - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.2.jar`` - - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. - -Installing the Admin Server and SQLoader Service -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -1. To install the admin server, run the following command (install it only once on one machine): - -.. code-block:: - - sudo ./sqloader-v1.sh -admin - -Output: - -.. code-block:: - - ################################################################################## - Welcome to SQloader Admin-Service installation - ################################################################################## - Please Enter JAVA_HOME PATH - /opt/java - ################################################################################## - The default PATH to install SQloader Admin Service is /usr/local/sqloader-admin - Do you want to change the default PATH ? (y/N) - ################################################################################## - The default PATH to SQloader-Admin logs directory is /var/log/sqloader-admin/logs - Do you want to change the default? (y/N) - ################################################################################## - Please enter HZCLUSTERNAME - sqcluster - ################################################################################## - SQloader-Admin default port is 7070 , Do you want to change the default port ? (y/N) - ################################################################################## - JAVA_HOME=/opt/java - BINDIR=/usr/local/sqloader-admin/ - LOG_DIR=/var/log/sqloader-admin/ - JAR=sqloader-admin-server-1.0.jar - ADMINPORT=7070 - HZCLUSTERNAME=sqcluster - ################################################################################## - ############# SQLoader-Admin Service installed successfuly ####################### - ################################################################################## - To Start SQLoader-Admin Service: sudo systemctl start sqloader-admin - To View SQLoader-Admin Service status: sudo systemctl status sqloader-admin - ################################################################################## - -2. To start the admin server, run the following command: - -.. code-block:: - - sudo systemctl start sqloader-admin - -3. To verify admin server start status, run the following command (optional): - -.. code-block:: - - sudo systemctl status sqloader-admin - -4. To install SQLoader service, run the following command (you can install per machine): - -.. code-block:: - - sudo ./sqloader-v1.sh -service - -Output: - -.. code-block:: - - ################################################################################## - Welocome to SQloader service installation - ################################################################################## - Please Enter JAVA_HOME Path - /opt/java - ################################################################################## - The Default PATH to install SQloader Service is /usr/local/sqloader - Do you want to change the default? (y/N) - ################################################################################## - The default PATH to SQloader Service logs directory is /var/log/sqloader-service - Do you want to change The default? (y/N) - ################################################################################## - Please enter SQloader Admin IP address - 192.168.5.234 - ################################################################################## - Please enter SQloader MEM size in GB - 20 - ################################################################################## - Please enter HZCLUSTERNAME - sqcluster - ################################################################################## - Default CONFDIR is /usr/local/sqloader/config , Do you want to change the default CONFDIR ? (y/N) - ################################################################################## - Default SQloader Admin port is 7070 , Do you want to change the default port ? (y/N) - ################################################################################## - Default SQloader Service port is 6060 , Do you want to change the default port ? (y/N) - ################################################################################## - Default sqload-jdbc.properties is /usr/local/sqloader/config, Do you want to change the default? (y/N) - Using default sqload-jdbc.properties PATH - /usr/local/sqloader/config - ################################################################################## - ################################################################################## - Using /usr/local/sqloader/config/sqload-jdbc.properties - ################################################################################## - JAVA_HOME=/opt/java - BINDIR=/usr/local/sqloader/bin - LOG_DIR=/var/log/sqloader-service - CONFDIR=/usr/local/sqloader/config - JAR=sqloader-service-8.2.jar - PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties - PORT=6060 - ADMINIP=192.168.5.234 - ADMINPORT=7070 - MEM=20 - HZCLUSTERNAME=sqcluster - ################################################################################## - ############# SQLoader Service installed successfuly ####################### - ################################################################################## - To Start SQLoader Service: sudo systemctl start sqloader-service - To View SQLoader Service status: sudo systemctl status sqloader-service - ################################################################################## - -5. To start the SQLoader service, run the following command: - -.. code-block:: - - sudo systemctl start sqloader-service - -6. To verify SQLoader service start status, run the following command (optional): - -.. code-block:: - - sudo systemctl status sqloader-service - -Reconfiguration ---------------- - -**Admin server** - -You may reconfigure the admin server even after you have started it. - - -1. To get the configuration path, run the following command: - -.. code-block:: - - cat /usr/lib/systemd/system/sqloader-admin.service | grep 'EnvironmentFile' - -Output: - -.. code-block:: - - EnvironmentFile=/usr/local/sqloader-admin/config/sqloader_admin.conf - -2. Restart the admin server: - -.. code-block:: - - sudo systemctl restart sqloader-admin - -**SQLoader service** - -You may reconfigure the SQLoader service even after you have started it. - -1. To get the configuration path, run the following command: - -.. code-block:: - - cat /usr/lib/systemd/system/sqloader-service.service | grep 'EnvironmentFile' - -Output: - -.. code-block:: - - EnvironmentFile=/usr/local/sqloader/config/sqloader_service.conf - -2. Restart the SQLoader service: - -.. code-block:: - - sudo systemctl restart sqloader-service - -Connection String ------------------ - -It is recommended that the ``sqload-jdbc.properties`` file will contain a connection string. - -1. Open the ``sqload-jdbc.properties`` file. -2. Configure connection parameters for: - - a. The source connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase or Teradata - b. The target connection string: SQreamDB - c. The :ref:`catalog<creating_catalog_tables>` connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, SQreamDB, Sybase, or Teradata - -.. list-table:: Connection String Parameters - :widths: auto - :header-rows: 1 - - * - Parameter - - Description - * - ``HostIp:port`` - - The host and IP address number - * - ``database_name`` - - The name of the database from which data is loaded - * - ``user`` - - Username of a role to use for connection - * - ``password`` - - Specifies the password of the selected role - * - ``ssl`` - - Specifies SSL for this connection - -.. literalinclude:: connection_string.ini - :language: ini - :caption: Properties File Sample - :linenos: - -SQLoader Service Interface -========================== - -The SQLoader service automatically detects the IP addresses of incoming HTTP requests, even if the request originates from the same IP address as the one hosting the service. If you are accessing the service using a proxy server, you can include the client IP address in the request itself by using the ``X-Forwarded-For`` HTTP header, as in the following example: - -.. code-block:: - - curl -X POST -H 'X-Forwarded-For: 192.168.1.2' -H 'Content-Type: application/json' --data '{"loadTypeName": "inc", "sourceSchema": "QA", "sourceTable": "MY_TABLE", "sqreamTable": "MY_TABLE", "sqreamSchema": "QA"}' http://MyPc:6060/load - -Supported HTTP Requests ------------------------ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Request Type - - Request Name - - cURL Command - - Description - - Example - * - POST - - ``load`` - - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/load`` - - Sends a request to the service and returns immediately. This HTTP request is utilized within a load-balancing queue shared across multiple instances. This setup ensures efficient resource utilization by distributing incoming load requests evenly across all available instances. Additionally, the system incorporates :ref:`high availability<high_availability>` mechanisms to recover failed jobs in case an instance crashes, ensuring continuous operation and reliability even during instance failures. Note that if all instances crash, at least one instance must remain operational to recover and execute pending jobs. - - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/load`` - * - POST - - ``syncLoad`` - - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/syncLoad`` - - Sends a request to the service and returns once the request is complete. There's no load-balancing queue shared across multiple instances; therefore, it's advised that ``syncLoad`` requests be monitored by the user and not heavily sent. Monitor using the ``getActiveLoads`` cURL. - - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/syncLoad`` - * - POST - - ``filterLogs`` - - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"", "outputFilePath": ""}' http://127.0.0.1:6060/filterLogs`` - - Retrieves logs for a specific request ID - - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"request-1-6a2884a3", "outputFilePath": "/home/avivs/sqloader_request.log"}' http://127.0.0.1:6060/filterLogs`` - * - GET - - ``getActiveLoads`` - - ``curl --header "Content-Type: application/json" --request GET http://127.0.0.1:6060/getActiveLoads`` - - Returns a list of all active loads currently running across all services - - - * - GET - - ``cancelRequest`` - - ``curl --request GET http://127.0.0.1:6061/cancelRequest/<RequestId>`` - - Cancels an active request by request ID - - ``curl --request GET http://127.0.0.1:6061/cancelRequest/request-2-6aa3c53d`` - -.. _high_availability: - -High Availability ------------------ - -SQLoader as a service supports high availability for asynchronous load requests only. When a service crashes, another service will take over the tasks and execute them from the beginning. However, there are some limited cases where high availability will not provide coverage: - -* **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. - -* **Limitations for specific tasks**: When any of the following is configured: - - * A task involving a ``clustered`` flag must be set to ``true`` to enable high availability. - - * A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. - -This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. - -Log Rotation ------------- - -Log rotation is based on time and size. At midnight (00:00) or when the file reaches 100MB, rotation occurs. Rotation means the log file ``SQLoader_service.log`` is renamed to ``SQLoader_service_%d_%i.log`` (%d=date, %i=rotation number), and a new, empty ``SQLoader_service.log`` file is created for the SQLoader service to continue writing to. - -Log Automatic cleanup -^^^^^^^^^^^^^^^^^^^^^ - -The maximum number of archived log files to keep is set to 360, so Logback will retain the latest 360 log files in the logs directory. Additionally, the total file size in the directory is limited to 50 GB. If the total size of archived log files exceeds this limit, older log files will be deleted to make room for new ones. - -SQLoader Request Parameters ---------------------------- - -Mandatory flags must be configured using HTTP flags or the ``properties`` file. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - HTTP Parameter - - State - - Default - - Description - * - ``clustered`` - - Optional - - ``true`` - - This flag is relevant only for ``load`` requests (``async``), not for ``syncLoad``. Note that this flag affects :ref:`high availability<high_availability>`. When set to ``true``: the request is directed to one of the available instances within a cluster, often through a load balancer. When set to ``false``: the request goes directly to the specified host without load balancing. - * - ``configFile`` - - Optional - - ``sqload-jdbc.properties`` - - Defines the path to the configuration file you wish to use. If not specified, the service will use the default path provided upon service deployment. - * - ``connectionStringSqream`` - - Mandatory - - - - JDBC connection string to SQreamDB - * - ``connectionStringSource`` - - Mandatory - - - - JDBC connection string to source database - * - ``connectionStringCatalog`` - - Mandatory - - - - JDBC connection string to catalog database - * - ``cdcCatalogTable`` - - Optional - - - - Part of the schema within the catalog database. Holds all inc/cdc tables and their settings - * - ``cdcTrackingTable`` - - Optional - - - - Part of the schema within the catalog database. Holds the last tracking value for every inc/cdc table from ``cdcCatalogTable`` table - * - ``cdcPrimaryKeyTable`` - - Optional - - - - Part of the schema within the catalog database. Holds all primary keys for every inc/cdc table from ``cdcCatalogTable`` table - * - ``loadSummaryTable`` - - Mandatory - - - - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load - * - ``batchSize`` - - Optional - - ``10.000`` - - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. - * - ``caseSensitive`` - - Optional - - ``false`` - - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB - * - ``checkCdcChain`` - - Optional - - ``false`` - - Check CDC chain between tracking table and source table - * - ``chunkSize`` - - Optional - - ``0`` - - The number of records read at once from the source database - * - ``columnListFilePath`` - - Optional - - - - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` - * - ``columns`` - - Optional - - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true - * - ``count`` - - Optional - - ``true`` - - Defines whether or not table rows will be counted before being loaded into SQreamDB - * - ``cdcDelete`` - - Optional - - ``true`` - - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows - * - ``drop`` - - Optional - - ``false`` - - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter - * - ``fetchSize`` - - Optional - - ``100000`` - - The number of records to be read at once from source database. - * - ``filter`` - - Optional - - ``1=1`` - - Defines whether or not only records with SQL conditions are loaded - * - ``h, help`` - - Optional - - - - Displays the help menu and exits - * - ``limit`` - - Optional - - ``0`` (no limit) - - Limits the number of rows to be loaded - * - ``loadDttm`` - - Optional - - ``true`` - - Add an additional ``loadDttm`` column that defines the time and date of loading - * - ``loadDttmColumnName`` - - Optional - - ``sq_load_dttm`` - - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the ``loadDttm`` parameter. If ``loadDttm`` is enabled, the column defined by ``loadDttmColumnName`` will be added to the target table. - * - ``loadTypeName`` - - Optional - - ``full`` - - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc`` is supported for Oracle only and that ``inc`` is supported for Oracle and Postgresql - * - ``lockCheck`` - - Optional - - ``true`` - - Defines whether or not SQLoader will check source table is locked before the loading starts - * - ``lockTable`` - - Optional - - ``true`` - - Defines whether or not SQLoader will lock target table before the loading starts - * - ``partitionName`` - - Optional - - - - Specifies the number of table partitions. If configured, ``partition`` ensures that data is loaded according to the specified partition. You may configure the ``thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. - * - ``port`` - - Optional - - ``6060`` - - - * - ``rowid`` - - Optional - - ``false`` - - Defines whether or not SQLoader will get row IDs from Oracle tables - * - ``sourceDatabaseName`` - - Optional - - ``ORCL`` - - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. - * - ``splitByColumn`` - - Optional - - - - Column name for split (required for multi-thread loads) - * - ``sourceSchema`` - - Mandatory - - - - Source schema name to load data from - * - ``sourceTable`` - - Mandatory - - - - Source table name to load data from - * - ``sqreamSchema`` - - Optional - - The schema name defined in the ``sourceSchema`` flag - - Target schema name to load data into - * - ``sqreamTable`` - - Optional - - The table name defined in the ``sourceTable`` flag - - Target table name to load data into - * - ``threadCount`` - - Optional - - ``1`` - - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guideline>` - * - ``truncate`` - - Optional - - ``false`` - - Truncate target table before loading - * - ``typeMappingPath`` - - Optional - - ``config/sqream-mapping.json`` - - A mapping file that converts source data types into SQreamDB data types. - * - ``useDbmsLob`` - - Optional - - ``true`` - - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types - * - ``usePartitions`` - - Optional - - ``true`` - - Defines whether or not SQLoader uses partitions in ``SELECT`` statements - * - ``validateSourceTable`` - - Optional - - ``true`` - - Allows control over the validation of table existence during the load. - -.. _load_type_name: - -Using the ``loadTypeName`` Parameter -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Loading Type - - Parameter Option - - Description - * - Full Table - - ``full`` - - The entire data of the source table is loaded into SQreamDB - * - Change Data Capture (CDC) - - ``cdc`` - - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only - * - Incremental - - ``inc`` - - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle and Postgresql - - - - -Using the SQLoader Service Web Interface ----------------------------------------- - -The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. - - -SQLoader Service Web Interface Features -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -* Monitor Services: - - * Health Checks: Monitor the health status of services to ensure they are functioning properly. - * Metrics: Monitor real-time performance metrics, including CPU usage, memory usage, and response times. - * Logging: View logs generated by services for troubleshooting and debugging purposes, and dynamically modify log levels during runtime to adjust verbosity for troubleshooting or performance monitoring. - -* Manage Active Load Requests: - - * View a list of currently active data loading requests, including their status, progress, and relevant metadata. - -Creating Summary and Catalog Tables -=================================== - -The summary and catalog tables are pre-aggregated tables that store summarized or aggregated data. - -Creating a Summary Table ------------------------- - -The summary table is part of the schema within the database catalog. - -The following summary table DDL uses Oracle syntax. - -.. note:: - - If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following column to your existing summary table instead of re-creating it. - - .. code-block:: sql - - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL - CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL - REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL - ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL - -.. code-block:: sql - - CREATE TABLE public.SQLOAD_SUMMARY ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - UPDATED_DTTM_FROM DATE VISIBLE, - UPDATED_DTTM_TO DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - START_TIME TIMESTAMP(6) VISIBLE, - FINISH_TIME TIMESTAMP(6) VISIBLE, - ELAPSED_SEC NUMBER VISIBLE, - ROW_COUNT NUMBER VISIBLE, - SQL_FILTER TEXT(200 BYTE) VISIBLE, - PARTITION TEXT(200 BYTE) VISIBLE, - STMT_TYPE TEXT(200 BYTE) VISIBLE, - STATUS TEXT(200 BYTE) VISIBLE, - LOG_FILE TEXT(200 BYTE) VISIBLE, - DB_URL TEXT(200 BYTE) VISIBLE, - PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, - THREAD_COUNT NUMBER VISIBLE DEFAULT 1, - ELAPSED_MS NUMBER VISIBLE DEFAULT 0, - STATUS_CODE NUMBER VISIBLE DEFAULT 0, - ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, - TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, - SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, - CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, - REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, - ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL - ); - -.. _creating_catalog_tables: - -Creating Catalog Tables ------------------------ - -CDC (Change Data Capture) and Incremental tables are database tables that record changes made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. - -See :ref:`load_type_name` - -Change Data Capture (CDC) and Incremental tables are supported only for Oracle. - -.. code-block:: sql - - CREATE TABLE public.CDC_TABLES ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, - INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, - INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_INTERVAL NUMBER(22,0) VISIBLE, - IS_ACTIVE NUMBER VISIBLE DEFAULT 0, - STATUS_LOAD NUMBER VISIBLE DEFAULT 0, - INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 - ); - - CREATE TABLE public.CDC_TRACKING ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LAST_UPDATED_DTTM DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - LAST_VAL_DT DATE VISIBLE - ); - - CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, - COLUMN_NAME TEXT(200 BYTE) VISIBLE, - IS_NULLABLE NUMBER VISIBLE DEFAULT 0 - ); - - -Data Type Mapping -================= - -.. contents:: - :local: - :depth: 1 - -Automatic Mapping ------------------- - -The **SQLoader** automatically maps data types used in Greenplum, Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. - -Greenplum -^^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Greenplum Type - - SQreamDB Type - * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - - ``TEXT`` - * - ``TEXT`` - - ``TEXT`` - * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT``, ``BOOL`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL``, ``FLOAT4`` - - ``REAL`` - -Microsoft SQL Server -^^^^^^^^^^^^^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Microsoft SQL Server Type - - SQreamDB Type - * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` - - ``TEXT`` - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL`` - - ``REAL`` - * - ``VARBINARY`` - - ``TEXT`` - -Oracle -^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Oracle Type - - SQreamDB Type - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` - - ``BIGINT`` - * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` - - ``TEXT`` - * - ``DATE``, ``DATETIME`` - - ``DATETIME`` - * - ``TIMESTAMP`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOLEAN`` - - ``BOOL`` - * - ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``CLOB`` - - ``TEXT`` - * - ``BLOB`` - - ``TEXT`` - * - ``RAW`` - - ``TEXT`` - - -Postgresql -^^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Postgresql Type - - SQreamDB Type - * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` - - ``TEXT`` - * - ``TEXT`` - - ``TEXT`` - * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` - - ``BIGINT`` - * - ``DATETIME``, ``TIMESTAMP`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BIT``, ``BOOL`` - - ``BOOL`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``REAL``, ``FLOAT4`` - - ``REAL`` - -SAP HANA -^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - SAP HANA Type - - SQreamDB Type - * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` - - ``BIGINT`` - * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` - - ``TEXT`` - * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOLEAN`` - - ``TEXT`` - * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` - - ``NUMERIC`` - * - ``DOUBLE``, ``REAL`` - - ``FLOAT`` - * - ``TEXT`` - - ``TEXT`` - * - ``BIGINT`` - - ``BIGINT`` - * - ``INT`` - - ``INT`` - * - ``SMALLINT`` - - ``SMALLINT`` - * - ``TINYINT`` - - ``TINYINT`` - * - ``DATETIME`` - - ``DATETIME`` - * - ``DATE`` - - ``DATE`` - * - ``BOOL`` - - ``BOOL`` - * - ``NUMERIC`` - - ``NUMERIC`` - * - ``DOUBLE`` - - ``DOUBLE`` - * - ``FLOAT`` - - ``FLOAT`` - * - ``REAL`` - - ``REAL`` - -Sybase -^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Sybase Type - - SQreamDB Type - * - ``CHAR``, ``VARCHAR``, ``LONG VARCHAR``, ``CHARACTER``, ``TEXT`` - - ``TEXT`` - * - ``TINYINT`` - - ``TINYINT`` - * - ``SMALLINT`` - - ``SMALLINT`` - * - ``INT``, ``INTEGER`` - - ``INT`` - * - ``BIGINT`` - - ``BIGINT`` - * - ``DECIMAL``, ``NUMERIC`` - - ``NUMERIC`` - * - ``NUMERIC(126,38)`` - - ``NUMERIC(38,10)`` - * - ``FLOAT``, ``DOUBLE`` - - ``DOUBLE`` - * - ``DATE`` - - ``DATE`` - * - ``DATETIME``, ``TIMESTAMP``, ``TIME`` - - ``DATETIME`` - * - ``BIT`` - - ``BOOL`` - * - ``VARBINARY``, ``BINARY``, ``LONG BINARY`` - - ``TEXT`` - -Teradata -^^^^^^^^^ - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Teradata Type - - SQreamDB Type - * - ``F`` - - ``DOUBLE`` - * - ``N``, ``D`` - - ``NUMERIC`` - * - ``CO`` - - ``TEXT`` - * - ``BO`` - - ``TEXT`` - * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` - - ``TEXT`` - * - ``I``, ``I4``, ``I(4)`` - - ``INT`` - * - ``I2``, ``I(2)`` - - ``SMALLINT`` - * - ``I1``, ``I(1)`` - - ``TINYINT`` - * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` - - ``BIGINT`` - * - ``TS``, ``DATETIME`` - - ``DATETIME`` - * - ``DA`` - - ``DATE`` - * - ``BIT`` - - ``BOOL`` - * - ``REAL``, ``DOUBLE`` - - ``DOUBLE`` - -Manually Adjusting Mapping ----------------------------- - -You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. - -``names`` Method -^^^^^^^^^^^^^^^^^ - -To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. - -In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. - -.. code-block:: json - - { - "oracle": [ - { - "names": ["column1", "column2", "column3"], - "sqream": "bigint", - "java": "int", - "length": false - }, - { - "type": ["bigint","int","smallint","integer"], - "sqream": "bigint", - "java": "int", - "length": false - } - } - - - - From 413ede3bc5b1e05fa7888ac92e79c0a3ae1d3932 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 24 Mar 2025 14:24:48 +0200 Subject: [PATCH 1795/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 140 ++++++++++++++++++------------------ 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index e7c83ad02..3aa24b757 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -695,80 +695,80 @@ The following summary table DDL uses Oracle syntax. .. code-block:: sql # Use this DDL to create summary tables on none SQDB databases - CREATE TABLE public.SQLOAD_SUMMARY ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - UPDATED_DTTM_FROM DATE VISIBLE, - UPDATED_DTTM_TO DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - START_TIME TIMESTAMP(6) VISIBLE, - FINISH_TIME TIMESTAMP(6) VISIBLE, - ELAPSED_SEC NUMBER VISIBLE, - ROW_COUNT NUMBER VISIBLE, - SQL_FILTER TEXT(200 BYTE) VISIBLE, - PARTITION TEXT(200 BYTE) VISIBLE, - STMT_TYPE TEXT(200 BYTE) VISIBLE, - STATUS TEXT(200 BYTE) VISIBLE, - LOG_FILE TEXT(200 BYTE) VISIBLE, - DB_URL TEXT(200 BYTE) VISIBLE, - PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, - THREAD_COUNT NUMBER VISIBLE DEFAULT 1, - ELAPSED_MS NUMBER VISIBLE DEFAULT 0, - STATUS_CODE NUMBER VISIBLE DEFAULT 0, - ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, - TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, - SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, - CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, - REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, - ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL - ); + CREATE TABLE public.SQLOAD_SUMMARY ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + UPDATED_DTTM_FROM DATE VISIBLE, + UPDATED_DTTM_TO DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + START_TIME TIMESTAMP(6) VISIBLE, + FINISH_TIME TIMESTAMP(6) VISIBLE, + ELAPSED_SEC NUMBER VISIBLE, + ROW_COUNT NUMBER VISIBLE, + SQL_FILTER TEXT(200 BYTE) VISIBLE, + PARTITION TEXT(200 BYTE) VISIBLE, + STMT_TYPE TEXT(200 BYTE) VISIBLE, + STATUS TEXT(200 BYTE) VISIBLE, + LOG_FILE TEXT(200 BYTE) VISIBLE, + DB_URL TEXT(200 BYTE) VISIBLE, + PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, + THREAD_COUNT NUMBER VISIBLE DEFAULT 1, + ELAPSED_MS NUMBER VISIBLE DEFAULT 0, + STATUS_CODE NUMBER VISIBLE DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, + TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, + SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, + CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, + REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, + ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + ); .. code-block:: sql # Use this DDL to create summary tables SQDB databases - CREATE TABLE sqload_summary ( - DB_NAME TEXT, - SCHEMA_NAME TEXT, - TABLE_NAME TEXT, - TABLE_NAME_FULL TEXT, - LOAD_TYPE TEXT, - UPDATED_DTTM_FROM DATE , - UPDATED_DTTM_TO DATE , - LAST_VAL_INT NUMBER, - LAST_VAL_TS DATETIME , - START_TIME DATETIME , - FINISH_TIME DATETIME , - ELAPSED_SEC NUMBER , - ROW_COUNT NUMBER , - SQL_FILTER TEXT, - PARTITION TEXT, - STMT_TYPE TEXT, - STATUS TEXT, - LOG_FILE TEXT, - DB_URL TEXT, - PARTITION_COUNT NUMBER DEFAULT 0, - THREAD_COUNT NUMBER DEFAULT 1, - ELAPSED_MS NUMBER DEFAULT 0, - STATUS_CODE NUMBER DEFAULT 0, - ELAPSED_SOURCE_MS NUMBER DEFAULT NULL, - ELAPSED_SOURCE_SEC NUMBER DEFAULT NULL, - ELAPSED_TARGET_MS NUMBER DEFAULT NULL, - ELAPSED_TARGET_SEC NUMBER DEFAULT NULL, - TARGET_DB_URL TEXT DEFAULT NULL, - SQLOADER_VERSION TEXT DEFAULT NULL, - CLIENT_IP TEXT DEFAULT NULL, - REQUESTED_HOST TEXT DEFAULT NULL, - ACQUIRED_HOST TEXT DEFAULT NULL, - REQUEST_ID TEXT DEFAULT NULL -); + CREATE TABLE sqload_summary ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LOAD_TYPE TEXT, + UPDATED_DTTM_FROM DATE , + UPDATED_DTTM_TO DATE , + LAST_VAL_INT NUMBER, + LAST_VAL_TS DATETIME , + START_TIME DATETIME , + FINISH_TIME DATETIME , + ELAPSED_SEC NUMBER , + ROW_COUNT NUMBER , + SQL_FILTER TEXT, + PARTITION TEXT, + STMT_TYPE TEXT, + STATUS TEXT, + LOG_FILE TEXT, + DB_URL TEXT, + PARTITION_COUNT NUMBER DEFAULT 0, + THREAD_COUNT NUMBER DEFAULT 1, + ELAPSED_MS NUMBER DEFAULT 0, + STATUS_CODE NUMBER DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER DEFAULT NULL, + TARGET_DB_URL TEXT DEFAULT NULL, + SQLOADER_VERSION TEXT DEFAULT NULL, + CLIENT_IP TEXT DEFAULT NULL, + REQUESTED_HOST TEXT DEFAULT NULL, + ACQUIRED_HOST TEXT DEFAULT NULL, + REQUEST_ID TEXT DEFAULT NULL + ); .. _creating_catalog_tables: From 034c4c1204d3f7ce5a64bd8d025ff671515722f5 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 24 Mar 2025 14:32:47 +0200 Subject: [PATCH 1796/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 3aa24b757..cc28ffc27 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -15,7 +15,7 @@ The **SQLoader** is a Java service that enables you to ingest data into SQreamDB * SAP HANA * Sybase * Teradata -* SQreamDB 4.5.15 or later (Full Load only) +* SQreamDB 4.5.15 or later .. contents:: :local: From 5e236fdb7866a2d95ab7265b4680d01d5089444f Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 24 Mar 2025 15:47:43 +0200 Subject: [PATCH 1797/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index cc28ffc27..147a34079 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -636,16 +636,20 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang * - Loading Type - Parameter Option + - Supported Databases - Description * - Full Table - ``full`` + - All - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. Supported for Oracle only + - Oracle + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. * - Incremental - ``inc`` - - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. Supported for Oracle and Postgresql + - Oracle, Postgresql, SqreamDB + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. From 353a394fb6f010aa89f58224bd95d1334ba76a56 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 24 Mar 2025 16:12:08 +0200 Subject: [PATCH 1798/1892] Sharon Change SQloader --- data_ingestion/sqloader.rst | 69 +- data_ingestion/sqloader.rst.bck | 1126 +++++++++++++++++++++++++++++++ 2 files changed, 1175 insertions(+), 20 deletions(-) create mode 100644 data_ingestion/sqloader.rst.bck diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 147a34079..f70b5970e 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -630,7 +630,7 @@ Using the ``loadTypeName`` Parameter Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. -.. list-table:: +.. list-table:: :widths: auto :header-rows: 1 @@ -640,15 +640,15 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang - Description * - Full Table - ``full`` - - All + - All supported DBs - The entire data of the source table is loaded into SQreamDB * - Change Data Capture (CDC) - ``cdc`` - - Oracle + - Oracle - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. * - Incremental - ``inc`` - - Oracle, Postgresql, SqreamDB + - Oracle, PostgreSQL, SQreamDB - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. @@ -676,6 +676,10 @@ SQLoader Service Web Interface Features Creating Summary and Catalog Tables =================================== +.. contents:: + :local: + :depth: 1 + The summary and catalog tables are pre-aggregated tables that store summarized or aggregated data. Creating a Summary Table @@ -797,22 +801,6 @@ See :ref:`load_type_name` LAST_VAL_DT DATE VISIBLE ); -.. code-block:: sql - - #To be used for SQDB - CREATE TABLE cdc_tracking ( - DB_NAME TEXT, - SCHEMA_NAME TEXT, - TABLE_NAME TEXT, - TABLE_NAME_FULL TEXT, - LAST_UPDATED_DTTM DATE , - LAST_VAL_INT NUMBER DEFAULT 0, - LAST_VAL_TS DATETIME, - LAST_VAL_DT DATETIME - ); - -.. code-block:: sql - CREATE TABLE public.CDC_TABLES ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, @@ -839,6 +827,47 @@ See :ref:`load_type_name` IS_NULLABLE NUMBER VISIBLE DEFAULT 0 ); +.. code-block:: sql + + #To be used for SQDB + CREATE TABLE cdc_tracking ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LAST_UPDATED_DTTM DATE , + LAST_VAL_INT NUMBER DEFAULT 0, + LAST_VAL_TS DATETIME, + LAST_VAL_DT DATETIME + ); + + CREATE TABLE public.CDC_TABLES ( + DB_NAME TEXT(200), + SCHEMA_NAME TEXT(200), + TABLE_NAME TEXT(200), + TABLE_NAME_FULL TEXT(200), + TABLE_NAME_CDC TEXT(200), + INC_COLUMN_NAME TEXT(200), + INC_COLUMN_TYPE TEXT(200), + LOAD_TYPE TEXT(200), + FREQ_TYPE TEXT(200), + FREQ_INTERVAL BIGINT, + IS_ACTIVE INT DEFAULT 0, + STATUS_LOAD INT DEFAULT 0, + INC_GAP_VALUE INT DEFAULT 0 + ); + + CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME TEXT(200), + SCHEMA_NAME TEXT(200), + TABLE_NAME TEXT(200), + TABLE_NAME_FULL TEXT(200), + CONSTRAINT_NAME TEXT(200), + COLUMN_NAME TEXT(200), + IS_NULLABLE INT DEFAULT 0 + ); + + Data Type Mapping ================= diff --git a/data_ingestion/sqloader.rst.bck b/data_ingestion/sqloader.rst.bck new file mode 100644 index 000000000..0f5644a52 --- /dev/null +++ b/data_ingestion/sqloader.rst.bck @@ -0,0 +1,1126 @@ +.. _sqloader: + +********************* +SQLoader As a Service +********************* + +The **SQLoader** is a Java service that enables you to ingest data into SQreamDB from other DBMS and DBaaS through HTTP requests using network insert. + +**SQLoader** supports ingesting data from the following DBMSs: + +* Greenplum +* Microsoft SQL Server +* Oracle (including Oracle Autonomous Database) +* Postgresql +* SAP HANA +* Sybase +* Teradata +* SQreamDB 4.5.15 or later + +.. contents:: + :local: + :depth: 1 + +Before You Begin +================ + +It is essential that you have the following: + +* Java 17 +* :ref:`SQLoader configuration files<getting_the_sqloader_configuration_and_jar_files>` +* :ref:`SQLoader.jar file<getting_the_sqloader_configuration_and_jar_files>` + +Minimum Hardware Requirements +------------------------------ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Component + - Type + * - CPU cores + - 16 + * - RAM + - 32GB + +.. _sqloader_thread_sizing_guideline: + +Sizing Guidelines +------------------ + +The SQLoader sizing is determined by the number of concurrent tables and threads based on the available CPU cores, limiting it to the number of cores minus one, with the remaining core reserved for the operating system. Each SQLoader request runs on a single table, meaning concurrent imports of multiple tables require multiple requests. Additionally, it is important to note that for partitioned tables, each partition consumes a thread. Therefore, for performance efficiency, considering the table's partition count when managing thread allocation is a must. + +Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + +Installation and Connectivity +============================= + +.. _getting_the_sqloader_configuration_and_jar_files: + +Getting All Configuration and JAR Files +--------------------------------------- + +#. Download the SQLoader zip file: + + .. code-block:: console + + https://storage.cloud.google.com/cicd-storage/sqloader_release/sqloader-release-v1.1.zip + +#. Extract the ``.tar`` file using the following command: + + .. code-block:: bash + + tar -xf sqloader_srv_v8.2.tar.gz + + A folder named ``sqloader`` with the following files is created: + + .. code-block:: + + ├── sqloader-v1.sh + ├── bin + │ ├── sqloader-admin-server-1.1.jar + │ └── sqloader-service-8.2.jar + ├── config + ├── reserved_words.txt + ├── sqload-jdbc.properties + └── sqream-mapping.json + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - File Name + - Description + * - ``sqream-mapping.json`` + - Maps foreign DBMS and DBaaS data types into SQreamDB data types during ingestion + * - ``sqload-jdbc.properties`` + - Used for defining a connection string and may also be used to reconfigure data loading + * - ``reserved_words.txt`` + - A list of reserved words which cannot be used as table and/or column names. + * - ``sqloader-service-8.2.jar`` + - The SQLoader service JAR file + * - ``sqloader-admin-server-1.0.jar`` + - The SQLoader admin server JAR file + * - ``sqloader-v1.sh`` + - SQLoader service installer bash file + +Installation +------------ + +Deployment Parameters +^^^^^^^^^^^^^^^^^^^^^ + +When using the ``sqloader-v1.sh`` file (installer), the following flags are already configured. + +All deployment flags are not dynamically adjustable at runtime. + + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - State + - Default + - Example + - Description + * - ``configDir`` + - Optional + - ``config`` + - ``java -jar sqloaderService-8.2.jar --configDir=</path/to/directory/>`` + - Defines the path to the folder containing both the data type mapping and the reserved words files. The defined folder must contain both files or else you will receive an error. This flag affects the mapping and reserved words files and does not affect the properties file + * - ``hzClusterName=<TEXT>`` + - Optional + - + - ``java -jar sqloader-service-8.2.jar --hzClusterName=<TEXT>`` + - In Hazelcast, a cluster refers to a group of connected Hazelcast instances across different JVMs or machines. By default, these instances connect to the same cluster on the network level, meaning that all SQLoader services that start on a network will connect to each other and share the same queue. An admin can connect to only one Hazelcast cluster at a time. If you start multiple clusters and want to connect them to the admin service, you will need to start multiple admin services, with each service connecting to one of your clusters. It is essential that this flag has the same name used here and across all SQLoader instances. + * - ``LOG_DIR`` + - Optional + - ``logs`` + - ``java -jar -DLOG_DIR=/path/to/log/directory sqloader-service-8.2.jar`` + - Defines the path of log directory created when loading data. If no value is specified, a ``logs`` folder is created under the same location as the ``sqloader.jar`` file + * - ``spring.boot.admin.client.url`` + - Optional + - ``http://localhost:7070`` + - ``java -jar sqloader-service-8.2.jar --spring.boot.admin.client.url=http://IP:PORT`` + - SQLoader admin server connection flag + * - ``Xmx`` + - Optional + - + - ``java -jar -Xmx<number>g sqloader-service-8.2.jar`` + - We recommend using the ``Xmx`` flag to set the maximum heap memory allocation for the service. If a single service is running on the machine, we suggest allocating 80% of the total memory minus approximately 4GB, which the service typically needs on average. If multiple services are running on the same machine, calculate the recommended heap size for one service and then divide it by the number of services. Compute formula: :math:`⌊ 0.8 * (TotalMemory - 4) ⌋` + * - ``DEFAULT_PROPERTIES`` + - Mandatory + - ``sqload-jdbc.properties`` + - ``java -jar -DDEFAULT_PROPERTIES=/path/to/file/sqload-jdbc.properties sqloader-service-8.2.jar`` + - When the service initializes, it looks for the variable DEFAULT_PROPERTIES, which corresponds to the default sqload-jdbc.properties file. Once the service is running with a specified properties file, this setting will remain unchanged as long as the service is operational. To modify it, you must shut down the service, edit the properties file, and then restart the service. Alternatively, you can modify it via a POST request, but this change will only affect the specific load request and not the default setting for all requests. + +Installing the Admin Server and SQLoader Service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +1. To install the admin server, run the following command (install it only once on one machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -admin + +Output: + +.. code-block:: + + ################################################################################## + Welcome to SQloader Admin-Service installation + ################################################################################## + Please Enter JAVA_HOME PATH + /opt/java + ################################################################################## + The default PATH to install SQloader Admin Service is /usr/local/sqloader-admin + Do you want to change the default PATH ? (y/N) + ################################################################################## + The default PATH to SQloader-Admin logs directory is /var/log/sqloader-admin/logs + Do you want to change the default? (y/N) + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + SQloader-Admin default port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader-admin/ + LOG_DIR=/var/log/sqloader-admin/ + JAR=sqloader-admin-server-1.0.jar + ADMINPORT=7070 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader-Admin Service installed successfuly ####################### + ################################################################################## + To Start SQLoader-Admin Service: sudo systemctl start sqloader-admin + To View SQLoader-Admin Service status: sudo systemctl status sqloader-admin + ################################################################################## + +2. To start the admin server, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-admin + +3. To verify admin server start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-admin + +4. To install SQLoader service, run the following command (you can install per machine): + +.. code-block:: + + sudo ./sqloader-v1.sh -service + +Output: + +.. code-block:: + + ################################################################################## + Welocome to SQloader service installation + ################################################################################## + Please Enter JAVA_HOME Path + /opt/java + ################################################################################## + The Default PATH to install SQloader Service is /usr/local/sqloader + Do you want to change the default? (y/N) + ################################################################################## + The default PATH to SQloader Service logs directory is /var/log/sqloader-service + Do you want to change The default? (y/N) + ################################################################################## + Please enter SQloader Admin IP address + 192.168.5.234 + ################################################################################## + Please enter SQloader MEM size in GB + 20 + ################################################################################## + Please enter HZCLUSTERNAME + sqcluster + ################################################################################## + Default CONFDIR is /usr/local/sqloader/config , Do you want to change the default CONFDIR ? (y/N) + ################################################################################## + Default SQloader Admin port is 7070 , Do you want to change the default port ? (y/N) + ################################################################################## + Default SQloader Service port is 6060 , Do you want to change the default port ? (y/N) + ################################################################################## + Default sqload-jdbc.properties is /usr/local/sqloader/config, Do you want to change the default? (y/N) + Using default sqload-jdbc.properties PATH + /usr/local/sqloader/config + ################################################################################## + ################################################################################## + Using /usr/local/sqloader/config/sqload-jdbc.properties + ################################################################################## + JAVA_HOME=/opt/java + BINDIR=/usr/local/sqloader/bin + LOG_DIR=/var/log/sqloader-service + CONFDIR=/usr/local/sqloader/config + JAR=sqloader-service-8.2.jar + PROPERTIES_FILE=/usr/local/sqloader/config/sqload-jdbc.properties + PORT=6060 + ADMINIP=192.168.5.234 + ADMINPORT=7070 + MEM=20 + HZCLUSTERNAME=sqcluster + ################################################################################## + ############# SQLoader Service installed successfuly ####################### + ################################################################################## + To Start SQLoader Service: sudo systemctl start sqloader-service + To View SQLoader Service status: sudo systemctl status sqloader-service + ################################################################################## + +5. To start the SQLoader service, run the following command: + +.. code-block:: + + sudo systemctl start sqloader-service + +6. To verify SQLoader service start status, run the following command (optional): + +.. code-block:: + + sudo systemctl status sqloader-service + +Reconfiguration +--------------- + +**Admin server** + +You may reconfigure the admin server even after you have started it. + + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-admin.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader-admin/config/sqloader_admin.conf + +2. Restart the admin server: + +.. code-block:: + + sudo systemctl restart sqloader-admin + +**SQLoader service** + +You may reconfigure the SQLoader service even after you have started it. + +1. To get the configuration path, run the following command: + +.. code-block:: + + cat /usr/lib/systemd/system/sqloader-service.service | grep 'EnvironmentFile' + +Output: + +.. code-block:: + + EnvironmentFile=/usr/local/sqloader/config/sqloader_service.conf + +2. Restart the SQLoader service: + +.. code-block:: + + sudo systemctl restart sqloader-service + +Connection String +----------------- + +It is recommended that the ``sqload-jdbc.properties`` file will contain a connection string. + +1. Open the ``sqload-jdbc.properties`` file. +2. Configure connection parameters for: + + a. The source connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, Sybase or Teradata + b. The target connection string: SQreamDB + c. The :ref:`catalog<creating_catalog_tables>` connection string: Greenplum, Microsoft SQL Server, Oracle, Postgresql, SAP HANA, SQreamDB, Sybase, or Teradata + +.. list-table:: Connection String Parameters + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``HostIp:port`` + - The host and IP address number + * - ``database_name`` + - The name of the database from which data is loaded + * - ``user`` + - Username of a role to use for connection + * - ``password`` + - Specifies the password of the selected role + * - ``ssl`` + - Specifies SSL for this connection + +.. literalinclude:: connection_string.ini + :language: ini + :caption: Properties File Sample + :linenos: + +SQLoader Service Interface +========================== + +The SQLoader service automatically detects the IP addresses of incoming HTTP requests, even if the request originates from the same IP address as the one hosting the service. If you are accessing the service using a proxy server, you can include the client IP address in the request itself by using the ``X-Forwarded-For`` HTTP header, as in the following example: + +.. code-block:: + + curl -X POST -H 'X-Forwarded-For: 192.168.1.2' -H 'Content-Type: application/json' --data '{"loadTypeName": "inc", "sourceSchema": "QA", "sourceTable": "MY_TABLE", "sqreamTable": "MY_TABLE", "sqreamSchema": "QA"}' http://MyPc:6060/load + +Supported HTTP Requests +----------------------- + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Request Type + - Request Name + - cURL Command + - Description + - Example + * - POST + - ``load`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/load`` + - Sends a request to the service and returns immediately. This HTTP request is utilized within a load-balancing queue shared across multiple instances. This setup ensures efficient resource utilization by distributing incoming load requests evenly across all available instances. Additionally, the system incorporates :ref:`high availability<high_availability>` mechanisms to recover failed jobs in case an instance crashes, ensuring continuous operation and reliability even during instance failures. Note that if all instances crash, at least one instance must remain operational to recover and execute pending jobs. + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/load`` + * - POST + - ``syncLoad`` + - ``curl --header "Content-Type: application/json" --request POST --data '{}' http://127.0.0.1:6060/syncLoad`` + - Sends a request to the service and returns once the request is complete. There's no load-balancing queue shared across multiple instances; therefore, it's advised that ``syncLoad`` requests be monitored by the user and not heavily sent. Monitor using the ``getActiveLoads`` cURL. + - ``curl --header "Content-Type: application/json" --request POST --data '{"sourceTable": "AVIV_INC", "sqreamTable": "t_inc", "limit":2000, "loadTypeName":"full"}' http://127.0.0.1:6060/syncLoad`` + * - POST + - ``filterLogs`` + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"", "outputFilePath": ""}' http://127.0.0.1:6060/filterLogs`` + - Retrieves logs for a specific request ID + - ``curl --header "Content-Type: application/json" --request POST --data '{"requestId":"request-1-6a2884a3", "outputFilePath": "/home/avivs/sqloader_request.log"}' http://127.0.0.1:6060/filterLogs`` + * - GET + - ``getActiveLoads`` + - ``curl --header "Content-Type: application/json" --request GET http://127.0.0.1:6060/getActiveLoads`` + - Returns a list of all active loads currently running across all services + - + * - GET + - ``cancelRequest`` + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/<RequestId>`` + - Cancels an active request by request ID + - ``curl --request GET http://127.0.0.1:6061/cancelRequest/request-2-6aa3c53d`` + +.. _high_availability: + +High Availability +----------------- + +SQLoader as a service supports high availability for asynchronous load requests only. When a service crashes, another service will take over the tasks and execute them from the beginning. However, there are some limited cases where high availability will not provide coverage: + +* **At least one service must remain operational**: After a crash, at least one service must be up and running to ensure that tasks can be recovered and executed. + +* **Limitations for specific tasks**: When any of the following is configured: + + * A task involving a ``clustered`` flag must be set to ``true`` to enable high availability. + + * A task involving a full load with ``truncate=false`` and ``drop=false`` will not rerun to prevent data duplication. In this type of load, data is inserted directly into the target table rather than a temporary table, making it impossible to determine if any data was inserted before the crash. + +This setup ensures that asynchronous load requests are handled reliably, even in the event of service failures. + +Log Rotation +------------ + +Log rotation is based on time and size. At midnight (00:00) or when the file reaches 100MB, rotation occurs. Rotation means the log file ``SQLoader_service.log`` is renamed to ``SQLoader_service_%d_%i.log`` (%d=date, %i=rotation number), and a new, empty ``SQLoader_service.log`` file is created for the SQLoader service to continue writing to. + +Log Automatic cleanup +^^^^^^^^^^^^^^^^^^^^^ + +The maximum number of archived log files to keep is set to 360, so Logback will retain the latest 360 log files in the logs directory. Additionally, the total file size in the directory is limited to 50 GB. If the total size of archived log files exceeds this limit, older log files will be deleted to make room for new ones. + +SQLoader Request Parameters +--------------------------- + +Mandatory flags must be configured using HTTP flags or the ``properties`` file. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - HTTP Parameter + - State + - Default + - Description + * - ``clustered`` + - Optional + - ``true`` + - This flag is relevant only for ``load`` requests (``async``), not for ``syncLoad``. Note that this flag affects :ref:`high availability<high_availability>`. When set to ``true``: the request is directed to one of the available instances within a cluster, often through a load balancer. When set to ``false``: the request goes directly to the specified host without load balancing. + * - ``configFile`` + - Optional + - ``sqload-jdbc.properties`` + - Defines the path to the configuration file you wish to use. If not specified, the service will use the default path provided upon service deployment. + * - ``connectionStringSqream`` + - Mandatory + - + - JDBC connection string to SQreamDB + * - ``connectionStringSource`` + - Mandatory + - + - JDBC connection string to source database + * - ``connectionStringCatalog`` + - Mandatory + - + - JDBC connection string to catalog database + * - ``cdcCatalogTable`` + - Optional + - + - Part of the schema within the catalog database. Holds all inc/cdc tables and their settings + * - ``cdcTrackingTable`` + - Optional + - + - Part of the schema within the catalog database. Holds the last tracking value for every inc/cdc table from ``cdcCatalogTable`` table + * - ``cdcPrimaryKeyTable`` + - Optional + - + - Part of the schema within the catalog database. Holds all primary keys for every inc/cdc table from ``cdcCatalogTable`` table + * - ``loadSummaryTable`` + - Mandatory + - + - Part of the schema within the catalog database. Pre-aggregated table that stores summarized loads which can help monitoring and analyzing load + * - ``batchSize`` + - Optional + - ``10.000`` + - The number of records to be inserted into SQreamDB at once. Please note that the configured batch size may impact chunk sizes. + * - ``caseSensitive`` + - Optional + - ``false`` + - If ``true``, keeps table name uppercase and lowercase characters when table is created in SQreamDB + * - ``checkCdcChain`` + - Optional + - ``false`` + - Check CDC chain between tracking table and source table + * - ``chunkSize`` + - Optional + - ``0`` + - The number of records read at once from the source database + * - ``columnListFilePath`` + - Optional + - + - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` + * - ``columns`` + - Optional + - All columns + - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true + * - ``count`` + - Optional + - ``true`` + - Defines whether or not table rows will be counted before being loaded into SQreamDB + * - ``cdcDelete`` + - Optional + - ``true`` + - Defines whether or not loading using Change Data Capture (CDC) includes deleted rows + * - ``drop`` + - Optional + - ``false`` + - Defines whether or not a new target table in SQreamDB is created. If ``false``, you will need to configure a target table name using the ``target`` parameter + * - ``fetchSize`` + - Optional + - ``100000`` + - The number of records to be read at once from source database. + * - ``filter`` + - Optional + - ``1=1`` + - Defines whether or not only records with SQL conditions are loaded + * - ``h, help`` + - Optional + - + - Displays the help menu and exits + * - ``limit`` + - Optional + - ``0`` (no limit) + - Limits the number of rows to be loaded + * - ``loadDttm`` + - Optional + - ``true`` + - Add an additional ``loadDttm`` column that defines the time and date of loading + * - ``loadDttmColumnName`` + - Optional + - ``sq_load_dttm`` + - Specifies the name of the additional column that records the time and date of loading. This parameter works in conjunction with the ``loadDttm`` parameter. If ``loadDttm`` is enabled, the column defined by ``loadDttmColumnName`` will be added to the target table. + * - ``loadTypeName`` + - Optional + - ``full`` + - Defines a loading type that affects the table that is created in SQreamDB. Options are ``full``, ``cdc``, or ``inc``. Please note that ``cdc`` is supported for Oracle only and that ``inc`` is supported for Oracle and Postgresql + * - ``lockCheck`` + - Optional + - ``true`` + - Defines whether or not SQLoader will check source table is locked before the loading starts + * - ``lockTable`` + - Optional + - ``true`` + - Defines whether or not SQLoader will lock target table before the loading starts + * - ``partitionName`` + - Optional + - + - Specifies the number of table partitions. If configured, ``partition`` ensures that data is loaded according to the specified partition. You may configure the ``thread`` parameter for parallel loading of your table partitions. If you do, please ensure that the number of threads does not exceed the number of partitions. + * - ``port`` + - Optional + - ``6060`` + - + * - ``rowid`` + - Optional + - ``false`` + - Defines whether or not SQLoader will get row IDs from Oracle tables + * - ``sourceDatabaseName`` + - Optional + - ``ORCL`` + - Defines the source database name. It does not modify the database connection string but impacts the storage and retrieval of data within catalog tables. + * - ``splitByColumn`` + - Optional + - + - Column name for split (required for multi-thread loads) + * - ``sourceSchema`` + - Mandatory + - + - Source schema name to load data from + * - ``sourceTable`` + - Mandatory + - + - Source table name to load data from + * - ``sqreamSchema`` + - Optional + - The schema name defined in the ``sourceSchema`` flag + - Target schema name to load data into + * - ``sqreamTable`` + - Optional + - The table name defined in the ``sourceTable`` flag + - Target table name to load data into + * - ``threadCount`` + - Optional + - ``1`` + - Number of threads to use for loading. Using multiple threads can significantly improve the loading performance, especially when dealing with columns that have metadata statistics (e.g., min/max values). SQLoader will automatically divide the data into batches based on the specified thread number, allowing for parallel processing. You may use ``thread`` both for tables that are partitioned and tables that are not. See :ref:`Sizing Guidelines<sqloader_thread_sizing_guideline>` + * - ``truncate`` + - Optional + - ``false`` + - Truncate target table before loading + * - ``typeMappingPath`` + - Optional + - ``config/sqream-mapping.json`` + - A mapping file that converts source data types into SQreamDB data types. + * - ``useDbmsLob`` + - Optional + - ``true`` + - Defines whether or not SQLoader uses ``dbms_lob_substr`` function for ``CLOB`` and ``BLOB`` data types + * - ``usePartitions`` + - Optional + - ``true`` + - Defines whether or not SQLoader uses partitions in ``SELECT`` statements + * - ``validateSourceTable`` + - Optional + - ``true`` + - Allows control over the validation of table existence during the load. + +.. _load_type_name: + +Using the ``loadTypeName`` Parameter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Loading Type + - Parameter Option + - Supported Databases + - Description + * - Full Table + - ``full`` + - All + - The entire data of the source table is loaded into SQreamDB + * - Change Data Capture (CDC) + - ``cdc`` + - Oracle + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT``, ``UPDATE``, and ``DELETE`` statements. SQLoader recognizes tables by table name and metadata. + * - Incremental + - ``inc`` + - Oracle, Postgresql, SqreamDB + - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. + +Please see below + + +Using the SQLoader Service Web Interface +---------------------------------------- + +The SQLoader Admin Server is a web-based administration tool specifically designed to manage and monitor the SQLoader service. It provides a user-friendly interface for monitoring data loading processes, managing configurations, and troubleshooting issues related to data loading into SQreamDB. + + +SQLoader Service Web Interface Features +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +* Monitor Services: + + * Health Checks: Monitor the health status of services to ensure they are functioning properly. + * Metrics: Monitor real-time performance metrics, including CPU usage, memory usage, and response times. + * Logging: View logs generated by services for troubleshooting and debugging purposes, and dynamically modify log levels during runtime to adjust verbosity for troubleshooting or performance monitoring. + +* Manage Active Load Requests: + + * View a list of currently active data loading requests, including their status, progress, and relevant metadata. + +Creating Summary and Catalog Tables +=================================== + +The summary and catalog tables are pre-aggregated tables that store summarized or aggregated data. + +Creating a Summary Table +------------------------ + +The summary table is part of the schema within the database catalog. + +The following summary table DDL uses Oracle syntax. + +.. note:: + + If you are migrating from :ref:`SQLoader as a process<ingesting_from_databases>` to **SQLoader as a service**, as described on this page, it is highly recommended that you add the following column to your existing summary table instead of re-creating it. + + .. code-block:: sql + + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL + REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + +.. code-block:: sql + + # Use this DDL to create summary tables on none SQDB databases + CREATE TABLE public.SQLOAD_SUMMARY ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + UPDATED_DTTM_FROM DATE VISIBLE, + UPDATED_DTTM_TO DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + START_TIME TIMESTAMP(6) VISIBLE, + FINISH_TIME TIMESTAMP(6) VISIBLE, + ELAPSED_SEC NUMBER VISIBLE, + ROW_COUNT NUMBER VISIBLE, + SQL_FILTER TEXT(200 BYTE) VISIBLE, + PARTITION TEXT(200 BYTE) VISIBLE, + STMT_TYPE TEXT(200 BYTE) VISIBLE, + STATUS TEXT(200 BYTE) VISIBLE, + LOG_FILE TEXT(200 BYTE) VISIBLE, + DB_URL TEXT(200 BYTE) VISIBLE, + PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, + THREAD_COUNT NUMBER VISIBLE DEFAULT 1, + ELAPSED_MS NUMBER VISIBLE DEFAULT 0, + STATUS_CODE NUMBER VISIBLE DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, + TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, + SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, + CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, + REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, + ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, + REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + ); + +.. code-block:: sql + + # Use this DDL to create summary tables SQDB databases + CREATE TABLE sqload_summary ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LOAD_TYPE TEXT, + UPDATED_DTTM_FROM DATE , + UPDATED_DTTM_TO DATE , + LAST_VAL_INT NUMBER, + LAST_VAL_TS DATETIME , + START_TIME DATETIME , + FINISH_TIME DATETIME , + ELAPSED_SEC NUMBER , + ROW_COUNT NUMBER , + SQL_FILTER TEXT, + PARTITION TEXT, + STMT_TYPE TEXT, + STATUS TEXT, + LOG_FILE TEXT, + DB_URL TEXT, + PARTITION_COUNT NUMBER DEFAULT 0, + THREAD_COUNT NUMBER DEFAULT 1, + ELAPSED_MS NUMBER DEFAULT 0, + STATUS_CODE NUMBER DEFAULT 0, + ELAPSED_SOURCE_MS NUMBER DEFAULT NULL, + ELAPSED_SOURCE_SEC NUMBER DEFAULT NULL, + ELAPSED_TARGET_MS NUMBER DEFAULT NULL, + ELAPSED_TARGET_SEC NUMBER DEFAULT NULL, + TARGET_DB_URL TEXT DEFAULT NULL, + SQLOADER_VERSION TEXT DEFAULT NULL, + CLIENT_IP TEXT DEFAULT NULL, + REQUESTED_HOST TEXT DEFAULT NULL, + ACQUIRED_HOST TEXT DEFAULT NULL, + REQUEST_ID TEXT DEFAULT NULL + ); + +.. _creating_catalog_tables: + +Creating Catalog Tables +----------------------- + +CDC (Change Data Capture) and Incremental tables are database tables that record changes made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. + +See :ref:`load_type_name` + +.. code-block:: sql + + #To be used for Oracle + CREATE TABLE public.CDC_TRACKING ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + LAST_UPDATED_DTTM DATE VISIBLE, + LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, + LAST_VAL_TS TIMESTAMP(6) VISIBLE, + LAST_VAL_DT DATE VISIBLE + ); + +.. code-block:: sql + + #To be used for SQDB + CREATE TABLE cdc_tracking ( + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LAST_UPDATED_DTTM DATE , + LAST_VAL_INT NUMBER DEFAULT 0, + LAST_VAL_TS DATETIME, + LAST_VAL_DT DATETIME + ); + +.. code-block:: sql + + CREATE TABLE public.CDC_TABLES ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, + INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, + INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, + LOAD_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_TYPE TEXT(200 BYTE) VISIBLE, + FREQ_INTERVAL NUMBER(22,0) VISIBLE, + IS_ACTIVE NUMBER VISIBLE DEFAULT 0, + STATUS_LOAD NUMBER VISIBLE DEFAULT 0, + INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 + ); + + CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( + DB_NAME TEXT(200 BYTE) VISIBLE, + SCHEMA_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME TEXT(200 BYTE) VISIBLE, + TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, + CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, + COLUMN_NAME TEXT(200 BYTE) VISIBLE, + IS_NULLABLE NUMBER VISIBLE DEFAULT 0 + ); + + +Data Type Mapping +================= + +.. contents:: + :local: + :depth: 1 + +Automatic Mapping +------------------ + +The **SQLoader** automatically maps data types used in Greenplum, Microsoft SQL Server, Oracle, Postgresql, Sybase, SAP HANA, and Teradata tables that are loaded into SQreamDB. + +Greenplum +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Greenplum Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +Microsoft SQL Server +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Microsoft SQL Server Type + - SQreamDB Type + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``NVARCHAR``, ``NVARCHAR2``, ``CHARACTER``, ``TEXT``, ``NTEXT`` + - ``TEXT`` + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INT``, ``TINYINT`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SMALLDATETIME``, ``DATETIMEOFFSET``, ``DATETIME2`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL`` + - ``REAL`` + * - ``VARBINARY`` + - ``TEXT`` + +Oracle +^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Oracle Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGE`` + - ``BIGINT`` + * - ``CHAR``, ``NCHAR``, ``VARCHAR``, ``VARCHAR2``, ``NVARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``DATE``, ``DATETIME`` + - ``DATETIME`` + * - ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``CLOB`` + - ``TEXT`` + * - ``BLOB`` + - ``TEXT`` + * - ``RAW`` + - ``TEXT`` + + +Postgresql +^^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Postgresql Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``CHARACTER`` + - ``TEXT`` + * - ``TEXT`` + - ``TEXT`` + * - ``INT``, ``SMALLINT``, ``BIGINT``, ``INT2``, ``INT4``, ``INT8`` + - ``BIGINT`` + * - ``DATETIME``, ``TIMESTAMP`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BIT``, ``BOOL`` + - ``BOOL`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``REAL``, ``FLOAT4`` + - ``REAL`` + +SAP HANA +^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - SAP HANA Type + - SQreamDB Type + * - ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER``, ``TINYINT`` + - ``BIGINT`` + * - ``CHAR``, ``VARCHAR``, ``NVARCHAR``, ``TEXT``, ``VARCHAR2``, ``NVARCHAR2`` + - ``TEXT`` + * - ``DATETIME``, ``TIMESTAMP``, ``SECONDDATE`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOLEAN`` + - ``TEXT`` + * - ``DECIMAL``, ``SMALLDECIMAL``, ``BIGDECIMAL`` + - ``NUMERIC`` + * - ``DOUBLE``, ``REAL`` + - ``FLOAT`` + * - ``TEXT`` + - ``TEXT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``INT`` + - ``INT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``DATETIME`` + - ``DATETIME`` + * - ``DATE`` + - ``DATE`` + * - ``BOOL`` + - ``BOOL`` + * - ``NUMERIC`` + - ``NUMERIC`` + * - ``DOUBLE`` + - ``DOUBLE`` + * - ``FLOAT`` + - ``FLOAT`` + * - ``REAL`` + - ``REAL`` + +Sybase +^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Sybase Type + - SQreamDB Type + * - ``CHAR``, ``VARCHAR``, ``LONG VARCHAR``, ``CHARACTER``, ``TEXT`` + - ``TEXT`` + * - ``TINYINT`` + - ``TINYINT`` + * - ``SMALLINT`` + - ``SMALLINT`` + * - ``INT``, ``INTEGER`` + - ``INT`` + * - ``BIGINT`` + - ``BIGINT`` + * - ``DECIMAL``, ``NUMERIC`` + - ``NUMERIC`` + * - ``NUMERIC(126,38)`` + - ``NUMERIC(38,10)`` + * - ``FLOAT``, ``DOUBLE`` + - ``DOUBLE`` + * - ``DATE`` + - ``DATE`` + * - ``DATETIME``, ``TIMESTAMP``, ``TIME`` + - ``DATETIME`` + * - ``BIT`` + - ``BOOL`` + * - ``VARBINARY``, ``BINARY``, ``LONG BINARY`` + - ``TEXT`` + +Teradata +^^^^^^^^^ + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Teradata Type + - SQreamDB Type + * - ``F`` + - ``DOUBLE`` + * - ``N``, ``D`` + - ``NUMERIC`` + * - ``CO`` + - ``TEXT`` + * - ``BO`` + - ``TEXT`` + * - ``A1``, ``AN``, ``AT``, ``BF``, ``BV``, ``CF``, ``CV``, ``JN``, ``PD``, ``PM``, ``PS``, ``PT``, ``PZ``, ``SZ``, ``TZ`` + - ``TEXT`` + * - ``I``, ``I4``, ``I(4)`` + - ``INT`` + * - ``I2``, ``I(2)`` + - ``SMALLINT`` + * - ``I1``, ``I(1)`` + - ``TINYINT`` + * - ``DH``, ``DM``, ``DS``, ``DY``, ``HM``, ``HS``, ``HR``, ``I8``, ``MO``, ``MS``, ``MI``, ``SC``, ``YM``, ``YR`` + - ``BIGINT`` + * - ``TS``, ``DATETIME`` + - ``DATETIME`` + * - ``DA`` + - ``DATE`` + * - ``BIT`` + - ``BOOL`` + * - ``REAL``, ``DOUBLE`` + - ``DOUBLE`` + +Manually Adjusting Mapping +---------------------------- + +You have the possibility to adjust the mapping process according to your specific needs, using any of the following methods. + +``names`` Method +^^^^^^^^^^^^^^^^^ + +To specify that you want to map one or more columns in your table to a specific data type, duplicate the code block which maps to the SQreamDB data type you want and include the ``names`` parameter in your code block. The SQLoader will map the specified columns to the specified SQreamDB data type. After the specified columns are mapped, the SQLoader continue to search for how to convert other data types to the same data type of the specified columns. + +In this example, ``column1``, ``column2``, and ``column3`` are mapped to ``BIGINT`` and the Oracle data types ``BIGINT``, ``INT``, ``SMALLINT``, ``INTEGER`` are also mapped to ``BIGINT``. + +.. code-block:: json + + { + "oracle": [ + { + "names": ["column1", "column2", "column3"], + "sqream": "bigint", + "java": "int", + "length": false + }, + { + "type": ["bigint","int","smallint","integer"], + "sqream": "bigint", + "java": "int", + "length": false + } + } + + +.. toctree:: + :maxdepth: 1 + :glob: + :hidden: + + preparing_oracle_for_data_migration \ No newline at end of file From 8b95e29064b0970b7260a41d51c121d74ca050b1 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 24 Mar 2025 16:20:44 +0200 Subject: [PATCH 1799/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index f70b5970e..3ce950211 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -630,7 +630,7 @@ Using the ``loadTypeName`` Parameter Using the ``loadTypeName`` parameter, you can define how you wish records' changes to be made to data in order to track inserts, updates, and deletes for data synchronization and auditing purposes. -.. list-table:: +.. list-table:: :widths: auto :header-rows: 1 @@ -651,8 +651,6 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang - Oracle, PostgreSQL, SQreamDB - Only changes made to the source table data since last load will be loaded into SQreamDB. Changes include transactions of ``INSERT`` statement. SQLoader recognizes the table by table name and metadata. - - Using the SQLoader Service Web Interface ---------------------------------------- @@ -702,7 +700,7 @@ The following summary table DDL uses Oracle syntax. .. code-block:: sql - # Use this DDL to create summary tables on none SQDB databases + # Use this DDL to create summary tables on non-SQDB databases CREATE TABLE public.SQLOAD_SUMMARY ( DB_NAME TEXT(200 BYTE) VISIBLE, SCHEMA_NAME TEXT(200 BYTE) VISIBLE, @@ -831,14 +829,14 @@ See :ref:`load_type_name` #To be used for SQDB CREATE TABLE cdc_tracking ( - DB_NAME TEXT, - SCHEMA_NAME TEXT, - TABLE_NAME TEXT, - TABLE_NAME_FULL TEXT, - LAST_UPDATED_DTTM DATE , - LAST_VAL_INT NUMBER DEFAULT 0, - LAST_VAL_TS DATETIME, - LAST_VAL_DT DATETIME + DB_NAME TEXT, + SCHEMA_NAME TEXT, + TABLE_NAME TEXT, + TABLE_NAME_FULL TEXT, + LAST_UPDATED_DTTM DATE , + LAST_VAL_INT NUMBER DEFAULT 0, + LAST_VAL_TS DATETIME, + LAST_VAL_DT DATETIME ); CREATE TABLE public.CDC_TABLES ( From 6af585508e5d837e2961d4f7c4c849ac62315c53 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 24 Mar 2025 16:25:19 +0200 Subject: [PATCH 1800/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 3ce950211..bc9aa8cbf 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -636,7 +636,7 @@ Using the ``loadTypeName`` parameter, you can define how you wish records' chang * - Loading Type - Parameter Option - - Supported Databases + - Supported Databases - Description * - Full Table - ``full`` From 237c7cd01787862cac1b1d8e18a9d43b5156a722 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 11:17:20 +0200 Subject: [PATCH 1801/1892] 4.11 RN --- data_ingestion/sqloader.rst | 2 +- releases/4.11.rst | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index cc28ffc27..12f3c1096 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -65,7 +65,7 @@ Getting All Configuration and JAR Files .. code-block:: console - https://storage.cloud.google.com/cicd-storage/sqloader_release/sqloader-release-v1.1.zip + https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz #. Extract the ``.tar`` file using the following command: diff --git a/releases/4.11.rst b/releases/4.11.rst index e23200a1a..cec5b4028 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -44,6 +44,8 @@ Version 4.11 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19275 | Compression issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19415 | Problem granting column DDL privilege to new roles | ++--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19485 | Issue using ``COPY FROM`` JSON file containing ``ARRAY`` data | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19534 | Issue with ``ARRAY`` containing large ``TEXT`` | @@ -52,7 +54,13 @@ Version 4.11 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19571 | ``LZ4`` is not permitted for ``FLOAT`` cell of ``ARRAY`` | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19635 | ``DICT`` Compression issue | +| SQ-19635 | ``DICT`` Compression issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19675 | Array decompress performance issue | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19869 | ``STDDEV`` functions slow compilation time | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19879 | Issue with Saved Queries Default permissions during database creation | +--------------+---------------------------------------------------------------------------------------------------------------------+ From 2dfe814dcdf4f24784169417ff59cec00077d64a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 11:30:15 +0200 Subject: [PATCH 1802/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 8bd9dab2b..bff44e4d4 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -61,11 +61,7 @@ Installation and Connectivity Getting All Configuration and JAR Files --------------------------------------- -#. Download the SQLoader zip file: - - .. code-block:: console - - https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz +#. Download the `SQLoader zip file` <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz>`_: #. Extract the ``.tar`` file using the following command: From 8fb425d598eb29327bf985fa880292c262f25001 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 13:17:02 +0200 Subject: [PATCH 1803/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index bff44e4d4..715b36fce 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -61,13 +61,13 @@ Installation and Connectivity Getting All Configuration and JAR Files --------------------------------------- -#. Download the `SQLoader zip file` <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz>`_: +#. Download the `SQLoader binary <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz>`_: #. Extract the ``.tar`` file using the following command: .. code-block:: bash - tar -xf sqloader_srv_v8.2.tar.gz + tar -xf sqloader_*.tar.gz A folder named ``sqloader`` with the following files is created: From 10ff38fe25c33e5646bd090a04709672c1971ad0 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 13:28:51 +0200 Subject: [PATCH 1804/1892] concat arrays --- reference/sql/sql_functions/scalar_functions/string/concat.rst | 2 +- .../sql_functions/scalar_functions/string/concat_function.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index 4e7fcf728..e6d993303 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -4,7 +4,7 @@ ``||`` (Concatenate) ************************** -Concatenate two strings to create a longer string +Concatenate two strings or string arrays to create a longer string The :ref:`concat_function` provides alternative syntax for CONCAT and requires at least two arguments. Syntax diff --git a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst index e08507161..24e397e7b 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat_function.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat_function.rst @@ -4,7 +4,7 @@ CONCAT function ************************** -Concatenates one or more strings, or concatenates one or more binary values. +Concatenates one or more strings, string arrays or concatenates one or more binary values. Syntax ========== From c80a5472457a167f977aa1eb4ecffa4d0fb88447 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 13:32:22 +0200 Subject: [PATCH 1805/1892] Update concat.rst --- .../sql/sql_functions/scalar_functions/string/concat.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/concat.rst b/reference/sql/sql_functions/scalar_functions/string/concat.rst index e6d993303..d984d1cdf 100644 --- a/reference/sql/sql_functions/scalar_functions/string/concat.rst +++ b/reference/sql/sql_functions/scalar_functions/string/concat.rst @@ -4,8 +4,8 @@ ``||`` (Concatenate) ************************** -Concatenate two strings or string arrays to create a longer string -The :ref:`concat_function` provides alternative syntax for CONCAT and requires at least two arguments. +Concatenate two strings or string arrays to create a longer string. + Syntax ========== @@ -39,6 +39,8 @@ Notes * SQream DB removes the trailing spaces from strings by default, which may lead to unexpected results. See the examples for more information. +* The :ref:`concat_function` provides alternative syntax for CONCAT and requires at least two arguments. + Examples =========== From d7bda3e7b4ab1c38e7db3b519f6f82871f090561 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 25 Mar 2025 15:18:04 +0200 Subject: [PATCH 1806/1892] Update 4.11.rst --- releases/4.11.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index cec5b4028..d18e4eefc 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -26,7 +26,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► SQDB's new ``DATETIME2`` data type delivers nanosecond precision and timezone control, for reliable and accurate time-based data.. +► SQDB's new ``DATETIME2`` data type delivers nanosecond precision and timezone notation, for reliable and accurate time-based data. + +► Array decompress to run on GPU (Performance improvement). Known Issues @@ -56,8 +58,6 @@ Version 4.11 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19635 | ``DICT`` Compression issue | +--------------+---------------------------------------------------------------------------------------------------------------------+ -| SQ-19675 | Array decompress performance issue | -+--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19869 | ``STDDEV`` functions slow compilation time | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19879 | Issue with Saved Queries Default permissions during database creation | @@ -78,7 +78,7 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re ► **DateTime2 Alias** -As of April 2025, The alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. +As of April 2025, the alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. Upgrading to Version 4.11 ------------------------- From 21286adc81776ba2c82b86728fb878867b25c7d7 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Thu, 27 Mar 2025 09:29:25 +0200 Subject: [PATCH 1807/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 159 +++++++++++++++++++----------------- 1 file changed, 84 insertions(+), 75 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 715b36fce..36a553cff 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -689,50 +689,55 @@ The following summary table DDL uses Oracle syntax. .. code-block:: sql - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL - CLIENT_IP TEXT (200 BYTE) VISIBLE DEFAULT NULL - REQUESTED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL - ACQUIRED_HOST TEXT (200 BYTE) VISIBLE DEFAULT NULL + request_id varchar2(200) default NULL, + client_ip varchar2(200) default NULL, + requested_host varchar2(200) default NULL, + acquired_host varchar2(200) default NULL .. code-block:: sql - # Use this DDL to create summary tables on non-SQDB databases - CREATE TABLE public.SQLOAD_SUMMARY ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - UPDATED_DTTM_FROM DATE VISIBLE, - UPDATED_DTTM_TO DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - START_TIME TIMESTAMP(6) VISIBLE, - FINISH_TIME TIMESTAMP(6) VISIBLE, - ELAPSED_SEC NUMBER VISIBLE, - ROW_COUNT NUMBER VISIBLE, - SQL_FILTER TEXT(200 BYTE) VISIBLE, - PARTITION TEXT(200 BYTE) VISIBLE, - STMT_TYPE TEXT(200 BYTE) VISIBLE, - STATUS TEXT(200 BYTE) VISIBLE, - LOG_FILE TEXT(200 BYTE) VISIBLE, - DB_URL TEXT(200 BYTE) VISIBLE, - PARTITION_COUNT NUMBER VISIBLE DEFAULT 0, - THREAD_COUNT NUMBER VISIBLE DEFAULT 1, - ELAPSED_MS NUMBER VISIBLE DEFAULT 0, - STATUS_CODE NUMBER VISIBLE DEFAULT 0, - ELAPSED_SOURCE_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_SOURCE_SEC NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_MS NUMBER(38,0) DEFAULT NULL, - ELAPSED_TARGET_SEC NUMBER(38,0) DEFAULT NULL, - TARGET_DB_URL TEXT (200 BYTE) DEFAULT NULL, - SQLOADER_VERSION TEXT (200 BYTE) DEFAULT NULL, - CLIENT_IP TEXT (200 BYTE) DEFAULT NULL, - REQUESTED_HOST TEXT (200 BYTE) DEFAULT NULL, - ACQUIRED_HOST TEXT (200 BYTE) DEFAULT NULL, - REQUEST_ID TEXT (200 BYTE) VISIBLE DEFAULT NULL + # Use this DDL to create summary tables on Oracle database + create table sqload_summary ( + db_name varchar2(200 byte), + schema_name varchar2(200 byte), + table_name varchar2(200 byte), + table_name_full varchar2(200 byte), + load_type varchar2(200 byte), + updated_dttm_from date, + updated_dttm_to date, + last_val_int number(22,0), + last_val_ts date, + start_time timestamp (6), + finish_time timestamp (6), + elapsed_sec number(*,0), + row_count number(*,0), + sql_filter varchar2(800 byte), + partition varchar2(200 byte), + stmt_type varchar2(200 byte), + status varchar2(200 byte), + log_file varchar2(200 byte), + db_url varchar2(400 byte), + partition_count number(*,0) default 0, + thread_count number(*,0) default 1, + elapsed_ms number(*,0) default 0, + status_code number(*,0) default 0, + elapsed_source_ms number(38,0) default NULL, + elapsed_source_sec number(38,0) default NULL, + elapsed_target_ms number(38,0) default NULL, + elapsed_target_sec number(38,0) default NULL, + target_db_url varchar2(200) default NULL, + sqloader_version varchar2(20) default NULL, + host varchar2(200) default NULL, + request_id varchar2(200) default NULL, + client_ip varchar2(200) default NULL, + requested_host varchar2(200) default NULL, + acquired_host varchar2(200) default NULL ); - + + create index sqload_summary_idx1 on sqload_summary (db_name,schema_name,table_name); + create index sqload_summary_idx2 on sqload_summary (start_time); + create index sqload_summary_idx3 on sqload_summary (finish_time); + .. code-block:: sql # Use this DDL to create summary tables SQDB databases @@ -784,42 +789,46 @@ See :ref:`load_type_name` .. code-block:: sql #To be used for Oracle - CREATE TABLE public.CDC_TRACKING ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - LAST_UPDATED_DTTM DATE VISIBLE, - LAST_VAL_INT NUMBER(22,0) VISIBLE DEFAULT 0, - LAST_VAL_TS TIMESTAMP(6) VISIBLE, - LAST_VAL_DT DATE VISIBLE - ); + create table cdc_tables ( + db_name varchar2(200 byte), + schema_name varchar2(200 byte), + table_name varchar2(200 byte), + table_name_full varchar2(200 byte), + table_name_cdc varchar2(200 byte), + inc_column_name varchar2(200 byte), + inc_column_type varchar2(200 byte), + load_type varchar2(200 byte), + freq_type varchar2(200 byte), + freq_interval number(22,0), + is_active number(*,0) default 0, + status_load number(*,0)); + + create index cdc_tables_idx1 on cdc_tables (db_name,table_name_full); + + create table cdc_table_primary_keys ( + db_name varchar2(200 byte), + schema_name varchar2(200 byte), + table_name varchar2(200 byte), + table_name_full varchar2(200 byte), + constraint_name varchar2(200 byte), + column_name varchar2(200 byte), + is_nullable number(*,0)); + + create index cdc_table_primary_keys_idx1 on cdc_table_primary_keys (db_name,table_name_full); + + + create table cdc_tracking ( + db_name varchar2(200 byte), + schema_name varchar2(200 byte), + table_name varchar2(200 byte), + table_name_full varchar2(200 byte), + last_updated_dttm date, + last_val_int number(22,0) default 0, + last_val_ts timestamp (6), + last_val_dt date); + + create index cdc_tracking_idx1 on cdc_tracking (db_name,table_name_full); - CREATE TABLE public.CDC_TABLES ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - TABLE_NAME_CDC TEXT(200 BYTE) VISIBLE, - INC_COLUMN_NAME TEXT(200 BYTE) VISIBLE, - INC_COLUMN_TYPE TEXT(200 BYTE) VISIBLE, - LOAD_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_TYPE TEXT(200 BYTE) VISIBLE, - FREQ_INTERVAL NUMBER(22,0) VISIBLE, - IS_ACTIVE NUMBER VISIBLE DEFAULT 0, - STATUS_LOAD NUMBER VISIBLE DEFAULT 0, - INC_GAP_VALUE NUMBER VISIBLE DEFAULT 0 - ); - - CREATE TABLE public.CDC_TABLE_PRIMARY_KEYS ( - DB_NAME TEXT(200 BYTE) VISIBLE, - SCHEMA_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME TEXT(200 BYTE) VISIBLE, - TABLE_NAME_FULL TEXT(200 BYTE) VISIBLE, - CONSTRAINT_NAME TEXT(200 BYTE) VISIBLE, - COLUMN_NAME TEXT(200 BYTE) VISIBLE, - IS_NULLABLE NUMBER VISIBLE DEFAULT 0 - ); .. code-block:: sql From 9ed96a6e56f29632f572189056c194304cd1f5a6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:06:48 +0300 Subject: [PATCH 1808/1892] Update index.rst --- connecting_to_sqream/client_drivers/python/index.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/python/index.rst b/connecting_to_sqream/client_drivers/python/index.rst index cb2524749..d18acdcba 100644 --- a/connecting_to_sqream/client_drivers/python/index.rst +++ b/connecting_to_sqream/client_drivers/python/index.rst @@ -124,12 +124,11 @@ SQLAlchemy is an Object-Relational Mapper (ORM) for Python. When you install the Before You Begin ---------------- -Download `pysqream-sqlalchemy <https://pypi.org/project/pysqream-sqlalchemy/1.3/>`_ +Download `pysqream-sqlalchemy <https://pypi.org/project/pysqream-sqlalchemy/>`_ Limitation ----------- -* Supports `Pysqream 3.2.5 <https://pypi.org/project/pysqream/3.2.5/>`_ * Does not support the ``ARRAY`` data type From 6990c773e409df4258507392a6489e39aa573e89 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:35:12 +0300 Subject: [PATCH 1809/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index c1c2ba96a..cc82adf6a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.2-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.3.0-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.4.2 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.4.2.jar>`_ + - `sqream-jdbc 5.4.2 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.5.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From 033c4c8ab0be2e41d9ca6fdcf69dee6ce8cf1ab8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 31 Mar 2025 11:40:58 +0300 Subject: [PATCH 1810/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index cc82adf6a..21b7afd44 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc 5.4.2 <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.5.0.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.5.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From 9b04c36d280bc147304f394f022dc22c8498f65a Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:02:39 +0300 Subject: [PATCH 1811/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index cb9076947..a1925219b 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -39,7 +39,7 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da - Integer (-9,223,372,036,854,775,808 - 9,223,372,036,854,775,807) - 8 bytes - ``36124441255243`` - - ``NUMBER`` + - * - ``REAL`` - Floating point (inexact) - 4 bytes @@ -59,7 +59,7 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da - 38 digits - 16 bytes - ``0.12324567890123456789012345678901234567`` - - ``DECIMAL`` + - ``DECIMAL``, ``NUMBER`` * - ``DATE`` - Date - 4 bytes From 3b756641d910c363f7547230edcd2101afa18c4c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:06:19 +0300 Subject: [PATCH 1812/1892] Update sql_data_types_primitives.rst --- data_type_guides/sql_data_types_primitives.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_type_guides/sql_data_types_primitives.rst b/data_type_guides/sql_data_types_primitives.rst index a1925219b..bd49468b2 100644 --- a/data_type_guides/sql_data_types_primitives.rst +++ b/data_type_guides/sql_data_types_primitives.rst @@ -73,6 +73,6 @@ SQreamDB compresses all columns and types. The data size noted is the maximum da * - ``DATETIME2`` - Date and time in nanosecond precision including UTC offset - 16 bytes - - ``'1955-11-05 01:24:00.000000000 +00:00:00'`` + - ``'1955-11-05 01:24:00.000000000 +00:00'`` - NA From 499f9efb369e452c11a7cba225d3e5ddb062b9d4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 1 Apr 2025 16:08:44 +0300 Subject: [PATCH 1813/1892] Update release date --- releases/4.11.rst | 2 +- releases/index.rst | 2 +- releases/releasePolicy.rst | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index d18e4eefc..c0a111c47 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -4,7 +4,7 @@ Release Notes 4.11 ***************** -The 4.11 release notes were released on March 30th, 2025 +The 4.11 release notes were released on April 3rd, 2025 .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index 4b16cf404..a80efbca1 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.11 - March 30, 2025<4.11>` +:ref:`Version 4.11 - April 3rd, 2025<4.11>` :ref:`Version 4.10 - January 20, 2025<4.10>` diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 7a06c0688..6392d647f 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -36,12 +36,12 @@ SQDB Releases Timeline - Maintenance Mode - End of Support * - ``4.11`` - - March 31st 2025 + - April 3rd 2025 - TBD - - March 31st 2026 + - April 3rd 2026 * - ``4.10`` - January 20th 2025 - - April 20th 2025 + - April 3rd 2025 - January 20th 2026 * - ``4.9`` - November 29th 2024 From f8b9363894cb8ff016f81202b93d06b1d0da0f6b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 3 Apr 2025 11:12:05 +0300 Subject: [PATCH 1814/1892] Update regexp_substr.rst --- .../scalar_functions/string/regexp_substr.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst index 37eb840cc..3af784070 100644 --- a/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst +++ b/reference/sql/sql_functions/scalar_functions/string/regexp_substr.rst @@ -4,7 +4,7 @@ REGEXP_SUBSTR ************************** -Returns the occurence of a regex match. +Returns the occurrence of a regex match. See also: :ref:`regexp_instr`, :ref:`regexp_count`. @@ -14,7 +14,7 @@ Syntax .. code-block:: postgres - REGEXP_SUBSTR( string_expr, string_test_expr [ , start_index [ , occurence ] ] ) --> INT + REGEXP_SUBSTR( string_expr, string_test_expr [ , start_index [ , occurrence ] ] ) --> TEXT Arguments ============ @@ -31,10 +31,10 @@ Arguments - Test pattern * - ``start_index`` - The character index offset to start counting from. Defaults to 1 - * - ``occurence`` - - Which occurence to search for. Defaults to 1 + * - ``occurrence`` + - Which occurrence to search for. Defaults to 1 * - ``return_position`` - - Setes the position within the string to return. Using 0, the function returns the string position of the first character of the substring that matches the pattern. Defaults to 0 + - Sets the position within the string to return. Using 0, the function returns the string position of the first character of the substring that matches the pattern. Defaults to 0 Supported RegEx Patterns ======================== @@ -51,13 +51,13 @@ Supported RegEx Patterns - Match the beginning of a string * - ``[^]`` - - Characters that do not match the speciifed string + - Characters that do not match the specified string * - ``$`` - Match the end of a string * - ``.`` - - Match any character (including whitespace such as carriage return and newline) + - Match any character (including white-space such as carriage return and newline) * - ``*`` - Match the preceding pattern zero or more times @@ -84,10 +84,10 @@ Supported RegEx Patterns - ``OR`` clause * - ``\`` - - Treating the subsequent characters in the expression as ordinary characters rather than metacharacters + - Treating the subsequent characters in the expression as ordinary characters rather than meta-characters * - ``\n`` - - Matching the nth (``1``-``9``) preceding subexpression grouped within parentheses + - Matching the nth (``1``-``9``) preceding sub-expression grouped within parentheses * - ``*?`` - Occurs zero or more times From 54dd37b19eb8b81e3f691978ea17bd03468d8cde Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 6 Apr 2025 10:34:40 +0300 Subject: [PATCH 1815/1892] Update optimization_best_practices.rst --- operational_guides/optimization_best_practices.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operational_guides/optimization_best_practices.rst b/operational_guides/optimization_best_practices.rst index 3b25c90ba..0ce1b1add 100644 --- a/operational_guides/optimization_best_practices.rst +++ b/operational_guides/optimization_best_practices.rst @@ -211,7 +211,7 @@ Filter and reduce table sizes prior to joining on them SELECT store_name, SUM(amount) - FROM dimention dim + FROM dimension dim JOIN fact ON dim.store_id = fact.store_id WHERE p_date BETWEEN '2019-07-01' AND '2019-07-31' GROUP BY store_name; @@ -222,7 +222,7 @@ Can be rewritten as: SELECT store_name, sum_amount - FROM dimention AS dim + FROM dimension AS dim INNER JOIN (SELECT SUM(amount) AS sum_amount, store_id FROM fact From 5615ddba8db01c8d46c5c41ea52325a44fe647a4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 9 Apr 2025 10:41:54 +0300 Subject: [PATCH 1816/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 36a553cff..db4755908 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -751,6 +751,7 @@ The following summary table DDL uses Oracle syntax. UPDATED_DTTM_TO DATE , LAST_VAL_INT NUMBER, LAST_VAL_TS DATETIME , + LAST_VAL_DT2 DATETIME2 , START_TIME DATETIME , FINISH_TIME DATETIME , ELAPSED_SEC NUMBER , @@ -841,7 +842,8 @@ See :ref:`load_type_name` LAST_UPDATED_DTTM DATE , LAST_VAL_INT NUMBER DEFAULT 0, LAST_VAL_TS DATETIME, - LAST_VAL_DT DATETIME + LAST_VAL_DT DATETIME, + LAST_VAL_DT2 DATETIME2 ); CREATE TABLE public.CDC_TABLES ( From 0092c84d5e0b58277c473ea1bbaba36a090f731b Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:05:34 +0300 Subject: [PATCH 1817/1892] 4.11 release --- releases/4.11.rst | 2 +- releases/index.rst | 2 +- releases/releasePolicy.rst | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/4.11.rst b/releases/4.11.rst index c0a111c47..c6137f744 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -4,7 +4,7 @@ Release Notes 4.11 ***************** -The 4.11 release notes were released on April 3rd, 2025 +The 4.11 release notes were released on April 9th, 2025 .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index a80efbca1..0d550b613 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.11 - April 3rd, 2025<4.11>` +:ref:`Version 4.11 - April 9th, 2025<4.11>` :ref:`Version 4.10 - January 20, 2025<4.10>` diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 6392d647f..0799468a1 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -36,12 +36,12 @@ SQDB Releases Timeline - Maintenance Mode - End of Support * - ``4.11`` - - April 3rd 2025 + - April 9th 2025 - TBD - - April 3rd 2026 + - April 9th 2026 * - ``4.10`` - January 20th 2025 - - April 3rd 2025 + - April 9th 2025 - January 20th 2026 * - ``4.9`` - November 29th 2024 From 1d9aaf872503356cfb916eab00f6814e987c8817 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:34:26 +0300 Subject: [PATCH 1818/1892] Update conf.py --- conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf.py b/conf.py index d1f0e04d4..3c71b0373 100644 --- a/conf.py +++ b/conf.py @@ -32,7 +32,7 @@ # The full version, including alpha/beta/rc tags -release = '4.11' +release = '4.12' # -- General configuration --------------------------------------------------- From 0e3e7df611a8f2395cd548095f0f6e5936e89424 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 10 Apr 2025 08:52:47 +0300 Subject: [PATCH 1819/1892] 4.12 RN --- releases/4.0_index.rst | 1 + releases/4.12.rst | 96 ++++++++++++++++++++++++++++++++++++++ releases/index.rst | 2 + releases/releasePolicy.rst | 6 ++- 4 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 releases/4.12.rst diff --git a/releases/4.0_index.rst b/releases/4.0_index.rst index 0d689dbf8..de53a91ce 100644 --- a/releases/4.0_index.rst +++ b/releases/4.0_index.rst @@ -18,3 +18,4 @@ 4.9 4.10 4.11 + 4.12 diff --git a/releases/4.12.rst b/releases/4.12.rst new file mode 100644 index 000000000..03e0d8ab3 --- /dev/null +++ b/releases/4.12.rst @@ -0,0 +1,96 @@ +.. _4.11: + +***************** +Release Notes 4.11 +***************** + +The 4.11 release notes were released on May 15th, 2025 + +.. contents:: + :local: + :depth: 1 + +Compatibility Matrix +-------------------- + ++-------------------------+------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================+ +| Supported OS | RHEL 8.9 | ++-------------------------+------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 12.3.2 | ++-------------------------+------------------------------------------------------------------------+ +| Storage version | 59 | ++-------------------------+------------------------------------------------------------------------+ + + +New Features and Enhancements +----------------------------- +► SQDB's new ``DATETIME2`` data type delivers nanosecond precision and timezone notation, for reliable and accurate time-based data. + +► Array decompress to run on GPU (Performance improvement). + + +Known Issues +------------ + +:ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` + +Version 4.11 resolved Issues +--------------------------- + ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| **SQ No.** | **Description** | ++==============+=====================================================================================================================+ +| SQ-xxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + + + + +Deprecation +------------------- + +► **Haskell CLI** + +Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. + +► **CentOS Linux 7.x** + +* As of June 2024, CentOS Linux 7.x has reached its End of Life and is no longer supported by SQreamDB. + +► **DateTime2 Alias** + +As of April 2025, the alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. + +Upgrading to Version 4.11 +------------------------- + +1. Generate a back-up of the metadata by running the following command: + + .. code-block:: console + + select backup_metadata('out_path'); + + .. tip:: SQreamDB recommends storing the generated back-up locally in case needed. + + SQreamDB runs the Garbage Collector and creates a clean backup tarball package. + +2. Shut down all SQreamDB services. + +3. Copy the recently created back-up file. + +4. Replace your current metadata with the metadata you stored in the back-up file. + +5. Navigate to the new SQreamDB package bin folder. + +6. Run the following command: + + .. code-block:: console + + ./upgrade_storage <levelDB path> + + + + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + diff --git a/releases/index.rst b/releases/index.rst index 0d550b613..b78bab2a5 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,6 +4,8 @@ Release Notes ************* +:ref:`Version 4.12 - May 15th, 2025<4.12>` + :ref:`Version 4.11 - April 9th, 2025<4.11>` :ref:`Version 4.10 - January 20, 2025<4.10>` diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 0799468a1..295884c48 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -35,9 +35,13 @@ SQDB Releases Timeline - Release Date - Maintenance Mode - End of Support + * - ``4.12`` + - May 15th 2025 + - TBD + - May 15th 2026 * - ``4.11`` - April 9th 2025 - - TBD + - May 15th 2025 - April 9th 2026 * - ``4.10`` - January 20th 2025 From 53957ca13cffc594b07a405d398dcfae73a8ea89 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 10 Apr 2025 08:56:53 +0300 Subject: [PATCH 1820/1892] Update 4.12.rst --- releases/4.12.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 03e0d8ab3..73e51d597 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -1,10 +1,10 @@ -.. _4.11: +.. _4.12: ***************** -Release Notes 4.11 +Release Notes 4.12 ***************** -The 4.11 release notes were released on May 15th, 2025 +The 4.12 release notes were released on May 15th, 2025 .. contents:: :local: @@ -36,7 +36,7 @@ Known Issues :ref:`Percentile<percentile_disc>` is not supported for :ref:`Window Functions<window_functions>` -Version 4.11 resolved Issues +Version 4.12 resolved Issues --------------------------- +--------------+---------------------------------------------------------------------------------------------------------------------+ @@ -63,7 +63,7 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re As of April 2025, the alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. -Upgrading to Version 4.11 +Upgrading to Version 4.12 ------------------------- 1. Generate a back-up of the metadata by running the following command: From 24900dd1f99f46b25db1ce99b8f2968d6d687cbd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:00:04 +0300 Subject: [PATCH 1821/1892] column ddl permission deprecation --- operational_guides/access_control_permissions.rst | 3 --- releases/4.12.rst | 10 +++++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/operational_guides/access_control_permissions.rst b/operational_guides/access_control_permissions.rst index b3e1152b8..2e0dc862a 100644 --- a/operational_guides/access_control_permissions.rst +++ b/operational_guides/access_control_permissions.rst @@ -73,8 +73,6 @@ The following table describe the required permissions for performing and executi +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``SELECT`` | Select from column | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ -| ``DDL`` | Column DDL operations | -+----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``INSERT`` | :ref:`insert` into the column | +----------------------+-------------------------------------------------------------------------------------------------------------------------+ | ``UPDATE`` | :ref:`update` the value of certain columns in existing rows | @@ -193,7 +191,6 @@ GRANT GRANT { { SELECT - | DDL | INSERT | UPDATE } [, ...] | ALL [PERMISSIONS] diff --git a/releases/4.12.rst b/releases/4.12.rst index 73e51d597..45c1cf133 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -26,9 +26,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► SQDB's new ``DATETIME2`` data type delivers nanosecond precision and timezone notation, for reliable and accurate time-based data. +► Metadata partitioning. -► Array decompress to run on GPU (Performance improvement). +► PUT. Known Issues @@ -51,9 +51,13 @@ Version 4.12 resolved Issues Deprecation ------------------- +► **Column ``DDL`` permission** + +Column ``DDL`` permission is now deprecated as its functionality is fully included within the table ``DDL`` permission. Upon upgrading to this version, all existing column ``DDL`` permissions will be automatically revoked. + ► **Haskell CLI** -Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatability. +Starting October 2024, support for the Haskell CLI is discontinued, and it is replaced by the :ref:`Multi Platform CLI<multi_platform_cli>` that is compatible with the Haskell CLI with the added value of ``Table-View`` and cross platform compatibility. ► **CentOS Linux 7.x** From a495112137e4fcd96d434971b22d57ec5328a6a8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 17 Apr 2025 11:04:01 +0300 Subject: [PATCH 1822/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 45c1cf133..efe916a84 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -51,7 +51,7 @@ Version 4.12 resolved Issues Deprecation ------------------- -► **Column ``DDL`` permission** +► **Column DDL permission** Column ``DDL`` permission is now deprecated as its functionality is fully included within the table ``DDL`` permission. Upon upgrading to this version, all existing column ``DDL`` permissions will be automatically revoked. From bcbe4c52e0d36aa0b74c2a1bdb89e789b97cf802 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 29 Apr 2025 15:42:10 +0300 Subject: [PATCH 1823/1892] Logs update --- .../current_method_configuration_levels.rst | 64 +------------------ operational_guides/logging.rst | 4 +- 2 files changed, 5 insertions(+), 63 deletions(-) diff --git a/configuration_guides/current_method_configuration_levels.rst b/configuration_guides/current_method_configuration_levels.rst index f0d0bb714..d91cb476a 100644 --- a/configuration_guides/current_method_configuration_levels.rst +++ b/configuration_guides/current_method_configuration_levels.rst @@ -164,24 +164,12 @@ Flag List - Checks for CUDA errors after producing each chunk. - boolean - ``FALSE`` - * - ``enableLogDebug`` - - SUPERUSER - - Session - - Enables creating and logging in the clientLogger_debug file. - - boolean - - ``TRUE`` * - ``enableNvprofMarkers`` - SUPERUSER - Session - Activates the Nvidia profiler (nvprof) markers. - boolean - - ``FALSE`` - * - ``endLogMessage`` - - SUPERUSER - - Session - - Appends a string at the end of every log line. - - string - - ``EOM`` + - ``FALSE`` * - ``extentStorageFileSizeMB`` - SUPERUSER - Cluster @@ -217,55 +205,7 @@ Flag List - Session - Sets the buffer size. - uint - - ``524288`` - * - ``logClientLevel`` - - SUPERUSER - - Cluster - - Used to control which :ref:`log level<information_level>` should appear in the logs. Value range: ``0`` - ``6`` - - int - - Default value: ``4`` - - Acceptable values: - - ``0`` - Only SYSTEM level logs - - ``1`` - SYSTEM and FATAL - - ``2`` - SYSTEM, FATAL, and ERROR level logs - - ``3`` - SYSTEM, FATAL, ERROR, and WARNING level logs - - ``4`` - SYSTEM, FATAL, ERROR, WARNING, and INFO level logs - - ``5`` - SYSTEM, FATAL, ERROR, WARNING, INFO, and DEBUG level logs - - ``6`` - SYSTEM, FATAL, ERROR, WARNING, INFO, DEBUG, and TRACE level logs - * - ``logFileRotateTimeFrequency`` - - SUPERUSER - - Cluster - - Specifies when the system begins writing to a new log file. SQreamDB recommends using the ``logFileRotateTimeFrequency`` flag (rather than the ``logMaxFilesSizeMB`` flag) to configure when a new log file is created, as this flag does not limit the number of log files. - - string - - ``daily``. Acceptable values: ``daily``, ``weekly``, or ``monthly`` - * - ``logMaxFilesSizeMB`` - - SUPERUSER - - Cluster - - Specifies when the system begins writing to a new log file. When configured with the ``logMaxFilesSizeMB`` flag, the system maintains up to 13 log files. Once the 13th file is complete, the oldest log file is overwritten by the newly created log file. SQreamDB recommends using the ``logFileRotateTimeFrequency`` flag to configure when a new log file is created, as this flag does not limit the number of log files. - - int - - ``100`` (Megabyte) - * - ``logSysLevel`` - - Anyone - - Session - - - Determines the client log level: - 0 - L_SYSTEM, - 1 - L_FATAL, - 2 - L_ERROR, - 3 - L_WARN, - 4 - L_INFO, - 5 - L_DEBUG, - 6 - L_TRACE - - uint - - ``100000`` + - ``524288`` * - ``maxAvgBlobSizeToCompressOnGpu`` - Anyone - Session diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index 21b4b2efc..e0bccdc46 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -7,7 +7,9 @@ Logging Locating the Log Files ====================== -The :ref:`storage cluster<storage_cluster>` contains a ``logs`` directory. Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. +The ``logs`` directory path is controlled by a ``DefaultPathToLogs`` cluster flag (legacy config). By default it is set to "~/tmp_logs", the best practice is to set it to ``<cluster home>/logs``. + +Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. .. TODO: expand this by giving some use caes for working with log files directly in sqream (troubleshooting, performance analysis, monitoring, that kind of thing. Stick to things customers actually use and/or we instruct them to do with the logs, not theoretical things they could do with the logs From 965f39bc21b075bd78dcdde187ea43209d869646 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 29 Apr 2025 15:46:39 +0300 Subject: [PATCH 1824/1892] Update logging.rst --- operational_guides/logging.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operational_guides/logging.rst b/operational_guides/logging.rst index e0bccdc46..6b6dbc5ab 100644 --- a/operational_guides/logging.rst +++ b/operational_guides/logging.rst @@ -7,7 +7,7 @@ Logging Locating the Log Files ====================== -The ``logs`` directory path is controlled by a ``DefaultPathToLogs`` cluster flag (legacy config). By default it is set to "~/tmp_logs", the best practice is to set it to ``<cluster home>/logs``. +The ``logs`` directory path is controlled by a ``DefaultPathToLogs`` cluster flag (legacy config). By default it is set to ``~/tmp_log``, the best practice is to set it to ``<cluster home>/logs``. Each worker produces a log file in its own directory, which can be identified by the worker's hostname and port. From 8c315f1fdd8bd34c8be0fd66a5ca0e8a292578b3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 6 May 2025 14:00:12 +0300 Subject: [PATCH 1825/1892] Update pivot_unpivot.rst --- reference/sql/sql_syntax/pivot_unpivot.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_syntax/pivot_unpivot.rst b/reference/sql/sql_syntax/pivot_unpivot.rst index a3949c0ec..b7d44f71b 100644 --- a/reference/sql/sql_syntax/pivot_unpivot.rst +++ b/reference/sql/sql_syntax/pivot_unpivot.rst @@ -20,7 +20,7 @@ Syntax FROM <from_clause> [ PIVOT - (<pivot_expression> + (<pivot_expression1> AS <pivot_expression1_name> [, <pivot_expression2> AS <pivot_expression2_name>, .... , <pivot_expressionN> AS <pivot_expressionN_name>] FOR <column_name> IN ([<expression1> AS] <name1>, [<expression2> AS] <name2>, ... , [<expressionN> AS] <nameN>) ) @@ -85,7 +85,7 @@ The ``PIVOT`` operation creates a new table with ProductName as the first column FROM Sales ) AS SourceTable PIVOT ( - SUM(Revenue) + SUM(Revenue) AS RevenueSum FOR SalesDate IN ("2024-01-01", "2024-01-02") ) AS PivotTable; From 7925047c803d602e75341b065ab0e2bd11f6bc26 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 May 2025 09:02:23 +0300 Subject: [PATCH 1826/1892] java 17 --- connecting_to_sqream/client_drivers/index.rst | 2 +- connecting_to_sqream/client_drivers/jdbc/index.rst | 9 ++------- connecting_to_sqream/client_platforms/denodo.rst | 2 +- .../client_platforms/sql_workbench.rst | 11 +---------- reference/cli/multi_platform_cli.rst | 2 +- 5 files changed, 6 insertions(+), 20 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 21b7afd44..051b627a1 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-5.5.0.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.0.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All diff --git a/connecting_to_sqream/client_drivers/jdbc/index.rst b/connecting_to_sqream/client_drivers/jdbc/index.rst index ccc821476..c1198bd1d 100644 --- a/connecting_to_sqream/client_drivers/jdbc/index.rst +++ b/connecting_to_sqream/client_drivers/jdbc/index.rst @@ -4,7 +4,7 @@ JDBC **** -The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 1.8 or newer. +The SQream JDBC driver lets you connect to SQream using many Java applications and tools. This page describes how to write a Java application using the JDBC interface. The JDBC driver requires Java 17 or newer. .. contents:: :local: @@ -22,13 +22,8 @@ The **Installing the JDBC Driver** section describes the following: Prerequisites ------------- -The SQream JDBC driver requires Java 1.8 or newer, and SQream recommends using Oracle Java or OpenJDK.: +The SQream JDBC driver requires Java 17 or newer, and SQream recommends using Oracle Java or OpenJDK.: -* **Oracle Java** - Download and install `Java 8 <https://www.java.com/en/download/manual.jsp>`_ from Oracle for your platform. - -* **OpenJDK** - Install `OpenJDK <https://openjdk.java.net/install/>`_ - -* **Windows** - SQream recommends installing `Zulu 8 <https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk>`_ Getting the JAR file -------------------- diff --git a/connecting_to_sqream/client_platforms/denodo.rst b/connecting_to_sqream/client_platforms/denodo.rst index 76da3264f..35eb33301 100644 --- a/connecting_to_sqream/client_platforms/denodo.rst +++ b/connecting_to_sqream/client_platforms/denodo.rst @@ -12,7 +12,7 @@ Before You Begin It is essential that you have the following installed: * Denodo 8.0 -* Java 1.8 +* Java 17 Setting Up a Connection to SQreamDB =================================== diff --git a/connecting_to_sqream/client_platforms/sql_workbench.rst b/connecting_to_sqream/client_platforms/sql_workbench.rst index 8d983eed9..b5006a7b0 100644 --- a/connecting_to_sqream/client_platforms/sql_workbench.rst +++ b/connecting_to_sqream/client_platforms/sql_workbench.rst @@ -43,17 +43,8 @@ This section applies to Linux and MacOS only. Install Java Runtime -------------------- -Both SQL Workbench and the SQream DB JDBC driver require Java 1.8 or newer. You can install either Oracle Java or OpenJDK. +Both SQL Workbench and the SQream DB JDBC driver require Java 17 or newer. You can install either Oracle Java or OpenJDK. -**Oracle Java** - -Download and install Java 8 from Oracle for your platform - https://www.java.com/en/download/manual.jsp - -**OpenJDK** - -For Linux and BSD, see https://openjdk.java.net/install/ - -For Windows, SQream recommends Zulu 8 https://www.azul.com/downloads/zulu-community/?&version=java-8-lts&architecture=x86-64-bit&package=jdk Get the SQream DB JDBC Driver ----------------------------- diff --git a/reference/cli/multi_platform_cli.rst b/reference/cli/multi_platform_cli.rst index 223c81871..69b71c893 100644 --- a/reference/cli/multi_platform_cli.rst +++ b/reference/cli/multi_platform_cli.rst @@ -13,7 +13,7 @@ SQreamDB comes with a built-in client for executing SQL statements either intera Before You Begin ================ -Sqream SQL requires Java 8 +Sqream SQL requires Java 17 Installing Sqream SQL ===================== From d5b9d1f7abce09266e4909d7e3eb5b16119dd354 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 11 May 2025 09:30:12 +0300 Subject: [PATCH 1827/1892] Update 4.12.rst --- releases/4.12.rst | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index efe916a84..d665e9ca5 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -26,9 +26,13 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► Metadata partitioning. +► Metadata partitioning significantly reduces statement execution time by intelligently leveraging previously created metadata partitions for efficient data skipping. -► PUT. +► New SQL syntax for ``PUT``, ``GET``, and ``REMOVE`` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. + +► We've upgraded our platform to Java 17, bringing performance enhancements and the latest security features. + +► The ``PIVOT`` functionality has been updated to now support multi-column pivoting. Known Issues @@ -42,9 +46,12 @@ Version 4.12 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ -| SQ-xxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | +| SQ-19869 | Queries with numerous STDDEV aggregations are experiencing long compilation time. | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-19879 | Default permissions for saved queries are not automatically created upon new database creation. | ++--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-20146 | The ``PIVOT`` function does not allow renaming of pivoted columns using aliases. | +--------------+---------------------------------------------------------------------------------------------------------------------+ - From a2ad241eebd2ec35afe85f243203d176c50fecb6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 May 2025 11:06:16 +0300 Subject: [PATCH 1828/1892] Update 4.12.rst --- releases/4.12.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/releases/4.12.rst b/releases/4.12.rst index d665e9ca5..d746369eb 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -61,6 +61,7 @@ Deprecation ► **Column DDL permission** Column ``DDL`` permission is now deprecated as its functionality is fully included within the table ``DDL`` permission. Upon upgrading to this version, all existing column ``DDL`` permissions will be automatically revoked. +If you are upgrading from a release using the old behavior, please contact SQream support prior to performing the upgrade. ► **Haskell CLI** From 19f649378fccc63478edd9b98ccc1bc8197cf1a6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 12 May 2025 16:50:26 +0300 Subject: [PATCH 1829/1892] Update data_encryption_syntax.rst --- feature_guides/data_encryption_syntax.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/data_encryption_syntax.rst b/feature_guides/data_encryption_syntax.rst index ff1628891..5642c7092 100644 --- a/feature_guides/data_encryption_syntax.rst +++ b/feature_guides/data_encryption_syntax.rst @@ -52,7 +52,7 @@ Inserting encrypt player salary (``INT`` data type) .. code-block:: psql INSERT INTO NBA (player_name, team_name, jersey_number, position, age, height, weight, college, salary) - VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f'); + VALUES ('Jayson Christopher Tatum', 'Boston Celtics', 0, 'SF', 25, '6-8', 210 , 'Duke', ENCRYPT ( 32600060 , '6a8431f6e9c2777ee356c0b8aa3c12c0c63bdf366ac3342c4c9184b51697b47f')); Similar example using ``COPY FROM`` From 79eabe361597ba0c2fca8a0ba8ade3b297f5aebd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 08:57:43 +0300 Subject: [PATCH 1830/1892] accelerating_filtered_queries_with_metadata_partitions --- ...tered_queries_with_metadata_partitions.rst | 97 +++++++++++++++++++ operational_guides/index.rst | 1 + 2 files changed, 98 insertions(+) create mode 100644 operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst diff --git a/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst new file mode 100644 index 000000000..019589753 --- /dev/null +++ b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst @@ -0,0 +1,97 @@ +.. _accelerating_filtered_statements: + +************************* +Accelerating Filtered Statements +************************* + +This page outlines a feature designed to significantly improve the performance of statements that include filters on large tables. By using **Metadata Partitions**, SQDB minimize the overhead associated with metadata scanning, leading to faster statement execution times, especially as tables grow. + +.. contents:: + :local: + :depth: 1 + +The Challenge: Metadata Scan Overhead +===================================== + +When you execute a statement with a filter (e.g., ``SELECT x, y FROM table1 WHERE X=7;``), the system needs to scan the metadata of each data chunk within the table to identify the relevant chunks containing the data that satisfies your filter condition. As tables scale to trillions of rows, this metadata scanning process can become a significant bottleneck, adding substantial latency to your statements. In some cases, this overhead can reach tens of seconds for very large tables. + +The Solution: Metadata Partitions +================================= + +To address this challenge, SQDB introduced **Metadata Partitions**. This feature creates an internal metadata metadata partitoning structure for each table, grouping data chunks based on the minimum and maximum values of sorted columns within those chunks. This allows the system to efficiently identify and target only the relevant partitions during a filtered statement, drastically reducing the amount of metadata that needs to be scanned. + + +Managing Metadata Partitions +============================ + +A new SQL function, `recalculate_metadata_partition`, is introduced to manage and update the Metadata Partitions for your tables. + +Syntax +====== + +.. code-block:: postgres + + SELECT recalculate_metadata_partition('<schema_name>', '<table_name>', '<column1_name>', ... , '<columnN_name>', ['true'/'false']) + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``schema_name`` + - The name of the schema + * - ``table_name`` + - The name of the table + * - ``column_name`` + - A list of column names to create metadata partitions for - a minimum of one column must be specified + * - ``case_sensitive_flag`` + - ``'false'`` (default) ignore case sensitivity. ``'true'`` for case sensitive. + + +Important Considerations +======================== + + * ```recalculate_metadata_partition`` function requires ``SUPERUSER`` privileges. + * **Impact of Data Modifications:** + * ``INSERT`` New chunks will be added, and a full scan of these new chunks will be performed until the Metadata Partition is updated. + * ``DELETE`` The existing metadata partition might still be used, potentially leading to false positives (pointing to non-existent chunks) - which will later get filtered out from the statement results. + * ``UPDATE`` The existing metadata partition will become irrelevant and will not be used. + * **Rechunk/ReExtent:** These operations will require dropping and recreating the Metadata Partition. + * The ``recalculate_metadata_partition`` utility is designed to be CPU-based, ensuring that it does not impact GPU-intensive workloads. + + +### Monitoring Metadata Partitions + +A new catalog statement is available to list the existing Metadata Partitions and their status: + +```sql +-- Example catalog statement (specific syntax may vary, please refer to your Studio documentation) +SELECT db_name, schema_name, table_name, column_name, last_update, total_chunks_per_column, total_metadata partitoned_chunks_per_column +FROM sqream_catalog.metadata_partitions; +``` + +Your Studio interface will also incorporate this catalog statement, providing a user-friendly way to view and manage your Metadata Partitions. + +### Backward Compatibility and Upgrade + + * This feature is backward compatible. Existing statements will continue to function correctly after the upgrade. + * Upon upgrading to a version that supports Metadata Partitioning, you will need to manually execute the `recalculate_metadata_partition` function for each column you want to benefit from this optimization. + * Future upgrades and modifications to the metadata metadata partitoning mechanism will be seamlessly integrated into the standard storage upgrade process. + +### Performance Expectations + +statements with filters on large tables (1 trillion rows or more) are expected to exhibit a significant reduction in metadata scan time. The runtime of these statements should demonstrate minimal growth as the table size increases, aiming for no more than a 1% increase in runtime per trillion rows added. This improvement will address the current bottleneck where metadata scans can take tens of seconds on very large tables. + +### Security + +The `recalculate_metadata_partition` function is protected and requires `SUPERUSER` privileges to execute, ensuring that only authorized users can manage these critical metadata structures. + +### Storage Implications + +The introduction of Metadata Partitions is expected to have a negligible impact on storage overhead (less than 1% increase in overall metadata size). + +By leveraging Metadata Partitions, you can expect a substantial improvement in the performance of your filtered statements, especially on large datasets, leading to a more responsive and efficient data analysis experience. \ No newline at end of file diff --git a/operational_guides/index.rst b/operational_guides/index.rst index ec5009a21..e5f640a59 100644 --- a/operational_guides/index.rst +++ b/operational_guides/index.rst @@ -14,6 +14,7 @@ This section summarizes the following operational guides: :titlesonly: access_control + accelerating_filtered_queries_with_metadata_partitions creating_or_cloning_a_storage_cluster external_data foreign_tables From a8ce62cec48351e4799f7e2d8e3da6131a7bb908 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 13:45:02 +0300 Subject: [PATCH 1831/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 051b627a1..ac19c1e32 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.3.0-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.4-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From b224c52b2114e3c25ecb9e1b04f1a5bc54eb7ad9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 14:41:39 +0300 Subject: [PATCH 1832/1892] Update accelerating_filtered_queries_with_metadata_partitions.rst --- ...tered_queries_with_metadata_partitions.rst | 38 ++++--------------- 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst index 019589753..603fc1c15 100644 --- a/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst +++ b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst @@ -31,7 +31,7 @@ Syntax .. code-block:: postgres - SELECT recalculate_metadata_partition('<schema_name>', '<table_name>', '<column1_name>', ... , '<columnN_name>', ['true'/'false']) + SELECT recalculate_metadata_partition('<schema_name>', '<table_name>', '<column_name>', ['true'/'false']) Parameters ========== @@ -47,9 +47,9 @@ Parameters * - ``table_name`` - The name of the table * - ``column_name`` - - A list of column names to create metadata partitions for - a minimum of one column must be specified + - The name of the column * - ``case_sensitive_flag`` - - ``'false'`` (default) ignore case sensitivity. ``'true'`` for case sensitive. + - optional input - ``'false'`` (default) ignore case sensitivity. ``'true'`` for case sensitivity. Important Considerations @@ -60,38 +60,16 @@ Important Considerations * ``INSERT`` New chunks will be added, and a full scan of these new chunks will be performed until the Metadata Partition is updated. * ``DELETE`` The existing metadata partition might still be used, potentially leading to false positives (pointing to non-existent chunks) - which will later get filtered out from the statement results. * ``UPDATE`` The existing metadata partition will become irrelevant and will not be used. - * **Rechunk/ReExtent:** These operations will require dropping and recreating the Metadata Partition. + * ``CLEANUP_CHUNKS``, ``CLEANUP_EXTENNTS``, ``RECHUNK`` These operations will require dropping and recreating the Metadata Partition. * The ``recalculate_metadata_partition`` utility is designed to be CPU-based, ensuring that it does not impact GPU-intensive workloads. -### Monitoring Metadata Partitions +Monitoring Metadata Partitions +============================== A new catalog statement is available to list the existing Metadata Partitions and their status: -```sql --- Example catalog statement (specific syntax may vary, please refer to your Studio documentation) +.. code-block:: postgres + SELECT db_name, schema_name, table_name, column_name, last_update, total_chunks_per_column, total_metadata partitoned_chunks_per_column FROM sqream_catalog.metadata_partitions; -``` - -Your Studio interface will also incorporate this catalog statement, providing a user-friendly way to view and manage your Metadata Partitions. - -### Backward Compatibility and Upgrade - - * This feature is backward compatible. Existing statements will continue to function correctly after the upgrade. - * Upon upgrading to a version that supports Metadata Partitioning, you will need to manually execute the `recalculate_metadata_partition` function for each column you want to benefit from this optimization. - * Future upgrades and modifications to the metadata metadata partitoning mechanism will be seamlessly integrated into the standard storage upgrade process. - -### Performance Expectations - -statements with filters on large tables (1 trillion rows or more) are expected to exhibit a significant reduction in metadata scan time. The runtime of these statements should demonstrate minimal growth as the table size increases, aiming for no more than a 1% increase in runtime per trillion rows added. This improvement will address the current bottleneck where metadata scans can take tens of seconds on very large tables. - -### Security - -The `recalculate_metadata_partition` function is protected and requires `SUPERUSER` privileges to execute, ensuring that only authorized users can manage these critical metadata structures. - -### Storage Implications - -The introduction of Metadata Partitions is expected to have a negligible impact on storage overhead (less than 1% increase in overall metadata size). - -By leveraging Metadata Partitions, you can expect a substantial improvement in the performance of your filtered statements, especially on large datasets, leading to a more responsive and efficient data analysis experience. \ No newline at end of file From f79c754745862166fbd39acd1ea8e2c010d423f9 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 16:54:51 +0300 Subject: [PATCH 1833/1892] Update accelerating_filtered_queries_with_metadata_partitions.rst --- ...celerating_filtered_queries_with_metadata_partitions.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst index 603fc1c15..d91e38b75 100644 --- a/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst +++ b/operational_guides/accelerating_filtered_queries_with_metadata_partitions.rst @@ -31,7 +31,7 @@ Syntax .. code-block:: postgres - SELECT recalculate_metadata_partition('<schema_name>', '<table_name>', '<column_name>', ['true'/'false']) + SELECT recalculate_metadata_partition('<schema_name>', '<table_name>', '<column_name>', ['true'/'false']); Parameters ========== @@ -71,5 +71,5 @@ A new catalog statement is available to list the existing Metadata Partitions an .. code-block:: postgres -SELECT db_name, schema_name, table_name, column_name, last_update, total_chunks_per_column, total_metadata partitoned_chunks_per_column -FROM sqream_catalog.metadata_partitions; + SELECT db_name, schema_name, table_name, column_name, last_update, total_chunks_per_column, total_metadata partitoned_chunks_per_column + FROM sqream_catalog.metadata_partitions; From 3622dea099c1a7fd637b0d5a7078e64564e3d8a3 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:19:49 +0300 Subject: [PATCH 1834/1892] get --- reference/sql/sql_statements/index.rst | 2 + .../sql_statements/utility_commands/get.rst | 48 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/get.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 07b968ff3..5dcfd6bb3 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -123,6 +123,8 @@ The following table shows the Utility commands: - Returns a static query plan, which can be used to debug query plans * - :ref:`export_open_snapshots` - Lists and saves information about all currently open snapshots to a specified file + * - :ref:`GET<get>` + - Transfer data files stored within the database's internal staging areas to a user's local file system. * - :ref:`get_chunk_info` - Retrieves information of specific chunks * - :ref:`GET DDL<get_ddl>` diff --git a/reference/sql/sql_statements/utility_commands/get.rst b/reference/sql/sql_statements/utility_commands/get.rst new file mode 100644 index 000000000..3aeab6ae0 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/get.rst @@ -0,0 +1,48 @@ +:orphan: + +.. _get: + +*** +GET +*** + +The ``GET`` function addresses the need to transfer data files stored within the database's internal staging areas to a user's local file system. + + +Syntax +====== + +.. code-block:: postgres + + GET <'SQDB-cluster-relative-file-path'> TO <'local-file-path'> + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``SQDB-cluster-relative-file-path`` + - Source File path - relative to the defined SQDB cluster staging area. + * - ``local-file-path`` + - Destination File path - on the executing client machine. + +Important Considerations +======================== + * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * The command is limited to a single file copy per execution. + * File extensions are limited to supported FDWs. + * The command execution is CPU based and does not use GPU Workers. + * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + + + + + +Permissions +============= + +The role must have the ``SUPERUSER`` privilege. \ No newline at end of file From 258d59851ed92cc0895da96ff95e03eeec7a5c65 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:31:22 +0300 Subject: [PATCH 1835/1892] put --- reference/sql/sql_statements/index.rst | 4 +- .../sql_statements/utility_commands/get.rst | 3 +- .../sql_statements/utility_commands/put.txt | 52 +++++++++++++++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 reference/sql/sql_statements/utility_commands/put.txt diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 5dcfd6bb3..1f70e9d71 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -124,7 +124,7 @@ The following table shows the Utility commands: * - :ref:`export_open_snapshots` - Lists and saves information about all currently open snapshots to a specified file * - :ref:`GET<get>` - - Transfer data files stored within the database's internal staging areas to a user's local file system. + - Transfer data files stored within the database's internal staging area to a user's local file system. * - :ref:`get_chunk_info` - Retrieves information of specific chunks * - :ref:`GET DDL<get_ddl>` @@ -151,6 +151,8 @@ The following table shows the Utility commands: - Enables you to specify the LDAP attributes you want the SQreamDB role catalog table to show * - :ref:`LIST SAVED QUERIES<list_saved_queries>` - Lists previously saved query names, one per row + * - :ref:`PUT<put>` + - Transfer data files stored within a user's local file system to the database's internal staging area. * - :ref:`RECHUNK<rechunk>` - Enables you to merge small data chunks into larger ones * - :ref:`RECOMPILE SAVED QUERY<recompile_saved_query>` diff --git a/reference/sql/sql_statements/utility_commands/get.rst b/reference/sql/sql_statements/utility_commands/get.rst index 3aeab6ae0..90c582e62 100644 --- a/reference/sql/sql_statements/utility_commands/get.rst +++ b/reference/sql/sql_statements/utility_commands/get.rst @@ -6,7 +6,7 @@ GET *** -The ``GET`` function addresses the need to transfer data files stored within the database's internal staging areas to a user's local file system. +The ``GET`` function addresses the need to transfer data files stored within the database's internal staging area to a user's local file system. Syntax @@ -37,6 +37,7 @@ Important Considerations * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * File size may be up to 25MB. diff --git a/reference/sql/sql_statements/utility_commands/put.txt b/reference/sql/sql_statements/utility_commands/put.txt new file mode 100644 index 000000000..57ef70cf5 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/put.txt @@ -0,0 +1,52 @@ +:orphan: + +.. _pet: + +*** +PUT +*** + +The ``PUT`` function addresses the need to transfer data files stored in a user's local file system to the database's internal staging area. + + +Syntax +====== + +.. code-block:: postgres + + PUT <'local-file-path'> INTO <'SQDB-cluster-relative-file-path'> [OVERWRITE] + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``local-file-path`` + - Source File path - on the executing client machine. + * - ``SQDB-cluster-relative-file-path`` + - Destination File path - relative to the defined SQDB cluster staging area. + * - ``OVERWRITE`` + - When used existing files will be overridden. + + +Important Considerations +======================== + * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * The command is limited to a single file copy per execution. + * File extensions are limited to supported FDWs. + * The command execution is CPU based and does not use GPU Workers. + * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * File size may be up to 25MB. + + + + + +Permissions +============= + +The role must have the ``SUPERUSER`` privilege. \ No newline at end of file From 8a1f270f7ce47f2e0258b74053c10fc9eeb2f1a8 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:36:14 +0300 Subject: [PATCH 1836/1892] put2 --- .../sql/sql_statements/utility_commands/{put.txt => put.rst} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename reference/sql/sql_statements/utility_commands/{put.txt => put.rst} (100%) diff --git a/reference/sql/sql_statements/utility_commands/put.txt b/reference/sql/sql_statements/utility_commands/put.rst similarity index 100% rename from reference/sql/sql_statements/utility_commands/put.txt rename to reference/sql/sql_statements/utility_commands/put.rst From 810f4bd59cca0dc06e5c693f197c320ab2b5bd70 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:39:07 +0300 Subject: [PATCH 1837/1892] Update put.rst --- reference/sql/sql_statements/utility_commands/put.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reference/sql/sql_statements/utility_commands/put.rst b/reference/sql/sql_statements/utility_commands/put.rst index 57ef70cf5..8f3187be2 100644 --- a/reference/sql/sql_statements/utility_commands/put.rst +++ b/reference/sql/sql_statements/utility_commands/put.rst @@ -1,6 +1,6 @@ :orphan: -.. _pet: +.. _put: *** PUT From 6318e26bcfd73357ae1069533c1ac192dc483ae0 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:45:51 +0300 Subject: [PATCH 1838/1892] remove --- reference/sql/sql_statements/index.rst | 2 + .../utility_commands/remove.rst | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 reference/sql/sql_statements/utility_commands/remove.rst diff --git a/reference/sql/sql_statements/index.rst b/reference/sql/sql_statements/index.rst index 1f70e9d71..b983876b2 100644 --- a/reference/sql/sql_statements/index.rst +++ b/reference/sql/sql_statements/index.rst @@ -159,6 +159,8 @@ The following table shows the Utility commands: - Recompiles a saved query that has been invalidated due to a schema change * - :ref:`RECOMPILE VIEW<recompile_view>` - Recreate a view after schema changes + * - :ref:`REMOVE<remove>` + - Delete data files stored within the database's internal staging area. * - :ref:`REMOVE LOCK<remove_lock>` - Clears locks * - :ref:`REMOVE STATEMENT LOCKS<remove_statement_locks>` diff --git a/reference/sql/sql_statements/utility_commands/remove.rst b/reference/sql/sql_statements/utility_commands/remove.rst new file mode 100644 index 000000000..becec51c3 --- /dev/null +++ b/reference/sql/sql_statements/utility_commands/remove.rst @@ -0,0 +1,47 @@ +:orphan: + +.. _remove: + +****** +REMOVE +****** + +The ``REMOVE`` function addresses the need to remove files from the database's internal staging area. + + +Syntax +====== + +.. code-block:: postgres + + REMOVE <'SQDB-cluster-relative-file-path'> + +Parameters +========== + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Parameter + - Description + * - ``SQDB-cluster-relative-file-path`` + - File path to remove - relative to the defined SQDB cluster staging area. + + +Important Considerations +======================== + * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * The command is limited to a single file deletion per execution. + * File extensions are limited to supported FDWs. + * The command execution is CPU based and does not use GPU Workers. + * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + + + + + +Permissions +============= + +The role must have the ``SUPERUSER`` privilege. \ No newline at end of file From 887ed94aa31a7bf65f10b81f0553f35407b1e185 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:49:16 +0300 Subject: [PATCH 1839/1892] putgetremove --- reference/sql/sql_statements/utility_commands/get.rst | 2 +- reference/sql/sql_statements/utility_commands/put.rst | 2 +- reference/sql/sql_statements/utility_commands/remove.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get.rst b/reference/sql/sql_statements/utility_commands/get.rst index 90c582e62..c49fcce5e 100644 --- a/reference/sql/sql_statements/utility_commands/get.rst +++ b/reference/sql/sql_statements/utility_commands/get.rst @@ -36,7 +36,7 @@ Important Considerations * The command is limited to a single file copy per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. - * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. * File size may be up to 25MB. diff --git a/reference/sql/sql_statements/utility_commands/put.rst b/reference/sql/sql_statements/utility_commands/put.rst index 8f3187be2..de1c8940e 100644 --- a/reference/sql/sql_statements/utility_commands/put.rst +++ b/reference/sql/sql_statements/utility_commands/put.rst @@ -39,7 +39,7 @@ Important Considerations * The command is limited to a single file copy per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. - * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. * File size may be up to 25MB. diff --git a/reference/sql/sql_statements/utility_commands/remove.rst b/reference/sql/sql_statements/utility_commands/remove.rst index becec51c3..b884c96e3 100644 --- a/reference/sql/sql_statements/utility_commands/remove.rst +++ b/reference/sql/sql_statements/utility_commands/remove.rst @@ -35,7 +35,7 @@ Important Considerations * The command is limited to a single file deletion per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. - * Up to 50 concurrent ''PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. From eb7abd4dbf9e8f49efb4f7071b7cd23191b36d18 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:55:50 +0300 Subject: [PATCH 1840/1892] Update 4.12.rst --- releases/4.12.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index d746369eb..bb8318864 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -26,9 +26,9 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► Metadata partitioning significantly reduces statement execution time by intelligently leveraging previously created metadata partitions for efficient data skipping. +► :ref:`Metadata partitioning<accelerating_filtered_statements>` significantly reduces statement execution time by intelligently leveraging previously created metadata partitions for efficient data skipping. -► New SQL syntax for ``PUT``, ``GET``, and ``REMOVE`` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. +► New SQL syntax for :ref:`PUT<put>``, :ref:`GET<get>`, and :ref:`REMOVE<remove>` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. ► We've upgraded our platform to Java 17, bringing performance enhancements and the latest security features. From 37f2c61daa6e46bcae647372b83e4d6645549212 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Wed, 14 May 2025 17:58:58 +0300 Subject: [PATCH 1841/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index bb8318864..6b5277852 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -28,7 +28,7 @@ New Features and Enhancements ----------------------------- ► :ref:`Metadata partitioning<accelerating_filtered_statements>` significantly reduces statement execution time by intelligently leveraging previously created metadata partitions for efficient data skipping. -► New SQL syntax for :ref:`PUT<put>``, :ref:`GET<get>`, and :ref:`REMOVE<remove>` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. +► New SQL syntax for :ref:`PUT<put>`, :ref:`GET<get>`, and :ref:`REMOVE<remove>` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. ► We've upgraded our platform to Java 17, bringing performance enhancements and the latest security features. From 354753407d9218675fa473d9ac9ff0704da10ccd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 19 May 2025 12:47:58 +0300 Subject: [PATCH 1842/1892] Remove docker mentions --- reference/cli/sqream_cli.rst | 448 ------------------------------- reference/cli/sqream_console.rst | 448 ------------------------------- 2 files changed, 896 deletions(-) delete mode 100644 reference/cli/sqream_cli.rst delete mode 100644 reference/cli/sqream_console.rst diff --git a/reference/cli/sqream_cli.rst b/reference/cli/sqream_cli.rst deleted file mode 100644 index 7d9b709f8..000000000 --- a/reference/cli/sqream_cli.rst +++ /dev/null @@ -1,448 +0,0 @@ -.. _sqream_cli: - -************ -SQreamDB CLI -************ - -``sqream-console`` is an interactive shell designed to help manage a dockerized SQream DB installation. - -The console itself is a dockerized application. - -.. contents:: - :local: - :depth: 1 - -Starting the console -==================== - -``sqream-console`` can be found in your SQream DB installation, under the name ``sqream-console``. - -Start the console by executing it from the shell - -.. code-block:: console - - $ ./sqream-console - .................................................................................................................... - - ███████╗ ██████╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗███████╗ ██████╗ ██╗ ███████╗ - ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗████╗ ████║ ██╔════╝██╔═══██╗████╗ ██║██╔════╝██╔═══██╗██║ ██╔════╝ - ███████╗██║ ██║██████╔╝█████╗ ███████║██╔████╔██║ ██║ ██║ ██║██╔██╗ ██║███████╗██║ ██║██║ █████╗ - ╚════██║██║▄▄ ██║██╔══██╗██╔══╝ ██╔══██║██║╚██╔╝██║ ██║ ██║ ██║██║╚██╗██║╚════██║██║ ██║██║ ██╔══╝ - ███████║╚██████╔╝██║ ██║███████╗██║ ██║██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██║ ╚████║███████║╚██████╔╝███████╗███████╗ - ╚══════╝ ╚══▀▀═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝ - - .................................................................................................................... - - - Welcome to SQream Console ver 1.7.6, type exit to log-out - - usage: sqream [-h] [--settings] {master,worker,client,editor} ... - - Run SQream Cluster - - optional arguments: - -h, --help show this help message and exit - --settings sqream environment variables settings - - subcommands: - sqream services - - {master,worker,client,editor} - sub-command help - master start sqream master - worker start sqream worker - client operating sqream client - editor operating sqream statement editor - sqream-console> - -The console is now waiting for commands. - -The console is a wrapper around a standard linux shell. It supports commands like ``ls``, ``cp``, etc. - -All SQream DB-specific commands start with the keyword ``sqream``. - - -Operations and flag reference -============================= - -Commands --------- - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Command - - Description - * - ``sqream --help`` - - Shows the initial usage information - * - ``sqream master`` - - Controls the master node's operations - * - ``sqream worker`` - - Controls workers' operations - * - ``sqream client`` - - Access to :ref:`sqream sql<sqream_sql_cli_reference>` - * - ``sqream editor`` - - Controls the statement editor's operations (web UI) - -.. _master_node: - -Master ------- - -The master node contains the :ref:`metadata server<metadata_server_cli_reference>` and the :ref:`load balancer<server_picker_cli_reference>`. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream master <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start [ --single-host ]`` - - - Starts the master node. - The ``--single-host`` modifier sets the mode to allow all containers to run on the same server. - - * - ``--stop [ --all ]`` - - - Stops the master node and all connected :ref:`workers<workers>`. - The ``--all`` modifier instructs the ``--stop`` command to stop all running services related to SQream DB - * - ``--list`` - - Shows a list of all active master nodes and their workers - * - ``-p <port>`` - - Sets the port for the load balancer. Defaults to ``3108`` - * - ``-m <port>`` - - Sets the port for the metadata server. Defaults to ``3105`` - -Common usage -^^^^^^^^^^^^ - -Start master node -***************** - -.. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - -Start master node on different ports -************************************ - -.. code-block:: console - - sqream-console> sqream master --start -p 4105 -m 4108 - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 4105,4108 - -Listing active master nodes and workers -*************************************** - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -Stopping all SQream DB workers and master -***************************************** - -.. code-block:: console - - sqream-console> sqream master --stop --all - shutting down 2 sqream services ... - sqream_editor stopped - sqream_single_host_worker_1 stopped - sqream_single_host_worker_0 stopped - sqream_single_host_master stopped - -.. _workers: - -Workers -------- - -Workers are :ref:`SQream DB daemons<sqreamd_cli_reference>`, that connect to the master node. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream worker <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start [ options [ ...] ]`` - - Starts worker nodes. See options table below. - * - ``--stop [ <worker name> | --all ]`` - - - Stops the specified worker name. - The ``--all`` modifier instructs the ``--stop`` command to stop all running workers. - -Start options are specified consecutively, separated by spaces. - -.. list-table:: Start options - :widths: auto - :header-rows: 1 - - * - Option - - Description - * - ``<n>`` - - Specifies the number of workers to start - * - ``-j <config file> [ ...]`` - - Specifies configuration files to apply to each worker. When launching multiple workers, specify one file per worker, separated by spaces. - * - ``-p <port> [ ...]`` - - Sets the ports to listen on. When launching multiple workers, specify one port per worker, separated by spaces. Defaults to 5000 - 5000+n. - * - ``-g <gpu id> [ ...]`` - - Sets the GPU ordinal to assign to each worker. When launching multiple workers, specify one GPU ordinal per worker, separated by spaces. Defaults to automatic allocation. - * - ``-m <spool memory>`` - - Sets the spool memory per node in gigabytes. - * - ``--master-host`` - - Sets the hostname for the master node. Defaults to ``localhost``. - * - ``--master-port`` - - Sets the port for the master node. Defaults to ``3105``. - * - ``--stand-alone`` - - For testing only: Starts a worker without connecting to the master node. - -Common usage -^^^^^^^^^^^^ - -Start 2 workers -*************** - -After starting the master node, start workers: - -.. code-block:: console - - sqream-console> sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - -Stop a single worker -******************** - -To stop a single worker, find its name first: - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -Then, issue a stop command: - -.. code-block:: console - - sqream-console> sqream worker --stop sqream_single_host_worker_1 - stopped sqream_single_host_worker_1 - -Start workers with a different spool size -***************************************** - -If no spool size is specified, the RAM is equally distributed among workers. -Sometimes a system engineer may wish to specify the spool size manually. - -This example starts two workers, with a spool size of 50GB per node: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -m 50 - -Starting multiple workers on non-dedicated GPUs -*********************************************** - -By default, SQream DB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. - -This example starts 4 workers on 2 GPUs, with 50GB spool each: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -g 0 -m 50 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 0 - sqream-console> sqream worker --start 2 -g 1 -m 50 - started sqream_single_host_worker_2 on port 5002, allocated gpu: 1 - started sqream_single_host_worker_3 on port 5003, allocated gpu: 1 - -Overriding default configuration files -************************************** - -It is possible to override default configuration settings by listing a configuration file for every worker. - -This example starts 2 workers on the same GPU, with modified configuration files: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -Client ------- - -The client operation runs :ref:`sqream sql<sqream_sql_cli_reference>` in interactive mode. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream client <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--master`` - - Connects to the master node via the load balancer - * - ``--worker`` - - Connects to a worker directly - * - ``--host <hostname>`` - - Specifies the hostname to connect to. Defaults to ``localhost``. - * - ``--port <port>``, ``-p <port>`` - - Specifies the port to connect to. Defaults to ``3108`` when used with ``-master``. - * - ``--user <username>``, ``-u <username>`` - - Specifies the role's username to use - * - ``--password <password>``, ``-w <password>`` - - Specifies the password to use for the role - * - ``--database <database>``, ``-d <database>`` - - Specifies the database name for the connection. Defaults to ``master``. - -Common usage -^^^^^^^^^^^^ - -Start a client -************** - -Connect to default ``master`` database through the load balancer: - -.. code-block:: console - - sqream-console> sqream client --master -u sqream -w sqream - Interactive client mode - To quit, use ^D or \q. - - master=> _ - -Start a client to a specific worker -*********************************** - -Connect to database ``raviga`` directly to a worker on port 5000: - -.. code-block:: console - - sqream-console> sqream client --worker -u sqream -w sqream -p 5000 -d raviga - Interactive client mode - To quit, use ^D or \q. - - raviga=> _ - -Start master node on different ports -************************************ - -.. code-block:: console - - sqream-console> sqream master --start -p 4105 -m 4108 - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 4105,4108 - -Listing active master nodes and worker nodes -******************************************** - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -.. _start_editor: - -Editor ------- - -The editor operation runs the web UI for the SQreamDB Statement Editor. - -The editor can be used to run queries from a browser. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream editor <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start`` - - Start the statement editor - * - ``--stop`` - - Shut down the statement editor - * - ``--port <port>``, ``-p <port>`` - - Specify a different port for the editor. Defaults to ``3000``. - -Common usage -^^^^^^^^^^^^ - -Start the editor UI -******************* - -.. code-block:: console - - sqream-console> sqream editor --start - access sqream statement editor through Chrome http://192.168.0.100:3000 - -Stop the editor UI -****************** - -.. code-block:: console - - sqream-console> sqream editor --stop - sqream_editor stopped - - -Using the console to start SQream DB -==================================== - -The console is used to start and stop SQream DB components in a dockerized environment. - -Starting a SQream DB cluster for the first time ------------------------------------------------ - -To start a SQream DB cluster, start the master node, followed by workers. - -The example below starts 2 workers, running on 2 dedicated GPUs. - -.. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - sqream-console> sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - sqream-console> sqream editor --start - access sqream statement editor through Chrome http://192.168.0.100:3000 - -SQream DB is now listening on port 3108 for any incoming statements. - -A user can also access the web editor (running on port ``3000`` on the SQream DB machine) to connect and run queries. \ No newline at end of file diff --git a/reference/cli/sqream_console.rst b/reference/cli/sqream_console.rst deleted file mode 100644 index 280ab0b14..000000000 --- a/reference/cli/sqream_console.rst +++ /dev/null @@ -1,448 +0,0 @@ -.. _sqream_console_cli_reference: - -**************** -SqreamDB Console -**************** - -``sqream-console`` is an interactive shell designed to help manage a dockerized SQreamDB installation. - -The console itself is a dockerized application. - -.. contents:: - :local: - :depth: 1 - -Starting the console -==================== - -``sqream-console`` can be found in your SQreamDB installation, under the name ``sqream-console``. - -Start the console by executing it from the shell - -.. code-block:: console - - $ ./sqream-console - .................................................................................................................... - - ███████╗ ██████╗ ██████╗ ███████╗ █████╗ ███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗███████╗ ██████╗ ██╗ ███████╗ - ██╔════╝██╔═══██╗██╔══██╗██╔════╝██╔══██╗████╗ ████║ ██╔════╝██╔═══██╗████╗ ██║██╔════╝██╔═══██╗██║ ██╔════╝ - ███████╗██║ ██║██████╔╝█████╗ ███████║██╔████╔██║ ██║ ██║ ██║██╔██╗ ██║███████╗██║ ██║██║ █████╗ - ╚════██║██║▄▄ ██║██╔══██╗██╔══╝ ██╔══██║██║╚██╔╝██║ ██║ ██║ ██║██║╚██╗██║╚════██║██║ ██║██║ ██╔══╝ - ███████║╚██████╔╝██║ ██║███████╗██║ ██║██║ ╚═╝ ██║ ╚██████╗╚██████╔╝██║ ╚████║███████║╚██████╔╝███████╗███████╗ - ╚══════╝ ╚══▀▀═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚══════╝ ╚═════╝ ╚══════╝╚══════╝ - - .................................................................................................................... - - - Welcome to SQream Console ver 1.7.6, type exit to log-out - - usage: sqream [-h] [--settings] {master,worker,client,editor} ... - - Run SQream Cluster - - optional arguments: - -h, --help show this help message and exit - --settings sqream environment variables settings - - subcommands: - sqream services - - {master,worker,client,editor} - sub-command help - master start sqream master - worker start sqream worker - client operating sqream client - editor operating sqream statement editor - sqream-console> - -The console is now waiting for commands. - -The console is a wrapper around a standard linux shell. It supports commands like ``ls``, ``cp``, etc. - -All SQreamDB-specific commands start with the keyword ``sqream``. - - -Operations and flag reference -============================= - -Commands --------- - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Command - - Description - * - ``sqream --help`` - - Shows the initial usage information - * - ``sqream master`` - - Controls the master node's operations - * - ``sqream worker`` - - Controls workers' operations - * - ``sqream client`` - - Access to :ref:`sqream sql<sqream_sql_cli_reference>` - * - ``sqream editor`` - - Controls the statement editor's operations (web UI) - -.. _master_node: - -Master ------- - -The master node contains the :ref:`metadata server<metadata_server_cli_reference>` and the :ref:`load balancer<server_picker_cli_reference>`. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream master <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start [ --single-host ]`` - - - Starts the master node. - The ``--single-host`` modifier sets the mode to allow all containers to run on the same server. - - * - ``--stop [ --all ]`` - - - Stops the master node and all connected :ref:`workers<workers>`. - The ``--all`` modifier instructs the ``--stop`` command to stop all running services related to SQreamDB - * - ``--list`` - - Shows a list of all active master nodes and their workers - * - ``-p <port>`` - - Sets the port for the load balancer. Defaults to ``3108`` - * - ``-m <port>`` - - Sets the port for the metadata server. Defaults to ``3105`` - -Common usage -^^^^^^^^^^^^ - -Start master node -***************** - -.. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - -Start master node on different ports -************************************ - -.. code-block:: console - - sqream-console> sqream master --start -p 4105 -m 4108 - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 4105,4108 - -Listing active master nodes and workers -*************************************** - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -Stopping all SQreamDB workers and master -***************************************** - -.. code-block:: console - - sqream-console> sqream master --stop --all - shutting down 2 sqream services ... - sqream_editor stopped - sqream_single_host_worker_1 stopped - sqream_single_host_worker_0 stopped - sqream_single_host_master stopped - -.. _workers: - -Workers -------- - -Workers are :ref:`SQreamDB daemons<sqreamd_cli_reference>`, that connect to the master node. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream worker <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start [ options [ ...] ]`` - - Starts worker nodes. See options table below. - * - ``--stop [ <worker name> | --all ]`` - - - Stops the specified worker name. - The ``--all`` modifier instructs the ``--stop`` command to stop all running workers. - -Start options are specified consecutively, separated by spaces. - -.. list-table:: Start options - :widths: auto - :header-rows: 1 - - * - Option - - Description - * - ``<n>`` - - Specifies the number of workers to start - * - ``-j <config file> [ ...]`` - - Specifies configuration files to apply to each worker. When launching multiple workers, specify one file per worker, separated by spaces. - * - ``-p <port> [ ...]`` - - Sets the ports to listen on. When launching multiple workers, specify one port per worker, separated by spaces. Defaults to 5000 - 5000+n. - * - ``-g <gpu id> [ ...]`` - - Sets the GPU ordinal to assign to each worker. When launching multiple workers, specify one GPU ordinal per worker, separated by spaces. Defaults to automatic allocation. - * - ``-m <spool memory>`` - - Sets the spool memory per node in gigabytes. - * - ``--master-host`` - - Sets the hostname for the master node. Defaults to ``localhost``. - * - ``--master-port`` - - Sets the port for the master node. Defaults to ``3105``. - * - ``--stand-alone`` - - For testing only: Starts a worker without connecting to the master node. - -Common usage -^^^^^^^^^^^^ - -Start 2 workers -*************** - -After starting the master node, start workers: - -.. code-block:: console - - sqream-console> sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - -Stop a single worker -******************** - -To stop a single worker, find its name first: - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -Then, issue a stop command: - -.. code-block:: console - - sqream-console> sqream worker --stop sqream_single_host_worker_1 - stopped sqream_single_host_worker_1 - -Start workers with a different spool size -***************************************** - -If no spool size is specified, the RAM is equally distributed among workers. -Sometimes a system engineer may wish to specify the spool size manually. - -This example starts two workers, with a spool size of 50GB per node: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -m 50 - -Starting multiple workers on non-dedicated GPUs -*********************************************** - -By default, SQreamDB workers assign one worker per GPU. However, a system engineer may wish to assign multiple workers per GPU, if the workload permits it. - -This example starts 4 workers on 2 GPUs, with 50GB spool each: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -g 0 -m 50 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 0 - sqream-console> sqream worker --start 2 -g 1 -m 50 - started sqream_single_host_worker_2 on port 5002, allocated gpu: 1 - started sqream_single_host_worker_3 on port 5003, allocated gpu: 1 - -Overriding default configuration files -************************************** - -It is possible to override default configuration settings by listing a configuration file for every worker. - -This example starts 2 workers on the same GPU, with modified configuration files: - -.. code-block:: console - - sqream-console> sqream worker --start 2 -g 0 -j /etc/sqream/configfile.json /etc/sqream/configfile2.json - -Client ------- - -The client operation runs :ref:`sqream sql<sqream_sql_cli_reference>` in interactive mode. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream client <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--master`` - - Connects to the master node via the load balancer - * - ``--worker`` - - Connects to a worker directly - * - ``--host <hostname>`` - - Specifies the hostname to connect to. Defaults to ``localhost``. - * - ``--port <port>``, ``-p <port>`` - - Specifies the port to connect to. Defaults to ``3108`` when used with ``-master``. - * - ``--user <username>``, ``-u <username>`` - - Specifies the role's username to use - * - ``--password <password>``, ``-w <password>`` - - Specifies the password to use for the role - * - ``--database <database>``, ``-d <database>`` - - Specifies the database name for the connection. Defaults to ``master``. - -Common usage -^^^^^^^^^^^^ - -Start a client -************** - -Connect to default ``master`` database through the load balancer: - -.. code-block:: console - - sqream-console> sqream client --master -u sqream -w sqream - Interactive client mode - To quit, use ^D or \q. - - master=> _ - -Start a client to a specific worker -*********************************** - -Connect to database ``raviga`` directly to a worker on port 5000: - -.. code-block:: console - - sqream-console> sqream client --worker -u sqream -w sqream -p 5000 -d raviga - Interactive client mode - To quit, use ^D or \q. - - raviga=> _ - -Start master node on different ports -************************************ - -.. code-block:: console - - sqream-console> sqream master --start -p 4105 -m 4108 - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 4105,4108 - -Listing active master nodes and worker nodes -******************************************** - -.. code-block:: console - - sqream-console> sqream master --list - container name: sqream_single_host_worker_1, container id: de9b8aff0a9c - container name: sqream_single_host_worker_0, container id: c919e8fb78c8 - container name: sqream_single_host_master, container id: ea7eef80e038 - -.. _start_editor: - -Editor ------- - -The editor operation runs the web UI for the SQreamDB Statement Editor. - -The editor can be used to run queries from a browser. - -Syntax -^^^^^^ - -.. code-block:: console - - sqream editor <flags> - -.. list-table:: - :widths: auto - :header-rows: 1 - - * - Flag/command - - Description - * - ``--start`` - - Start the statement editor - * - ``--stop`` - - Shut down the statement editor - * - ``--port <port>``, ``-p <port>`` - - Specify a different port for the editor. Defaults to ``3000``. - -Common usage -^^^^^^^^^^^^ - -Start the editor UI -******************* - -.. code-block:: console - - sqream-console> sqream editor --start - access sqream statement editor through Chrome http://192.168.0.100:3000 - -Stop the editor UI -****************** - -.. code-block:: console - - sqream-console> sqream editor --stop - sqream_editor stopped - - -Using the console to start SQreamDB -=================================== - -The console is used to start and stop SQreamDB components in a dockerized environment. - -Starting a SQreamDB cluster for the first time ----------------------------------------------- - -To start a SQreamDB cluster, start the master node, followed by workers. - -The example below starts 2 workers, running on 2 dedicated GPUs. - -.. code-block:: console - - sqream-console> sqream master --start - starting master server in single_host mode ... - sqream_single_host_master is up and listening on ports: 3105,3108 - - sqream-console> sqream worker --start 2 - started sqream_single_host_worker_0 on port 5000, allocated gpu: 0 - started sqream_single_host_worker_1 on port 5001, allocated gpu: 1 - - sqream-console> sqream editor --start - access sqream statement editor through Chrome http://192.168.0.100:3000 - -SQreamDB is now listening on port 3108 for any incoming statements. - -A user can also access the web editor (running on port ``3000`` on the SQreamDB machine) to connect and run queries. \ No newline at end of file From 458d1384f700576b90bc1a154978a7b92e43609f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 19 May 2025 14:00:18 +0300 Subject: [PATCH 1843/1892] Update put.rst --- reference/sql/sql_statements/utility_commands/put.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/put.rst b/reference/sql/sql_statements/utility_commands/put.rst index de1c8940e..22ab8a6be 100644 --- a/reference/sql/sql_statements/utility_commands/put.rst +++ b/reference/sql/sql_statements/utility_commands/put.rst @@ -35,12 +35,13 @@ Parameters Important Considerations ======================== - * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * File size may be up to 25MB. + * The SQDB cluster staging area's root path is configured using the ``stagingAreaRootPath`` flag. By default, this area is created within the defined ``storageClusterPath`` as a subdirectory named staging_area. This ``staging_area`` directory contains two subdirectories: ``content``, intended for user-uploaded data, and ``temp``, reserved for internal system operations. * The command is limited to a single file copy per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. - * File size may be up to 25MB. + From 69b38e4f3058c7d56db701d6314f64fc367aaddd Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 19 May 2025 14:18:31 +0300 Subject: [PATCH 1844/1892] put updates --- reference/sql/sql_statements/utility_commands/get.rst | 9 +++------ reference/sql/sql_statements/utility_commands/put.rst | 5 +---- reference/sql/sql_statements/utility_commands/remove.rst | 7 ++----- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/reference/sql/sql_statements/utility_commands/get.rst b/reference/sql/sql_statements/utility_commands/get.rst index c49fcce5e..443a8df41 100644 --- a/reference/sql/sql_statements/utility_commands/get.rst +++ b/reference/sql/sql_statements/utility_commands/get.rst @@ -14,7 +14,7 @@ Syntax .. code-block:: postgres - GET <'SQDB-cluster-relative-file-path'> TO <'local-file-path'> + GET <'SQDB-cluster-relative-file-path'> TO <'local-file-path'>; Parameters ========== @@ -32,17 +32,14 @@ Parameters Important Considerations ======================== - * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * File size may be up to 25MB. + * The SQDB cluster staging area's root path is configured using the ``stagingAreaRootPath`` flag. By default, this area is created within the defined ``storageClusterPath`` as a subdirectory named staging_area. This ``staging_area`` directory contains two subdirectories: ``content``, intended for user-uploaded data, and ``temp``, reserved for internal system operations. * The command is limited to a single file copy per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. - * File size may be up to 25MB. - - - Permissions ============= diff --git a/reference/sql/sql_statements/utility_commands/put.rst b/reference/sql/sql_statements/utility_commands/put.rst index 22ab8a6be..49235245d 100644 --- a/reference/sql/sql_statements/utility_commands/put.rst +++ b/reference/sql/sql_statements/utility_commands/put.rst @@ -14,7 +14,7 @@ Syntax .. code-block:: postgres - PUT <'local-file-path'> INTO <'SQDB-cluster-relative-file-path'> [OVERWRITE] + PUT <'local-file-path'> INTO <'SQDB-cluster-relative-file-path'> [OVERWRITE]; Parameters ========== @@ -42,9 +42,6 @@ Important Considerations * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. - - - Permissions diff --git a/reference/sql/sql_statements/utility_commands/remove.rst b/reference/sql/sql_statements/utility_commands/remove.rst index b884c96e3..e6530b820 100644 --- a/reference/sql/sql_statements/utility_commands/remove.rst +++ b/reference/sql/sql_statements/utility_commands/remove.rst @@ -14,7 +14,7 @@ Syntax .. code-block:: postgres - REMOVE <'SQDB-cluster-relative-file-path'> + REMOVE <'SQDB-cluster-relative-file-path'>; Parameters ========== @@ -31,16 +31,13 @@ Parameters Important Considerations ======================== - * The SQDB cluster staging area is configured using the ``stagingAreaRootPath`` flag. + * The SQDB cluster staging area's root path is configured using the ``stagingAreaRootPath`` flag. By default, this area is created within the defined ``storageClusterPath`` as a subdirectory named staging_area. This ``staging_area`` directory contains two subdirectories: ``content``, intended for user-uploaded data, and ``temp``, reserved for internal system operations. * The command is limited to a single file deletion per execution. * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. - - - Permissions ============= From 202df59f59da7cdf343e7b651a02167382405cde Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 20 May 2025 09:54:58 +0300 Subject: [PATCH 1845/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index db4755908..98cf8075c 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -826,7 +826,8 @@ See :ref:`load_type_name` last_updated_dttm date, last_val_int number(22,0) default 0, last_val_ts timestamp (6), - last_val_dt date); + last_val_dt date), + filter varchar2(2000 byte); create index cdc_tracking_idx1 on cdc_tracking (db_name,table_name_full); @@ -843,7 +844,8 @@ See :ref:`load_type_name` LAST_VAL_INT NUMBER DEFAULT 0, LAST_VAL_TS DATETIME, LAST_VAL_DT DATETIME, - LAST_VAL_DT2 DATETIME2 + LAST_VAL_DT2 DATETIME2. + FILTER TEXT ); CREATE TABLE public.CDC_TABLES ( From c31dca23b3d787e4029b38f336b398eac0b5b86c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Tue, 20 May 2025 09:58:07 +0300 Subject: [PATCH 1846/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 98cf8075c..a563cc417 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -826,8 +826,8 @@ See :ref:`load_type_name` last_updated_dttm date, last_val_int number(22,0) default 0, last_val_ts timestamp (6), - last_val_dt date), - filter varchar2(2000 byte); + last_val_dt date, + filter varchar2(2000 byte)); create index cdc_tracking_idx1 on cdc_tracking (db_name,table_name_full); From b9e62feb67b3b0279a25b76442487251e63952de Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 25 May 2025 09:26:44 +0300 Subject: [PATCH 1847/1892] 4.12 updates --- connecting_to_sqream/client_drivers/index.rst | 2 +- releases/4.12.rst | 2 +- releases/index.rst | 2 +- releases/releasePolicy.rst | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index ac19c1e32..14609df27 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.4-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.5-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All diff --git a/releases/4.12.rst b/releases/4.12.rst index 6b5277852..d6367be63 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -4,7 +4,7 @@ Release Notes 4.12 ***************** -The 4.12 release notes were released on May 15th, 2025 +The 4.12 release notes were released on May 27th, 2025 .. contents:: :local: diff --git a/releases/index.rst b/releases/index.rst index b78bab2a5..3bc3045b4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.12 - May 15th, 2025<4.12>` +:ref:`Version 4.12 - May 27th, 2025<4.12>` :ref:`Version 4.11 - April 9th, 2025<4.11>` diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index 295884c48..dfd9465e7 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -36,12 +36,12 @@ SQDB Releases Timeline - Maintenance Mode - End of Support * - ``4.12`` - - May 15th 2025 + - May 27th 2025 - TBD - - May 15th 2026 + - May 27th 2026 * - ``4.11`` - April 9th 2025 - - May 15th 2025 + - May 27th 2025 - April 9th 2026 * - ``4.10`` - January 20th 2025 From 170ed80947dcf2f3b11204cc3da0d54f16e70a91 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 25 May 2025 09:44:22 +0300 Subject: [PATCH 1848/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index d6367be63..48d6f490a 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -104,5 +104,5 @@ Upgrading to Version 4.12 - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. From e18c6784b5d11cdf0556a094671936bf43c103b6 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Sun, 25 May 2025 09:59:56 +0300 Subject: [PATCH 1849/1892] upgrade link --- releases/4.10.rst | 2 +- releases/4.11.rst | 2 +- releases/4.9.rst | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/releases/4.10.rst b/releases/4.10.rst index 4dd6d879a..deeb125b0 100644 --- a/releases/4.10.rst +++ b/releases/4.10.rst @@ -116,5 +116,5 @@ Upgrading to Version 4.10 - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. diff --git a/releases/4.11.rst b/releases/4.11.rst index c6137f744..b9c6ff319 100644 --- a/releases/4.11.rst +++ b/releases/4.11.rst @@ -109,5 +109,5 @@ Upgrading to Version 4.11 - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. diff --git a/releases/4.9.rst b/releases/4.9.rst index 75f532bf1..450454939 100644 --- a/releases/4.9.rst +++ b/releases/4.9.rst @@ -101,5 +101,5 @@ Upgrading to Version 4.9 - .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/installing_sqream_with_binary.html#upgrading-sqream-version>`_ procedure. + .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. From bee5413509a5d30be5876453c816848996ae193c Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:35:54 +0300 Subject: [PATCH 1850/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 8a9ce77f8..7160a7252 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -39,7 +39,7 @@ Other distributions may also work, but are not officially supported by SQream. Getting the ODBC driver ======================= -The SQream ODBC driver is distributed by your SQream account manager. Before contacting your account manager, verify which platform the ODBC driver will be used on. Go to `SQream Support <https://sqream.atlassian.net/servicedesk/>`_ or contact your SQream account manager to get the driver. +Download the relevant driver (Windows or Linux) from the :ref:`_client_drivers` The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: From 87fda1def534ce05bf6a62d2112c659f529125e4 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:41:18 +0300 Subject: [PATCH 1851/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index 7160a7252..fd82edeb2 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -39,7 +39,7 @@ Other distributions may also work, but are not officially supported by SQream. Getting the ODBC driver ======================= -Download the relevant driver (Windows or Linux) from the :ref:`_client_drivers` +Download the relevant driver (Windows or Linux) from the :ref:`Client Drivers Download Page<_client_drivers>` The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: From b00242f2dc56c71f1c6644f2fc74567aadded158 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Jun 2025 14:44:15 +0300 Subject: [PATCH 1852/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index fd82edeb2..a0a7487dd 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -39,7 +39,7 @@ Other distributions may also work, but are not officially supported by SQream. Getting the ODBC driver ======================= -Download the relevant driver (Windows or Linux) from the :ref:`Client Drivers Download Page<_client_drivers>` +Download the relevant driver (Windows or Linux) from the :ref:`client drivers download page<client_drivers>`. The driver is provided as an executable installer for Windows, or a compressed tarball for Linux platforms. After downloading the driver, follow the relevant instructions to install and configure the driver for your platform: From f4ae69c338a7de7b8c31351b624306b9958b908f Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Thu, 5 Jun 2025 15:53:50 +0300 Subject: [PATCH 1853/1892] Update index.rst --- connecting_to_sqream/client_drivers/odbc/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/odbc/index.rst b/connecting_to_sqream/client_drivers/odbc/index.rst index a0a7487dd..d7ef130b1 100644 --- a/connecting_to_sqream/client_drivers/odbc/index.rst +++ b/connecting_to_sqream/client_drivers/odbc/index.rst @@ -31,7 +31,7 @@ SQream has an ODBC driver to connect to SQream DB. This tutorial shows how to in * Windows Server 2019 * - Linux - - * Red Hat Enterprise Linux (RHEL) 8.9 + - * Red Hat Enterprise Linux (RHEL) 8.x Other distributions may also work, but are not officially supported by SQream. From 4f65c0e4cf368d96111ca57029dcc1d39faa9c13 Mon Sep 17 00:00:00 2001 From: shaharf111 <112806728+shaharf111@users.noreply.github.com> Date: Mon, 9 Jun 2025 15:24:04 +0300 Subject: [PATCH 1854/1892] connectors note --- reference/sql/sql_statements/utility_commands/get.rst | 1 + reference/sql/sql_statements/utility_commands/put.rst | 1 + reference/sql/sql_statements/utility_commands/remove.rst | 1 + 3 files changed, 3 insertions(+) diff --git a/reference/sql/sql_statements/utility_commands/get.rst b/reference/sql/sql_statements/utility_commands/get.rst index 443a8df41..1ad88b002 100644 --- a/reference/sql/sql_statements/utility_commands/get.rst +++ b/reference/sql/sql_statements/utility_commands/get.rst @@ -38,6 +38,7 @@ Important Considerations * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * The feature is supported for the following drivers: PySQream, JDBC, ODBC Permissions diff --git a/reference/sql/sql_statements/utility_commands/put.rst b/reference/sql/sql_statements/utility_commands/put.rst index 49235245d..d42d0bba8 100644 --- a/reference/sql/sql_statements/utility_commands/put.rst +++ b/reference/sql/sql_statements/utility_commands/put.rst @@ -41,6 +41,7 @@ Important Considerations * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * The feature is supported for the following drivers: PySQream, JDBC, ODBC diff --git a/reference/sql/sql_statements/utility_commands/remove.rst b/reference/sql/sql_statements/utility_commands/remove.rst index e6530b820..75406c0b3 100644 --- a/reference/sql/sql_statements/utility_commands/remove.rst +++ b/reference/sql/sql_statements/utility_commands/remove.rst @@ -36,6 +36,7 @@ Important Considerations * File extensions are limited to supported FDWs. * The command execution is CPU based and does not use GPU Workers. * Up to 50 concurrent ``PUT`` / ``GET`` / ``REMOVE`` operation are supported per SQDB cluster. + * The feature is supported for the following drivers: PySQream, JDBC, ODBC Permissions From f425469d0961970b338630024773ca7f8ad03dc2 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Tue, 10 Jun 2025 14:38:37 +0300 Subject: [PATCH 1855/1892] odbc500 links --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 14609df27..4675583fa 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -44,7 +44,7 @@ Client Driver Downloads - Recommended installation via ``npm`` - All * - **ODBC** - - `Windows ODBC Installer <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream_odbc_jdbc_installer_25072022_x86_64bit_windows.zip>`_ , `Linux ODBC <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream_odbc_v4.4_x86_64_linux.tar.gz>`_ + - `Windows ODBC Installer <https://sq-ftp-public.s3.us-east-1.amazonaws.com/SQream_ODBC_JDBC_Drivers_v5.0.0.exe>`_ , `Linux ODBC <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream_odbc_5.0.0_x86_64_linux.tar.gz>`_ - :ref:`Windows<install_odbc_windows>`, :ref:`Linux<install_odbc_linux>` - - Windows, Linux From bf84b1ccc89391e3a4c9b1f674d08ec19a3eec53 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 11 Jun 2025 10:34:59 +0300 Subject: [PATCH 1856/1892] JDBC601 --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 4675583fa..e7fb2f290 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.0.0.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.0.1.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From c5a19ec24f4f71e204da6f4741d7668db0354508 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:12:44 +0300 Subject: [PATCH 1857/1892] TPD-771 --- .../sql_statements/dml_commands/delete.rst | 5 ++++ .../utility_commands/rechunk.rst | 27 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/reference/sql/sql_statements/dml_commands/delete.rst b/reference/sql/sql_statements/dml_commands/delete.rst index 94d65ed57..b6e184657 100644 --- a/reference/sql/sql_statements/dml_commands/delete.rst +++ b/reference/sql/sql_statements/dml_commands/delete.rst @@ -97,6 +97,11 @@ The following table describes the parameters used for executing the ``DELETE`` s - An expression that returns Boolean values using columns, such as ``<column> = <value>``. Rows that match the expression will be deleted. +Limitations +=========== + +**Encrypted Columns:** ``CLEANUP_CHUNKS`` does not support tables with encrypted columns. Use :ref:`RECHUNK <rechunk>` instead. + Examples diff --git a/reference/sql/sql_statements/utility_commands/rechunk.rst b/reference/sql/sql_statements/utility_commands/rechunk.rst index ef69ca3ed..083c9f645 100644 --- a/reference/sql/sql_statements/utility_commands/rechunk.rst +++ b/reference/sql/sql_statements/utility_commands/rechunk.rst @@ -36,6 +36,33 @@ Example SELECT rechunk('public', 't'); + +Rechunk Encrypted Columns +========================= + +For tables with encrypted columns, RECHUNK requires the encryption keys for each encrypted column. + +Syntax +========== + +.. code-block:: postgres + + RECHUNK('<schema>', '<table>', '<col1>', '<key1>', '<col2>', '<key2>', ...); + +Example +========== + +.. code-block:: postgres + + CREATE TABLE sc.tbl ( + x TEXT ENCRYPT, + y TEXT, + z TEXT ENCRYPT + ); + + RECHUNK('sc', 'tbl', 'x', '[key-for-x]', 'z', '[key-for-z]'); + + Permissions ============= From 85ae254cc344de78bca16d4829ee0ab85dcc796a Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 23 Jun 2025 13:29:27 +0300 Subject: [PATCH 1858/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 48d6f490a..3337ab139 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -20,7 +20,7 @@ Compatibility Matrix +-------------------------+------------------------------------------------------------------------+ | supported Nvidia driver | CUDA version 12.3.2 | +-------------------------+------------------------------------------------------------------------+ -| Storage version | 59 | +| Storage version | 62 | +-------------------------+------------------------------------------------------------------------+ From 472b9ceaca8300c95dcd9baff8899338976fb4b0 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Thu, 26 Jun 2025 09:49:37 +0300 Subject: [PATCH 1859/1892] update columns parameter --- data_ingestion/sqloader.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index a563cc417..c3c4d0139 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -506,10 +506,10 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - - The name of the file that contains all column names. Columns must be separated using ``\n``. Expected file type is ``.txt`` - * - ``columns`` + * - ``selectedColumns`` - Optional - All columns - - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true + - The name or names of columns to be loaded into SQreamDB ("col1,col2, ..."). For column names containing uppercase characters, maintain the uppercase format, avoid using double quotes or apostrophes, and ensure that the ``caseSensitive`` parameter is set to true. **Note:** In versions prior to 8.5, the ``selectedColumns`` parameter was named ``columns``. * - ``count`` - Optional - ``true`` From 2250c3c949e2fe1b045cd78b2a1084edc5c34ba6 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 30 Jun 2025 12:00:54 +0300 Subject: [PATCH 1860/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index e7fb2f290..2327bf03a 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.0.1.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.1.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From f5d219a4f767290626d10b0652f6968b1af9ca16 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Tue, 1 Jul 2025 11:14:29 +0300 Subject: [PATCH 1861/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 2327bf03a..ae5911d64 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.5-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.6-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From 014aa66569d7e7d71470812022320f972cca5f11 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Tue, 1 Jul 2025 15:27:09 +0300 Subject: [PATCH 1862/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index ae5911d64..21eea287b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.6-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.6-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From 7833967b9014102640cf8a51d1c15a7eb780a59e Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:02:37 +0300 Subject: [PATCH 1863/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 3337ab139..f29d975a1 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -4,7 +4,7 @@ Release Notes 4.12 ***************** -The 4.12 release notes were released on May 27th, 2025 +The 4.12 release notes were released on July 3rd, 2025 .. contents:: :local: From 573aaea99457a8f5809903c2f34cb362b394cc97 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:43:29 +0300 Subject: [PATCH 1864/1892] Update 4.12.rst --- releases/4.12.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index f29d975a1..e60161c62 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -26,13 +26,13 @@ Compatibility Matrix New Features and Enhancements ----------------------------- -► :ref:`Metadata partitioning<accelerating_filtered_statements>` significantly reduces statement execution time by intelligently leveraging previously created metadata partitions for efficient data skipping. +► :ref:`Metadata partitioning<accelerating_filtered_statements>` significantly reduces statement execution time when metadata contains millions of keys by intelligently leveraging previously created metadata partitions for efficient data skipping. -► New SQL syntax for :ref:`PUT<put>`, :ref:`GET<get>`, and :ref:`REMOVE<remove>` statements empowers you to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. +► New SQL syntax for :ref:`PUT<put>`, :ref:`GET<get>`, and :ref:`REMOVE<remove>` statements empowers users to directly write and read files to and from the SQDB cluster, leveraging its robust access control system. -► We've upgraded our platform to Java 17, bringing performance enhancements and the latest security features. +► We've upgraded our platform to Java 17, delivering enhanced performance and the latest security features. -► The ``PIVOT`` functionality has been updated to now support multi-column pivoting. +► The ``PIVOT`` functionality has been updated to support multi-column pivoting. Known Issues From 76ddbbbd01e14938b6df3fc191e08ed3cb9d81a6 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:54:12 +0300 Subject: [PATCH 1865/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index e60161c62..fff125776 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -32,7 +32,7 @@ New Features and Enhancements ► We've upgraded our platform to Java 17, delivering enhanced performance and the latest security features. -► The ``PIVOT`` functionality has been updated to support multi-column pivoting. +► The :ref:`PIVOT<pivot>` functionality has been updated to support multi-column pivoting. Known Issues From 17a9a0bb786982e2b6dd813c253d0d8576fad82a Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 09:58:14 +0300 Subject: [PATCH 1866/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index fff125776..b4fdb5762 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -32,7 +32,7 @@ New Features and Enhancements ► We've upgraded our platform to Java 17, delivering enhanced performance and the latest security features. -► The :ref:`PIVOT<pivot>` functionality has been updated to support multi-column pivoting. +► The :ref:`PIVOT<pivot_unpivot>` functionality has been updated to support multi-column pivoting. Known Issues From 63856e47b06b5c000411eee7d34c08a4bd2eda70 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:20:39 +0300 Subject: [PATCH 1867/1892] Update 4.12.rst --- releases/4.12.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/releases/4.12.rst b/releases/4.12.rst index b4fdb5762..a9ad2d80a 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -54,6 +54,7 @@ Version 4.12 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ +.. _Deprecation: Deprecation ------------------- @@ -105,4 +106,7 @@ Upgrading to Version 4.12 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. + + + .. note:: Column DDL permission is now deprecated as its functionality is fully included within the table DDL permission. For more info please refer to `Deprecation_` From cb617e6f0e7426a82b377f11bf6e638d8be6c4ed Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:25:17 +0300 Subject: [PATCH 1868/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index a9ad2d80a..9e40a56c6 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -108,5 +108,5 @@ Upgrading to Version 4.12 .. note:: Upgrading from a major version to another major version requires you to follow the **Upgrade Storage** step. This is described in Step 7 of the `Upgrading SQreamDB Version <../installation_guides/upgrade_guide/version_upgrade.html>`_ procedure. - .. note:: Column DDL permission is now deprecated as its functionality is fully included within the table DDL permission. For more info please refer to `Deprecation_` + .. note:: Column DDL permission is now deprecated as its functionality is fully included within the table DDL permission. For more info please refer to `Deprecation`_ From 1a2a118a1040af75fef9110f59989b9367004a09 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Wed, 2 Jul 2025 14:29:43 +0300 Subject: [PATCH 1869/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 9e40a56c6..c56f90647 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -74,7 +74,7 @@ Starting October 2024, support for the Haskell CLI is discontinued, and it is re ► **DateTime2 Alias** -As of April 2025, the alias ``DateTime2`` for the ``DateTime`` Data Type has been deprecated to simplify our data model and make way for the introduction of a new data type named ``DateTime2``. +Effective April 2025, we've deprecated the alias ''DateTime2'' for the ''DateTime'' data type. This change streamlines our data model and prepares for the introduction of a new, distinct ''DateTime2'' data type in the future. Upgrading to Version 4.12 ------------------------- From 8ef6a9a0256c2eaea34342cb9445016dc1cf32a9 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Thu, 3 Jul 2025 10:59:07 +0300 Subject: [PATCH 1870/1892] Update 4.12.rst --- releases/4.12.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/releases/4.12.rst b/releases/4.12.rst index c56f90647..813dbab57 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -46,12 +46,17 @@ Version 4.12 resolved Issues +--------------+---------------------------------------------------------------------------------------------------------------------+ | **SQ No.** | **Description** | +==============+=====================================================================================================================+ +| SQ-19639 | Consistency check does not recognize arrays. | ++--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19869 | Queries with numerous STDDEV aggregations are experiencing long compilation time. | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-19879 | Default permissions for saved queries are not automatically created upon new database creation. | +--------------+---------------------------------------------------------------------------------------------------------------------+ | SQ-20146 | The ``PIVOT`` function does not allow renaming of pivoted columns using aliases. | +--------------+---------------------------------------------------------------------------------------------------------------------+ +| SQ-20400 | Compiler throws an error when performing a join on encrypted columns. | ++--------------+---------------------------------------------------------------------------------------------------------------------+ + .. _Deprecation: From acc0ad147971ea62194c01c9e9c5cea7e99572c2 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Thu, 3 Jul 2025 11:41:36 +0300 Subject: [PATCH 1871/1892] release dates --- releases/index.rst | 2 +- releases/releasePolicy.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/releases/index.rst b/releases/index.rst index 3bc3045b4..0f0fbd4f4 100644 --- a/releases/index.rst +++ b/releases/index.rst @@ -4,7 +4,7 @@ Release Notes ************* -:ref:`Version 4.12 - May 27th, 2025<4.12>` +:ref:`Version 4.12 - July 3rd, 2025<4.12>` :ref:`Version 4.11 - April 9th, 2025<4.11>` diff --git a/releases/releasePolicy.rst b/releases/releasePolicy.rst index dfd9465e7..1b3d91f0c 100644 --- a/releases/releasePolicy.rst +++ b/releases/releasePolicy.rst @@ -36,9 +36,9 @@ SQDB Releases Timeline - Maintenance Mode - End of Support * - ``4.12`` - - May 27th 2025 - - TBD - - May 27th 2026 + - July 3rd 2025 + - October 3rd, 2025 + - July 3rd 2026 * - ``4.11`` - April 9th 2025 - May 27th 2025 From d40b8705c1f00f2130239b401edc03b372a3e841 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Thu, 3 Jul 2025 14:50:17 +0300 Subject: [PATCH 1872/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index c3c4d0139..ec1585df3 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -61,7 +61,7 @@ Installation and Connectivity Getting All Configuration and JAR Files --------------------------------------- -#. Download the `SQLoader binary <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader-release-v1.5.tar.gz>`_: +#. Download the `SQLoader binary <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqloader_release_sqloader-release-v8.5.tar.gz>`_: #. Extract the ``.tar`` file using the following command: From 2327112d720dbb5eccfb3cf7fcf348bcad9971c8 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Sun, 6 Jul 2025 13:10:53 +0300 Subject: [PATCH 1873/1892] 2.7 --- .DS_Store | Bin 10244 -> 14340 bytes connecting_to_sqream/client_drivers/index.rst | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.DS_Store b/.DS_Store index 9bbcbcac4c0ec3d73d537815167a51d2e28dbfbc..4c5882b5bf359c7d8d9bd455398ce11eeec3a692 100644 GIT binary patch literal 14340 zcmeHNdvp}l9lpOwLS}{~nS=nlOBNO)uVjThfe@6<g9ro!lK=r9VUrz_DVyD}vk53g zX>I#Q)z&_&_91;*J;#d2wraJlmD3)NkJcVFePEB;s>lA(dXBX{YOAOAyLV=n*-1ha zIhKPvduHz5$8TotZ+`dA_kD92W7IMdtzoR1F(zZ@sperUUu7(a)Vc9`zK`4TP(s+3 zV#j}tu@rs=i?adNJFa!EAm@Rc2hJuBNVpk3e)F*xW6bJV<JUwk!jd@ZEE+RMhx=lQ zKE|Xk^bN-hGgV#vEJ=C!1=9*;MV;=MQQm%0`v%XZUafT0&<|`KP8o@~xkFEyNPD$n zb1-pWV}ByPEvfVRo&AZ}$WYwu)k^v!vHp=*B&9dUVqL~nI?9U8{$wH++m<j5ewtl9 zDg9uI*Nv;{*=;70saA2aUQHV@^-dk<GDh__oYCwta7k{ck#eG_SSu-=SvG6-oZzC$ z74@suHuv-=hKBTb%G@4{^y#skqt@+S8ij3ZQpYjcZNmC8Ua%z*HTD`P*=NL~-SNnf zeg!Yy95GW{hxND~9rOD9bISvs`8!7q)98!o+YcDg)Zng&*{{c=Mtop94E2L@3567` z&}zNVbDpe46|KO^F7YgrwGKs_W@SU=%Vq6eS(8N8Q&V22Xc1Y<v$CP`>56RqZS*uL znyF~{V{`pJ?**Q99*rp_WGLzLw8^q2%N6P9s|fQs8=L5dQW56!Ki^~)V707`ZDxD$ z=nt_Q*e&c%_G5M*yPrMIo?$20U)Zbcb@ndhlR{ovK+9+aHPSi?Q!BMmJ8h+H)Ja{m zovxr>iclX#X^7%9O#8{CkJDkghK|rD={mZeZlJHw&Gc3J8hwLqquc2Yx|4oD_tJfI zKRrMX(l6=P^b|d9-I~Nhm2VwZl0MR(@WRnqzvI=DVhOx}Otv3=&=JH#qg}~(ED;}o z4L?f}i=vc=cdz}r($Si~x)Lnjcfhnmo&6*o>c3BidZ9dBzPt;u+?9%?M$DE-@=~7b zP9$P|>Hm?w9f<H=t*kW>PeqKlo)iW~R7aD`b|MH82U-#%@u(?myQ~UXk(FM}d+1PI zb$uvU*U)%46g<>eTOA74udF_NSdnK{tZ3@&-4`2*Cq8TSozfnek@kh1UN==AF`UuF zHkYTn%yZeC2XY?Bd4SIkLF_yY+vyQ26;lTe976DV4k5&b|KI_lENG`;J3V5h!W1^b z6scuOHpL*z9OXgY9BJ52k65W?&d4%nWM7$VhC<@%unUUjjKWr$JLWu)^T2oyl%Qw| z?C%0k%h@1+Qxs4s!G;CQ(gCwZ0ko3Halo~ojQ~pVe<n)yiJCrfOo);Q>Qgw24&cT? zSHA#b0(@<ZCHgI%A?AU*ad$`G6`Q#AnF6j^%p}HQC+%>Z0ddtRzp4YmJ@BDJI3FO~ zs@0)j&FXp%;cDvYR)&JB8fsk_j$<@zlVZ5*QTZOb>v}*k8-ioF+n2LG?xJj`62G$3 zsWRJQx8Do*#+dGE|8H0OQt{yV<K`GzJU0A`on4Qhp$1;BZ?GT1Y5}9`Pva51r_Q<_ zfWkW2de#gYwFT*NJdS9#OC?T3vL68-EpR;?Y4QlpZjW;@DsqeiS&S}6`~P>u*VZ(G zwbV4!3D(k3hlp=%I1P7?>lm0yt1UddogT`6OtUcv58m$WJJd5EI%FgUhoF#A4<=9+ z%J2l88!5*;v;6ZbmY!b=VWEA~#bYzL-k{D@cZ1)>Q(QVoI-~$04Wxwvi-l{qD`PW? zi?rEuyxyLXK4brgk-Ac=kmWJ0sCb6z4a`%Z24rawqQ>hDER<!ZXki;HUIK%NP%x|# zwJM}QClCsTWvW)!$ch%V^bfnJVI_(>(qf2RxTZ;lpb*L^CRVX`T^Pc`akmh{@7L>X zTaUU&cbkKeq`vh4Xs~V5wo#UaB7}0To~(}=sYFtAy(8fD?&7LSb2O?)dC!ZBW_Y)G zJ7w)@*l0$4)By2@CS>t%xguO?Jq6*yjE<oIP5LnM!fXS(4C85-UCFLzx3Z(`E=U>2 z*%Rz3NEy$w7a(W6$o|Iu#ol0VvbTsxqC6^~QkqNU6o9x<OLbIFE2#<M#(Kyb8)ysd zpq<o1yJ-&@^fB58d1HjG7P7{*5H)VHMU6Y?9{M5u2y({5^cX!(PtbGp3cW`Epx5bb zdWZf??@Fc8OsQO2AlaSBNE|)R&;rV?LVlv5k=EpfCmI@o_KP;09Yf=UM+^oozRlw! zWMxx06G&%9dc&CU`PK4(C9zF5&a^@v!}1t!JzrfA&<YUyR`xt~aX_1fxVN&)0#yM` z;^LcVygX2?YIzt;ipbUls#J|+E3-;%RJD9Azm56kcxS8Xh3hcLZr7M-+8k&NKzY-S zLw$R{v3d`CkUh*EWn+ldR}iJIL3Wd=2(sHeT1-n3ogq3OvAG%oTobKDd|rh3+(aGJ zEn;*RVzi%h+Dn6o)Fh=4r=y6|Pe6YA6n&aLN1vw~>5KGbx|P03-=go(cj<d{7ozs3 zR{Uk+aZ`3Y($6M}N7q|Wb78?Dj6;t1OpMDEJLrZb3|KGg9aoH2NkEMefEfO!Gl3X6 z=Cr>sP4I@i+VO^*!rFDO+1<<KavsQeAm@RPf(K@!lZC7v3jpddFDEg}PDB@%J7(5G z5Iu{53-0ckhdE<+wpP)ae?c4q2DAA3ICet;mrVg!kO8|P7IV$h9@HeE7Yw4FpOt^~ z8R74l?7QInD(hV`sa<TKrVAedhaHc4(zZj1wl-UvkYDb2tf|cN2zVJgMf>RcYCk+U z?p_MfLwu5Ad+}_5VY7QloR~X(U1qnQ@^jd^!WQ3ihh1Tm`~H_<)p`DjsDp23&#tqB zI)GIN7A~%;ZdkLfZR3_p1glm{)v`2oc7J1cux+Iz?<z&`LXN~WpWjzLnUxHhouS;; zHRk&kD1iUjbeq!{-+bR97v1K?>QY}N|2l8cZBcT*x`NXJi*5_kTD6{k?zic-C<1-p zpZqg)TNJKUFBHoJGAv2lldsv=%9(_lZVQuk-v+R4*-5wU^34;{ZQ+vnzHPF6l5me{ zATXU>KHmgX8wC6`C=93D53ygdCqZGJWzT_fzr_9yy8R!lA1I(g(3ukQgKP&tX{tc9 z8$f4TKwvi0#aKzuO_yU8!5*w4*h>klAV^{b!IdB{*Mhu!2K41-x`n<j)(#w_y9M1o zE{OJT=t(+3FVai&GQ9zs%_NehOJ&j$X_-_hRY@VKL0TiVT9bZ;<Xq}_3E;2PhQldm z3df?D{S%F%j~oG?tJ(zIJu1`VPAlY#Uu*&%R6)Qo8f*f-2-#^E2{r+*41j=R0NMn6 zMF0dG!^<Y%mB?lY_-Yjd90Sd&TYCYrjE{XQ-`s*T2?BoR7<ie@z^gJ0d`*UdZ_F_8 z9!fLtfpHA{TAP92NM8c~zKM=z`1fse45|@l*w`|`>1N<RN98Gl)Ah>J97|qOP{W3S zp0d7~WMd1VP&=_j5ikf>r)|8IZF{cZiBopc<<KcUnq|9_aiHiF{HL%!R~$M;H&2TD zdFAN|G<#K{zk7T44o}Y+5ctO}9XvCu3Xc`dDPO>s6E<Gh(%!LkjIS~DcxKH`&v<Sr z(uq&_3Ox&-l$L145HS523?gKIUK*I^_hexZOo_@EuUR<H?{|v+m??Sj;w65Mz#w9> z<Rw)hk4In-F-7u{>Kc#V!XRS$<wXrEJ^nNX5tA@4T+`(7XCR0*bMxYLxUvg_*cWd_ z%}F?cLhcT~f8!=7pieuYiCup2gwVvU?BtabNdA0Y<lAX2Vtj=Cmi+;$|6j3)@t*)9 zZ?bm)M2biQ5aFu-QmO<H2?2;S1BkQ&h+KljjNM{6qot(|0EmpzK>(4f07S0CB1W#G z-a_Aoc6u9qA3)?G`i0Q^pP@1O9X(Gk(4PTDUIi3+lire4X#Qo=ENLmgNUhW)g(W^Y zV9U()yR3ZrD7ohTbomEP3#>C#^Ywr0Ctv^nfv=N0LCym?51hRop!~M3wietUO>&QX ztz8iN9_)PM?T%QfFu}oIjwk-`rFg5cXExM_c?RhbD-~wQTV@~HBEa-p+09RK{9k-< P&+&gAo%VK)^Z)+=cGRG& delta 1323 zcmc(eT}TvB6vxkhcFP%@ayCDAS7}qyEjL|tQCCbh%XGEK(EO^G)HS!(k8&+BWR;}o z<Hc_E6d6U(H!W+uWl~fx1qBvlAwg#K5=261WZiYFhlqqI8n|=rIrlQd`ThT=x3#x4 zhKP{gUY|x};#-lgU{vJ3ol$)$dS<n0^*kpdU*L5jFS)7C>1nB}^#pXrDXqWzf*|pu z;3J0eQnWUZB#&ueWH}}m`(PSpAD21Un&d`i4r!0Dr=?p=8TO1Wi)pVt-D)w}GHuKs zlEE)5mOX8|SJ!%4YKb&SEKeJy7|J(QRLa#=?z)!dGIyto^(3XRQ`!>dw?s+_4y*dx zK=BGMd=876B{<Bp8#NG>H*alnNeXy-ag<2e<e+kDpcd+(Bh*g=bdv_@Aw8v0dQ0zV zlBVc0O+y12k%&eN^oU0)(vXe}<e~^p6r&7PsKI7zfeYK=fv*Y8*n=+k(2X7(!ciQ< zahyOu&f^j;;|gxzF7Dwz9$^H}@dB?gjyHIR34Fmcz6v_QAQ**MAyu#nb|GIV5lV%P zY7@dNVXFDw)NH+s$1vJPF6K-&1Oc|H0ELqrV02hvk+WFN`X#@(AN-_e3&RxMqVR~w zsA$vD<*BypmHAAZH{{EbL<Pe!dV^8Uk#i-bO;WVOMuR>kPj<)(NjkWtnd4YXY=I~$ zqL?t33cuChF^$kmuE7LNVm?BBP_P(gSdj?_)}oMOFTr|Lpc2&_eh_^F8sWwcc+t-3 zcc2sd(2M;zfP-8C#x)2ka2jWD7Uysk*Wkwhu453lFofH<g9mtmQM~$z^E#d{P-`=9 zjImY8@hn9-oFMTDXr_8{Q3s{aE@~sMIuAkP21f*Ofs2Y+6R0p`Yjhg*Bc@Ou3xbms z(21WkEX?L)8)Q)t)S;WPEZ5k|8f|?L*^<O?-`p_&sil1${8vk}!sOV$Z0PJiHS{;x C`w$fX diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 21eea287b..ba7dc75fc 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.6-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.7-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From 170602796349ed16a144358766073096d715613d Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:14:30 +0300 Subject: [PATCH 1874/1892] Update 4.12.rst --- releases/4.12.rst | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index 813dbab57..dc8b45755 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -13,15 +13,22 @@ The 4.12 release notes were released on July 3rd, 2025 Compatibility Matrix -------------------- -+-------------------------+------------------------------------------------------------------------+ -| System Requirement | Details | -+=========================+========================================================================+ -| Supported OS | RHEL 8.9 | -+-------------------------+------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version 12.3.2 | -+-------------------------+------------------------------------------------------------------------+ -| Storage version | 62 | -+-------------------------+------------------------------------------------------------------------+ ++-------------------------+----------------------------------------------------------------------------------------+ +| System Requirement | Details | ++=========================+========================================================================================+ +| Supported OS | RHEL 8.9 | ++-------------------------+----------------------------------------------------------------------------------------+ +| supported Nvidia driver | CUDA version 12.3.2 | ++-------------------------+----------------------------------------------------------------------------------------+ +| Storage version | 62 | ++-------------------------+----------------------------------------------------------------------------------------+ +| Driver compatibility | The new features in this version are coupled with changes in the following components: | +| | * ODBC 5.0.0 | +| | * JDBC 6.1.0 | +| | * Pysqream 6.2.0 | +| | * Java CLI 2.7 | +| | * SQLoader As A Service 8.5.0 | ++-------------------------+----------------------------------------------------------------------------------------+ New Features and Enhancements From 5d0b6b5bae8668b8f0bbe0e30386baa9e42e5138 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:20:02 +0300 Subject: [PATCH 1875/1892] Update 4.12.rst --- releases/4.12.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index dc8b45755..db09c7c82 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -23,7 +23,8 @@ Compatibility Matrix | Storage version | 62 | +-------------------------+----------------------------------------------------------------------------------------+ | Driver compatibility | The new features in this version are coupled with changes in the following components: | -| | * ODBC 5.0.0 | +| | | +| | * ODBC 5.0.0 | | | * JDBC 6.1.0 | | | * Pysqream 6.2.0 | | | * Java CLI 2.7 | From 5d9f10c5730395405b45f848ed91060e483fe466 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 7 Jul 2025 13:43:40 +0300 Subject: [PATCH 1876/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index ec1585df3..2a4fbd768 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -618,6 +618,16 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``true`` - Allows control over the validation of table existence during the load. + * - ``warnOnIncLoadFilterChanges`` + - Optional + - ``true`` + - Warns if the filter was changed since the last load and fails the load. If set to false - it accepts the new filter an updates it, future filters will be compared to this one from now on, until changed again. + * - ``autoCreateNewNullableColumn`` + - Optional + - ``false`` + - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table : + when the parameter is set to false - there will be a warning and the load would fail. + if the arameter is set to true, then the new columns will be added to the target table as well. .. _load_type_name: From da395cb8de992391fb13bbacc50fa791efde0efd Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 7 Jul 2025 13:44:07 +0300 Subject: [PATCH 1877/1892] Update 4.12.rst --- releases/4.12.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index db09c7c82..a6b45308e 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -16,9 +16,9 @@ Compatibility Matrix +-------------------------+----------------------------------------------------------------------------------------+ | System Requirement | Details | +=========================+========================================================================================+ -| Supported OS | RHEL 8.9 | +| Supported OS | RHEL 8.9 / 8.10 | +-------------------------+----------------------------------------------------------------------------------------+ -| supported Nvidia driver | CUDA version 12.3.2 | +| supported Nvidia driver | CUDA version 12.3.2 / 12.6.1 | +-------------------------+----------------------------------------------------------------------------------------+ | Storage version | 62 | +-------------------------+----------------------------------------------------------------------------------------+ From 8fc43c3fddc8ebb53c189af388c02fd79a572943 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 7 Jul 2025 13:48:57 +0300 Subject: [PATCH 1878/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 2a4fbd768..6385502ff 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -625,9 +625,9 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``autoCreateNewNullableColumn`` - Optional - ``false`` - - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table : - when the parameter is set to false - there will be a warning and the load would fail. - if the arameter is set to true, then the new columns will be added to the target table as well. + - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table. + When the parameter is set to false - there will be a warning and the load would fail. + When the parameter is set to true, then the new columns will be added to the target table as well. .. _load_type_name: From 43111a22c8c74070c9aa06bf66435882a1ee6f0c Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 7 Jul 2025 13:55:37 +0300 Subject: [PATCH 1879/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 6385502ff..1f5d8378f 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -626,8 +626,8 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. - Optional - ``false`` - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table. - When the parameter is set to false - there will be a warning and the load would fail. - When the parameter is set to true, then the new columns will be added to the target table as well. + When the parameter is set to false - there will be a warning and the load would fail. + When the parameter is set to true, then the new columns will be added to the target table as well. .. _load_type_name: From f3859a525679b481b44ba83fe90c60ccab917938 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Mon, 7 Jul 2025 13:58:54 +0300 Subject: [PATCH 1880/1892] Update sqloader.rst --- data_ingestion/sqloader.rst | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/data_ingestion/sqloader.rst b/data_ingestion/sqloader.rst index 1f5d8378f..1b81484a7 100644 --- a/data_ingestion/sqloader.rst +++ b/data_ingestion/sqloader.rst @@ -625,9 +625,7 @@ Mandatory flags must be configured using HTTP flags or the ``properties`` file. * - ``autoCreateNewNullableColumn`` - Optional - ``false`` - - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table. - When the parameter is set to false - there will be a warning and the load would fail. - When the parameter is set to true, then the new columns will be added to the target table as well. + - Allows adding new columns to an INC load automatically, if the source table has new columns. If during an INC load, new columns exist in the source table. When the parameter is set to false - there will be a warning and the load would fail. When the parameter is set to true, then the new columns will be added to the target table as well. .. _load_type_name: From 8dda3c49e9167341fe07dff39968b337dec1f17a Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 7 Jul 2025 14:35:06 +0300 Subject: [PATCH 1881/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index ba7dc75fc..f7a081ee7 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.1.0.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.2.0.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From d42675d2e12a7fbcfd7b6ff4545099962d46688c Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 7 Jul 2025 15:00:12 +0300 Subject: [PATCH 1882/1892] Update 4.12.rst --- releases/4.12.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releases/4.12.rst b/releases/4.12.rst index a6b45308e..e5e9bc02c 100644 --- a/releases/4.12.rst +++ b/releases/4.12.rst @@ -25,7 +25,7 @@ Compatibility Matrix | Driver compatibility | The new features in this version are coupled with changes in the following components: | | | | | | * ODBC 5.0.0 | -| | * JDBC 6.1.0 | +| | * JDBC 6.2.0 | | | * Pysqream 6.2.0 | | | * Java CLI 2.7 | | | * SQLoader As A Service 8.5.0 | From 8e6e34d6f19b148def80a7e2d95d444a962af196 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 14 Jul 2025 13:15:37 +0300 Subject: [PATCH 1883/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index f7a081ee7..1ca6119ee 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -34,7 +34,7 @@ Client Driver Downloads - - All * - **JDBC** - - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.2.0.jar>`_ + - `sqream-jdbc <https://sq-ftp-public.s3.us-east-1.amazonaws.com/sqream-jdbc-6.2.1.jar>`_ - :ref:`java_jdbc` - Recommended installation via ``mvn`` - All From 5571fec624b6c3e397f283fde68c48ecd7eee371 Mon Sep 17 00:00:00 2001 From: inbarb <80248742+inbarb@users.noreply.github.com> Date: Mon, 14 Jul 2025 15:08:43 +0300 Subject: [PATCH 1884/1892] Update index.rst --- connecting_to_sqream/client_drivers/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connecting_to_sqream/client_drivers/index.rst b/connecting_to_sqream/client_drivers/index.rst index 1ca6119ee..cc9db574b 100644 --- a/connecting_to_sqream/client_drivers/index.rst +++ b/connecting_to_sqream/client_drivers/index.rst @@ -19,7 +19,7 @@ Client Driver Downloads - Notes - Operating System * - **SQream DB Java CLI** - - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console-2.7-v1.zip>`_ + - `SQream DB Java Command Line Interface <https://sq-ftp-public.s3.us-east-1.amazonaws.com/jdbc-console_release_jdbc-console-2.8-v1.zip>`_ - :ref:`sqream_sql_cli_reference` - Replaces the Deprecated Haskell Command Line Tool - All From a1bcb325d38e390ab42b86596ba7d2b41fba8308 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Wed, 23 Jul 2025 11:39:04 +0300 Subject: [PATCH 1885/1892] Updated and added all flags --- feature_guides/query_healer.rst | 21 ++++++++--- feature_guides/query_healer.rst_old | 58 +++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 feature_guides/query_healer.rst_old diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index ba07d3f11..9d0a92c09 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -5,12 +5,14 @@ Query Healer ************ -The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding a defined time period. +The **Query Healer** periodically examines the progress of running statements and connections, creating a log entry for all statements exceeding a defined time period and connections with no data transfer over a specified time. +It can also take action based on its findings, for two issues - a stuck query or a hung connection. +The query healer runs on a separate thread on each worker, this is able to take action if the worker it is coupled with has a problem. Configuration ------------- -The following worker flags are required to configure the Query Healer: +The following worker flags are required to configure the Query Healer. These are all worker level flags: .. list-table:: :widths: auto @@ -18,12 +20,19 @@ The following worker flags are required to configure the Query Healer: * - Flag - Description - * - ``is_healer_on`` + * - ``isHealerOn`` - The :ref:`is_healer_on` enables and disables the Query Healer. - * - ``maxStatementInactivitySeconds`` - - The :ref:`max_statement_inactivity_seconds` worker level flag defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The default setting is five hours. * - ``healerDetectionFrequencySeconds`` - - The :ref:`healer_detection_frequency_seconds` worker level flag triggers the healer to examine the progress of running statements. The default setting is one hour. + - The :ref:`healer_detection_frequency_seconds` triggers the healer to examine the progress of running statements. The default setting is one hour. + * - ``maxStatementInactivitySeconds`` + - The :ref:`max_statement_inactivity_seconds` defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. If a statement did not make any progress during this time, it is considerd stuck. The default setting is five hours. + * - ``healerRunActionAutomatically`` + - The healerRunActionAutomatically triggers the healer to take action once it detects a problem. In order for the healer to take an automatic correction action, this flag needs to be true, AND the flag that relates to the detected problem. The default setting is true. + * - ``healerActionGracefulShutdown`` + - The healerActionGracefulShutdown triggers the healer to restart a stuck worker automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is false. + * - ``healerActionCleanupConnection`` + - The healerActionCleanupConnection triggers the healer to close a hung connection automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is true. + Query Log --------- diff --git a/feature_guides/query_healer.rst_old b/feature_guides/query_healer.rst_old new file mode 100644 index 000000000..ba07d3f11 --- /dev/null +++ b/feature_guides/query_healer.rst_old @@ -0,0 +1,58 @@ +.. _query_healer: + +************ +Query Healer +************ + + +The **Query Healer** periodically examines the progress of running statements, creating a log entry for all statements exceeding a defined time period. + +Configuration +------------- + +The following worker flags are required to configure the Query Healer: + +.. list-table:: + :widths: auto + :header-rows: 1 + + * - Flag + - Description + * - ``is_healer_on`` + - The :ref:`is_healer_on` enables and disables the Query Healer. + * - ``maxStatementInactivitySeconds`` + - The :ref:`max_statement_inactivity_seconds` worker level flag defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. The default setting is five hours. + * - ``healerDetectionFrequencySeconds`` + - The :ref:`healer_detection_frequency_seconds` worker level flag triggers the healer to examine the progress of running statements. The default setting is one hour. + +Query Log +--------- + +The following is an example of a log record for a query stuck in the query detection phase for more than five hours: + +.. code-block:: console + + |INFO|0x00007f9a497fe700:Healer|192.168.4.65|5001|-1|master|sqream|-1|sqream|0|"[ERROR]|cpp/SqrmRT/healer.cpp:140 |"Stuck query found. Statement ID: 72, Last chunk producer updated: 1. + +Once you identify the stuck worker, you can execute the ``shutdown_server`` utility function from this specific worker, as described in the next section. + +Activating a Graceful Shutdown +------------------------------ + +You can activate a graceful shutdown if your log entry says ``Stuck query found``, as shown in the example above. You can do this by setting the **shutdown_server** utility function to ``select shutdown_server();``. + +**To activte a graceful shutdown:** + +1. Locate the IP and the Port of the stuck worker from the logs. + + .. note:: The log in the previous section identifies the IP **(192.168.4.65)** and port **(5001)** referring to the stuck query. + +2. From the machine of the stuck query (IP: **192.168.4.65**, port: **5001**), connect to SQream SQL client: + + .. code-block:: console + + ./sqream sql --port=$STUCK_WORKER_IP --username=$SQREAM_USER --password=$SQREAM_PASSWORD databasename=$SQREAM_DATABASE + +3. Execute ``shutdown_server``. + +For more information, see the :ref:`shutdown_server_command` utility function. This page describes all of ``shutdown_server`` options. From 8c2d4dbcbdb41dbdf30fd8323215423fc6798e52 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Wed, 23 Jul 2025 12:00:12 +0300 Subject: [PATCH 1886/1892] Updated links --- configuration_guides/is_healer_on.rst | 2 +- feature_guides/query_healer.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configuration_guides/is_healer_on.rst b/configuration_guides/is_healer_on.rst index ba359ec36..633b14971 100644 --- a/configuration_guides/is_healer_on.rst +++ b/configuration_guides/is_healer_on.rst @@ -6,7 +6,7 @@ Is Healer On ************ -The ``is_healer_on`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``maxStatementInactivitySeconds`` flag setting. +The ``isHealerOn`` flag enables the Query Healer, which periodically examines the progress of running statements and logs statements exceeding the ``maxStatementInactivitySeconds`` flag setting. * **Data type** - boolean * **Default value** - ``true`` diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 9d0a92c09..7e16d3971 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -27,11 +27,11 @@ The following worker flags are required to configure the Query Healer. These are * - ``maxStatementInactivitySeconds`` - The :ref:`max_statement_inactivity_seconds` defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. If a statement did not make any progress during this time, it is considerd stuck. The default setting is five hours. * - ``healerRunActionAutomatically`` - - The healerRunActionAutomatically triggers the healer to take action once it detects a problem. In order for the healer to take an automatic correction action, this flag needs to be true, AND the flag that relates to the detected problem. The default setting is true. + - The :ref:'healer_run_action_automatically' triggers the healer to take action once it detects a problem. In order for the healer to take an automatic correction action, this flag needs to be true, AND the flag that relates to the detected problem. The default setting is true. * - ``healerActionGracefulShutdown`` - - The healerActionGracefulShutdown triggers the healer to restart a stuck worker automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is false. + - The :ref:'healer_action_graceful_shutdown' triggers the healer to restart a stuck worker automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is false. * - ``healerActionCleanupConnection`` - - The healerActionCleanupConnection triggers the healer to close a hung connection automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is true. + - The :ref:'healer_action_cleanup_connection' triggers the healer to close a hung connection automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is true. Query Log From 258dd15c18e9fe6628b2bea2ddee7b884e776536 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Wed, 23 Jul 2025 12:05:40 +0300 Subject: [PATCH 1887/1892] Update query_healer.rst --- feature_guides/query_healer.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index 7e16d3971..b1d5f2cd3 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -27,11 +27,11 @@ The following worker flags are required to configure the Query Healer. These are * - ``maxStatementInactivitySeconds`` - The :ref:`max_statement_inactivity_seconds` defines the threshold for creating a log recording a slow statement. The log includes information about the log memory, CPU and GPU. If a statement did not make any progress during this time, it is considerd stuck. The default setting is five hours. * - ``healerRunActionAutomatically`` - - The :ref:'healer_run_action_automatically' triggers the healer to take action once it detects a problem. In order for the healer to take an automatic correction action, this flag needs to be true, AND the flag that relates to the detected problem. The default setting is true. + - The :ref:`healer_run_action_automatically` triggers the healer to take action once it detects a problem. In order for the healer to take an automatic correction action, this flag needs to be true, AND the flag that relates to the detected problem. The default setting is true. * - ``healerActionGracefulShutdown`` - - The :ref:'healer_action_graceful_shutdown' triggers the healer to restart a stuck worker automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is false. + - The :ref:`healer_action_graceful_shutdown` triggers the healer to restart a stuck worker automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is false. * - ``healerActionCleanupConnection`` - - The :ref:'healer_action_cleanup_connection' triggers the healer to close a hung connection automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is true. + - The :ref:`healer_action_cleanup_connection` triggers the healer to close a hung connection automatically (both this flag AND healerRunActionAutomatically need to be true). The default setting is true. Query Log From a6f9b580ee9ade86fd5bca43262dd33eea945897 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Wed, 23 Jul 2025 12:26:33 +0300 Subject: [PATCH 1888/1892] Update query_healer.rst --- feature_guides/query_healer.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/feature_guides/query_healer.rst b/feature_guides/query_healer.rst index b1d5f2cd3..a619a4dbb 100644 --- a/feature_guides/query_healer.rst +++ b/feature_guides/query_healer.rst @@ -5,9 +5,9 @@ Query Healer ************ -The **Query Healer** periodically examines the progress of running statements and connections, creating a log entry for all statements exceeding a defined time period and connections with no data transfer over a specified time. +The **Query Healer** periodically examines the progress of running statements and connections, creating a log entry for all statements deemed stuck (exceeding a defined time period with no progress) and connections with no data transfer over a specified time. It can also take action based on its findings, for two issues - a stuck query or a hung connection. -The query healer runs on a separate thread on each worker, this is able to take action if the worker it is coupled with has a problem. +The query healer runs on a separate thread of each worker, enables it to take action if the worker it is on has a problem. Configuration ------------- From 5bcd7996a08e5ee7628ea60e0cb9fdedf1d584c1 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Fri, 22 Aug 2025 01:12:20 +0300 Subject: [PATCH 1889/1892] Update python_functions.rst --- feature_guides/python_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 62f193c49..15982096d 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -17,7 +17,7 @@ Before You Begin * Ensure you have Python 3.11 or newer installed -* Enable UDFs by setting the ``enablePythonUdfs`` configuration flag to ``true`` in your :ref:`legacy configuration file<current_method_modification_methods>` +* Note - This feature is about to be depracated on Q4 2025, and replaced by a better one. It is advisable to wait for the newer version if you do not use it yet. SQreamDB's UDF Support ============================= From c9a2bc14a850fef36b5dde442e30543d259ed6e3 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Fri, 22 Aug 2025 01:23:55 +0300 Subject: [PATCH 1890/1892] Update python_functions.rst --- feature_guides/python_functions.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 15982096d..61dd9c8f3 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -6,7 +6,6 @@ Python User-Defined Functions User-Defined Functions (UDFs) offer streamlined statements, enabling the creation of a function once, storing it in the database, and calling it multiple times within a statement. Additionally, UDFs can be shared among roles, created by a database administrator and utilized by others. Furthermore, they contribute to code simplicity by allowing independent modifications in SQream DB without altering program source code. -To enable UDFs, in your :ref:`legacy configuration file<current_method_modification_methods>`, set the ``enablePythonUdfs`` configuration flag to ``true``. .. contents:: :local: From 220b5ba72cc59fea7c0b2b8668088b1a491772dd Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Sun, 24 Aug 2025 13:13:04 +0300 Subject: [PATCH 1891/1892] Update python_functions.rst --- feature_guides/python_functions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature_guides/python_functions.rst b/feature_guides/python_functions.rst index 61dd9c8f3..4df1a1eaa 100644 --- a/feature_guides/python_functions.rst +++ b/feature_guides/python_functions.rst @@ -16,7 +16,7 @@ Before You Begin * Ensure you have Python 3.11 or newer installed -* Note - This feature is about to be depracated on Q4 2025, and replaced by a better one. It is advisable to wait for the newer version if you do not use it yet. +.. note:: This feature is deprecated on Q3 2025, and would be replaced by an enhanced implementation. Please consult SQream support for usage. SQreamDB's UDF Support ============================= From a485e318d33a355f7b57109ab79d394f1f3d0af9 Mon Sep 17 00:00:00 2001 From: sharonl-sqreamtech <sharonl@sqreamtech.com> Date: Wed, 3 Sep 2025 14:19:26 +0300 Subject: [PATCH 1892/1892] Update pre-installation_configurations.rst --- installation_guides/pre-installation_configurations.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installation_guides/pre-installation_configurations.rst b/installation_guides/pre-installation_configurations.rst index 3036d1257..8a04f7c82 100644 --- a/installation_guides/pre-installation_configurations.rst +++ b/installation_guides/pre-installation_configurations.rst @@ -93,7 +93,7 @@ Before You Begin * Once the BIOS settings have been set, you must install the operating system. -* A SQreamDB installation requires RHEL8.8/8.9 +* Make sure you use a supported OS version as listed on the release notes of the installed version. * Verify the exact RHEL8 version with your storage vendor to avoid driver incompatibility.